Changeset 734
- Timestamp:
- 11/28/07 05:03:31 (16 years ago)
- Files:
-
- trunk/libffado/config.h.in (modified) (2 diffs)
- trunk/libffado/deb (copied) (copied from branches/ppalmers-streaming/deb)
- trunk/libffado/libffado/ffado.h (modified) (1 diff)
- trunk/libffado/SConstruct (modified) (9 diffs)
- trunk/libffado/src/bebob/bebob_avdevice.h (modified) (1 diff)
- trunk/libffado/src/bebob/bebob_avdevice_subunit.cpp (modified) (5 diffs)
- trunk/libffado/src/bebob/bebob_functionblock.cpp (modified) (3 diffs)
- trunk/libffado/src/bebob/bebob_functionblock.h (modified) (2 diffs)
- trunk/libffado/src/bounce/bounce_avdevice.h (modified) (1 diff)
- trunk/libffado/src/bounce/bounce_slave_avdevice.cpp (modified) (1 diff)
- trunk/libffado/src/debugmodule/debugmodule.cpp (modified) (6 diffs)
- trunk/libffado/src/debugmodule/debugmodule.h (modified) (3 diffs)
- trunk/libffado/src/devicemanager.cpp (modified) (1 diff)
- trunk/libffado/src/devicemanager.h (modified) (1 diff)
- trunk/libffado/src/dice/dice_avdevice.cpp (modified) (5 diffs)
- trunk/libffado/src/dice/dice_avdevice.h (modified) (1 diff)
- trunk/libffado/src/ffadodevice.cpp (modified) (1 diff)
- trunk/libffado/src/ffado_streaming.cpp (modified) (5 diffs)
- trunk/libffado/src/genericavc/avc_avdevice.cpp (modified) (4 diffs)
- trunk/libffado/src/genericavc/avc_avdevice.h (modified) (1 diff)
- trunk/libffado/src/libavc/audiosubunit/avc_audiosubunit.h (modified) (1 diff)
- trunk/libffado/src/libavc/descriptors/avc_descriptor.cpp (modified) (5 diffs)
- trunk/libffado/src/libavc/descriptors/avc_descriptor.h (modified) (1 diff)
- trunk/libffado/src/libavc/descriptors/avc_descriptor_cmd.cpp (modified) (1 diff)
- trunk/libffado/src/libavc/general/avc_plug.cpp (modified) (5 diffs)
- trunk/libffado/src/libavc/general/avc_plug.h (modified) (5 diffs)
- trunk/libffado/src/libavc/general/avc_subunit.cpp (modified) (7 diffs)
- trunk/libffado/src/libavc/general/avc_subunit.h (modified) (2 diffs)
- trunk/libffado/src/libavc/general/avc_unit.cpp (modified) (3 diffs)
- trunk/libffado/src/libavc/musicsubunit/avc_musicsubunit.cpp (modified) (10 diffs)
- trunk/libffado/src/libieee1394/configrom.cpp (modified) (3 diffs)
- trunk/libffado/src/libosc (deleted)
- trunk/libffado/src/libstreaming/amdtp (copied) (copied from branches/ppalmers-streaming/src/libstreaming/amdtp)
- trunk/libffado/src/libstreaming/AmdtpPort.cpp (deleted)
- trunk/libffado/src/libstreaming/AmdtpPort.h (deleted)
- trunk/libffado/src/libstreaming/AmdtpPortInfo.cpp (deleted)
- trunk/libffado/src/libstreaming/AmdtpPortInfo.h (deleted)
- trunk/libffado/src/libstreaming/AmdtpSlaveStreamProcessor.cpp (deleted)
- trunk/libffado/src/libstreaming/AmdtpSlaveStreamProcessor.h (deleted)
- trunk/libffado/src/libstreaming/AmdtpStreamProcessor.cpp (deleted)
- trunk/libffado/src/libstreaming/AmdtpStreamProcessor.h (deleted)
- trunk/libffado/src/libstreaming/cip.c (deleted)
- trunk/libffado/src/libstreaming/cip.h (deleted)
- trunk/libffado/src/libstreaming/cycletimer.h (deleted)
- trunk/libffado/src/libstreaming/generic (copied) (copied from branches/ppalmers-streaming/src/libstreaming/generic)
- trunk/libffado/src/libstreaming/IsoHandler.cpp (deleted)
- trunk/libffado/src/libstreaming/IsoHandler.h (deleted)
- trunk/libffado/src/libstreaming/IsoHandlerManager.cpp (deleted)
- trunk/libffado/src/libstreaming/IsoHandlerManager.h (deleted)
- trunk/libffado/src/libstreaming/IsoStream.cpp (deleted)
- trunk/libffado/src/libstreaming/IsoStream.h (deleted)
- trunk/libffado/src/libstreaming/motu (copied) (copied from branches/ppalmers-streaming/src/libstreaming/motu)
- trunk/libffado/src/libstreaming/MotuPort.cpp (deleted)
- trunk/libffado/src/libstreaming/MotuPort.h (deleted)
- trunk/libffado/src/libstreaming/MotuPortInfo.cpp (deleted)
- trunk/libffado/src/libstreaming/MotuPortInfo.h (deleted)
- trunk/libffado/src/libstreaming/MotuStreamProcessor.cpp (deleted)
- trunk/libffado/src/libstreaming/MotuStreamProcessor.h (deleted)
- trunk/libffado/src/libstreaming/Port.cpp (deleted)
- trunk/libffado/src/libstreaming/Port.h (deleted)
- trunk/libffado/src/libstreaming/PortManager.cpp (deleted)
- trunk/libffado/src/libstreaming/PortManager.h (deleted)
- trunk/libffado/src/libstreaming/StreamProcessor.cpp (deleted)
- trunk/libffado/src/libstreaming/StreamProcessor.h (deleted)
- trunk/libffado/src/libstreaming/StreamProcessorManager.cpp (modified) (24 diffs)
- trunk/libffado/src/libstreaming/StreamProcessorManager.h (modified) (7 diffs)
- trunk/libffado/src/libstreaming/util (copied) (copied from branches/ppalmers-streaming/src/libstreaming/util)
- trunk/libffado/src/libutil/StreamStatistics.cpp (modified) (4 diffs)
- trunk/libffado/src/libutil/StreamStatistics.h (modified) (3 diffs)
- trunk/libffado/src/libutil/TimestampedBuffer.cpp (modified) (26 diffs)
- trunk/libffado/src/libutil/TimestampedBuffer.h (modified) (1 diff)
- trunk/libffado/src/maudio/maudio_avdevice.h (modified) (1 diff)
- trunk/libffado/src/metrichalo/mh_avdevice.h (modified) (1 diff)
- trunk/libffado/src/motu/motu_avdevice.cpp (modified) (3 diffs)
- trunk/libffado/src/motu/motu_avdevice.h (modified) (1 diff)
- trunk/libffado/src/rme/rme_avdevice.h (modified) (1 diff)
- trunk/libffado/src/SConscript (modified) (5 diffs)
- trunk/libffado/support/dbus (copied) (copied from branches/ppalmers-streaming/support/dbus)
- trunk/libffado/support/firmware/SConscript (modified) (2 diffs)
- trunk/libffado/support/SConscript (modified) (1 diff)
- trunk/libffado/tests/control-interface.xml (deleted)
- trunk/libffado/tests/controlclient.cpp (deleted)
- trunk/libffado/tests/controlclient.h (deleted)
- trunk/libffado/tests/controlserver.cpp (deleted)
- trunk/libffado/tests/controlserver.h (deleted)
- trunk/libffado/tests/SConscript (modified) (3 diffs)
- trunk/libffado/tests/streaming/test-isohandling.cpp (modified) (1 diff)
- trunk/libffado/tests/SytMonitor.cpp (modified) (2 diffs)
- trunk/libffado/tests/SytMonitor.h (modified) (1 diff)
- trunk/libffado/tests/test-cycletimer.cpp (modified) (3 diffs)
- trunk/libffado/tests/test-dbus-server.cpp (deleted)
- trunk/libffado/tests/test-dbus.cpp (deleted)
- trunk/libffado/tests/test-ffado.cpp (modified) (4 diffs)
- trunk/libffado/tests/test-sytmonitor.cpp (modified) (2 diffs)
- trunk/libffado/tests/test-timestampedbuffer.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/libffado/config.h.in
r609 r734 13 13 14 14 /* Define to the full name and version of this package. */ 15 #define PACKAGE_STRING "$PACKAGE $VERSION "15 #define PACKAGE_STRING "$PACKAGE $VERSION-$REVISION" 16 16 17 17 /* Define to the one symbol short name of this package. */ … … 19 19 20 20 /* Define to the version of this package. */ 21 #define PACKAGE_VERSION $VERSION21 #define PACKAGE_VERSION "$VERSION-$REVISION" 22 22 23 23 /* Define to 1 if SSE assembly is available. */ 24 24 /*#define USE_SSE 1*/ 25 26 /* Version number of package */27 #define VERSION "$VERSION"28 25 29 26 #define CACHEDIR "~/.ffado" trunk/libffado/libffado/ffado.h
r453 r734 145 145 typedef struct ffado_device_info { 146 146 /* TODO: How is the device specification done? */ 147 // char xml_location[FFADO_STREAMING_MAX_URL_LENGTH]; // can be an osc url or an XML filename148 147 // ffado_device_info_location_type location_type; 149 148 } ffado_device_info_t; trunk/libffado/SConstruct
r718 r734 62 62 buildenv['PKG_CONFIG_PATH']='' 63 63 64 if os.environ.has_key('LD_LIBRARY_PATH'):65 buildenv['LD_LIBRARY_PATH']=os.environ['LD_LIBRARY_PATH']66 else:67 buildenv['LD_LIBRARY_PATH']=''68 69 64 70 65 env = Environment( tools=['default','scanreplace','pyuic','dbus','doxygen','pkgconfig'], toolpath=['admin'], ENV = buildenv, options=opts ) … … 97 92 opts.Save( 'cache/' + build_base + "options.cache", env ) 98 93 99 100 tests = {} 94 # 95 # Check for apps... 96 # 97 def CheckForApp( context, app ): 98 context.Message( "Checking if '%s' executes... " % app ) 99 ret = context.env.WhereIs( app ) 100 if ret != "": 101 context.Result( True ) 102 else: 103 context.Result( False ) 104 return ret 105 106 tests = { 'CheckForApp' : CheckForApp } 101 107 tests.update( env['PKGCONFIG_TESTS'] ) 102 108 … … 130 136 'alsa' : '1.0.0', 131 137 'libxml++-2.6' : '2.13.0', 132 'liblo' : '0.22',133 138 'dbus-1' : '1.0', 134 139 } … … 149 154 # Optional checks follow: 150 155 # 156 env['PYUIC'] = conf.CheckForApp( 'pyuic' ) 151 157 env['ALSA_SEQ_OUTPUT'] = conf.CheckLib( 'asound', symbol='snd_seq_event_output_direct', autoadd=0 ) 152 158 … … 158 164 env.AppendUnique( CCFLAGS=["-DDEBUG","-Wall","-g"] ) 159 165 else: 160 env.AppendUnique( CCFLAGS=["-O2" ] )166 env.AppendUnique( CCFLAGS=["-O2","-DNDEBUG"] ) 161 167 162 168 # this is required to indicate that the DBUS version we use has support … … 191 197 env['sharedir'] = Template( os.path.join( env['SHAREDIR'] ) ).safe_substitute( env ) 192 198 193 env.Command( target=env['sharedir'], source="", action=Mkdir( env['sharedir'] ) )194 195 199 env.Alias( "install", env['libdir'] ) 196 200 env.Alias( "install", env['includedir'] ) … … 198 202 env.Alias( "install", env['bindir'] ) 199 203 204 205 env['REVISION'] = os.popen('svnversion .').read()[:-1] 206 # This may be as simple as '89' or as complex as '4123:4184M'. 207 # We'll just use the last bit. 208 env['REVISION'] = env['REVISION'].split(':')[-1] 209 210 if env['REVISION'] == 'exported': 211 env['REVISION'] = '' 212 200 213 env['PACKAGE'] = "libffado" 201 env['VERSION'] = "1.999. 6"214 env['VERSION'] = "1.999.7" 202 215 env['LIBVERSION'] = "1.0.0" 203 216 … … 210 223 # Start building 211 224 # 212 213 225 env.ScanReplace( "config.h.in" ) 214 226 … … 222 234 env.SConscript( dirs=subdirs, exports="env" ) 223 235 236 if 'debian' in COMMAND_LINE_TARGETS: 237 env.SConscript("deb/SConscript", exports="env") 224 238 225 239 # By default only src is built but all is cleaned trunk/libffado/src/bebob/bebob_avdevice.h
r661 r734 42 42 #include "bebob/bebob_mixer.h" 43 43 44 #include "libstreaming/AmdtpStreamProcessor.h" 45 #include "libstreaming/AmdtpPort.h" 46 #include "libstreaming/AmdtpPortInfo.h" 44 #include "libstreaming/amdtp/AmdtpReceiveStreamProcessor.h" 45 #include "libstreaming/amdtp/AmdtpTransmitStreamProcessor.h" 46 #include "libstreaming/amdtp/AmdtpPort.h" 47 #include "libstreaming/amdtp/AmdtpPortInfo.h" 47 48 48 49 #include "libutil/serialize.h" trunk/libffado/src/bebob/bebob_avdevice_subunit.cpp
r716 r734 82 82 { 83 83 debugOutput(DEBUG_LEVEL_NORMAL, "Discovering %s...\n", getName()); 84 84 85 85 // discover the AV/C generic part 86 86 if ( !AVC::SubunitAudio::discover() ) { … … 160 160 #ifdef DEBUG 161 161 if ((int)getDebugLevel() >= DEBUG_LEVEL_NORMAL) { 162 162 163 163 for ( FunctionBlockVector::iterator it = m_functions.begin(); 164 164 it != m_functions.end(); … … 340 340 bool 341 341 BeBoB::SubunitAudio::serializeChild( Glib::ustring basePath, 342 Util::IOSerialize& ser ) const342 Util::IOSerialize& ser ) const 343 343 { 344 344 bool result = true; … … 363 363 bool 364 364 BeBoB::SubunitAudio::deserializeChild( Glib::ustring basePath, 365 Util::IODeserialize& deser,366 AVC::Unit& avDevice )365 Util::IODeserialize& deser, 366 AVC::Unit& avDevice ) 367 367 { 368 368 int i = 0; … … 426 426 { 427 427 debugOutput(DEBUG_LEVEL_NORMAL, "Discovering %s...\n", getName()); 428 428 429 429 // discover the AV/C generic part 430 430 if ( !AVC::SubunitMusic::discover() ) { trunk/libffado/src/bebob/bebob_functionblock.cpp
r716 r734 160 160 161 161 bool 162 serializePlugVector( Glib::ustring basePath, 163 Util::IOSerialize& ser, 164 const PlugVector& vec ) 165 { 166 bool result = true; 167 int i = 0; 168 for ( PlugVector::const_iterator it = vec.begin(); 169 it != vec.end(); 170 ++it ) 171 { 172 std::ostringstream strstrm; 173 strstrm << basePath << i; 174 result &= ser.write( strstrm.str(), ( *it )->getGlobalId() ); 175 i++; 176 } 177 return result; 178 } 179 180 bool 181 deserializePlugVector( Glib::ustring basePath, 182 Util::IODeserialize& deser, 183 AVC::Unit& unit, 184 PlugVector& vec ) 185 { 186 int i = 0; 187 bool bFinished = false; 188 bool result = true; 189 do { 190 plug_id_t plugId; 191 std::ostringstream strstrm; 192 strstrm << basePath << i; 193 194 if ( deser.isExisting( strstrm.str() ) ) { 195 result &= deser.read( strstrm.str(), plugId ); 196 AVC::Plug* pPlug = unit.getPlugManager().getPlug( plugId ); 197 198 if ( result && pPlug ) { 199 vec.push_back( pPlug ); 200 i++; 201 } else { 202 bFinished = true; 203 } 204 } else { 205 bFinished = true; 206 } 207 } while ( !bFinished ); 208 209 return result; 210 } 211 212 bool 162 213 FunctionBlock::serialize( Glib::ustring basePath, Util::IOSerialize& ser ) const 163 214 { … … 178 229 FunctionBlock* 179 230 FunctionBlock::deserialize( Glib::ustring basePath, 180 Util::IODeserialize& deser,181 AVC::Unit& unit,182 AVC::Subunit& subunit )231 Util::IODeserialize& deser, 232 AVC::Unit& unit, 233 AVC::Subunit& subunit ) 183 234 { 184 235 bool result; … … 227 278 result &= deser.read( basePath + "m_nrOfOutputPlugs", pFB->m_nrOfOutputPlugs ); 228 279 result &= deser.read( basePath + "m_verbose", pFB->m_verbose ); 229 result &= deserializePlugVector( basePath + "m_plugs", deser, 230 unit.getPlugManager(), pFB->m_plugs ); 280 result &= deserializePlugVector( basePath + "m_plugs", deser, unit, pFB->m_plugs ); 231 281 232 282 return 0; trunk/libffado/src/bebob/bebob_functionblock.h
r716 r734 69 69 70 70 virtual const char* getName() = 0; 71 71 72 72 AVC::function_block_type_t getType() {return m_type;}; 73 73 AVC::function_block_type_t getSubtype() {return m_subtype;}; 74 74 AVC::function_block_id_t getId() {return m_id;}; 75 75 76 76 AVC::no_of_input_plugs_t getNrOfInputPlugs() {return m_nrOfInputPlugs;}; 77 77 AVC::no_of_output_plugs_t getNrOfOutputPlugs() {return m_nrOfOutputPlugs;}; 78 78 79 79 bool serialize( Glib::ustring basePath, Util::IOSerialize& ser ) const; 80 81 80 static FunctionBlock* deserialize( Glib::ustring basePath, 82 81 Util::IODeserialize& deser, … … 145 144 146 145 virtual const char* getName(); 147 146 148 147 // FIXME: this is not pretty! 149 148 enum EControlSelectorEncoding { trunk/libffado/src/bounce/bounce_avdevice.h
r639 r734 30 30 #include "libavc/general/avc_extended_cmd_generic.h" 31 31 32 #include "libstreaming/AmdtpStreamProcessor.h" 33 #include "libstreaming/AmdtpPort.h" 34 #include "libstreaming/AmdtpPortInfo.h" 32 #include "libstreaming/amdtp/AmdtpReceiveStreamProcessor.h" 33 #include "libstreaming/amdtp/AmdtpTransmitStreamProcessor.h" 34 #include "libstreaming/amdtp/AmdtpPort.h" 35 #include "libstreaming/amdtp/AmdtpPortInfo.h" 35 36 36 37 #include "libieee1394/ARMHandler.h" trunk/libffado/src/bounce/bounce_slave_avdevice.cpp
r587 r734 23 23 */ 24 24 25 #include "libstreaming/ AmdtpSlaveStreamProcessor.h"25 #include "libstreaming/amdtp/AmdtpSlaveStreamProcessor.h" 26 26 27 27 #include "libieee1394/configrom.h" trunk/libffado/src/debugmodule/debugmodule.cpp
r698 r734 35 35 36 36 #ifndef DO_MESSAGE_BUFFER_PRINT 37 37 #warning Printing debug info without ringbuffer, not RT-safe! 38 38 #endif 39 39 … … 46 46 47 47 ColorEntry colorTable[] = { 48 { "", "" }, 48 49 { "\033[31mFatal", "\033[0m" }, 49 50 { "\033[31mError", "\033[0m" }, … … 213 214 DebugModule::getPreSequence( debug_level_t level ) const 214 215 { 215 if ( ( level <= eDL_Normal ) && ( level >= eDL_ Fatal) ) {216 if ( ( level <= eDL_Normal ) && ( level >= eDL_Message ) ) { 216 217 return colorTable[level].preSequence; 217 218 } … … 222 223 DebugModule::getPostSequence( debug_level_t level ) const 223 224 { 224 if ( ( level <= eDL_Normal ) && ( level >= eDL_ Fatal) ) {225 if ( ( level <= eDL_Normal ) && ( level >= eDL_Message ) ) { 225 226 return colorTable[level].postSequence; 226 227 } … … 428 429 for (unsigned int i=0; i<BACKLOG_MB_BUFFERS;i++) { 429 430 unsigned int idx=(i+bl_mb_inbuffer)%BACKLOG_MB_BUFFERS; 431 fputs("BL: ", stderr); 430 432 fputs(bl_mb_buffers[idx], stderr); 431 433 } 432 fprintf(stderr, " \n");434 fprintf(stderr, "BL: \n"); 433 435 434 436 fprintf(stderr, "=====================================================\n"); … … 454 456 if (lines_to_skip-- < 0) { 455 457 unsigned int idx=(i+bl_mb_inbuffer)%BACKLOG_MB_BUFFERS; 458 fputs("BL: ", stderr); 456 459 fputs(bl_mb_buffers[idx], stderr); 457 460 } 458 461 } 459 fprintf(stderr, " \n");462 fprintf(stderr, "BL: \n"); 460 463 461 464 fprintf(stderr, "=====================================================\n"); trunk/libffado/src/debugmodule/debugmodule.h
r698 r734 34 34 typedef short debug_level_t; 35 35 36 #define DEBUG_LEVEL_FATAL 0 37 #define DEBUG_LEVEL_ERROR 1 38 #define DEBUG_LEVEL_WARNING 2 39 #define DEBUG_LEVEL_NORMAL 3 40 #define DEBUG_LEVEL_INFO 4 41 #define DEBUG_LEVEL_VERBOSE 5 42 #define DEBUG_LEVEL_VERY_VERBOSE 6 43 #define DEBUG_LEVEL_ULTRA_VERBOSE 7 36 #define DEBUG_LEVEL_MESSAGE 0 37 #define DEBUG_LEVEL_FATAL 1 38 #define DEBUG_LEVEL_ERROR 2 39 #define DEBUG_LEVEL_WARNING 3 40 #define DEBUG_LEVEL_NORMAL 4 41 #define DEBUG_LEVEL_INFO 5 42 #define DEBUG_LEVEL_VERBOSE 6 43 #define DEBUG_LEVEL_VERY_VERBOSE 7 44 #define DEBUG_LEVEL_ULTRA_VERBOSE 8 44 45 45 46 #define DEBUG_MAX_MESSAGE_LENGTH 512 … … 95 96 ##args ) 96 97 98 // these are for messages that are also displayed when not compiled 99 // for debug 100 #define printMessage( format, args... ) \ 101 m_debugModule.print( DebugModule::eDL_Message, \ 102 __FILE__, \ 103 __FUNCTION__, \ 104 __LINE__, \ 105 format, \ 106 ##args ) 107 #define printMessageShort( format, args... ) \ 108 m_debugModule.printShort( DebugModule::eDL_Message, \ 109 format, \ 110 ##args ) 111 97 112 #define DECLARE_DEBUG_MODULE static DebugModule m_debugModule 98 113 #define IMPL_DEBUG_MODULE( ClassName, RegisterName, Level ) \ … … 182 197 public: 183 198 enum { 199 eDL_Message = DEBUG_LEVEL_MESSAGE, 184 200 eDL_Fatal = DEBUG_LEVEL_FATAL, 185 201 eDL_Error = DEBUG_LEVEL_ERROR, trunk/libffado/src/devicemanager.cpp
r674 r734 31 31 #include "libieee1394/ieee1394service.h" 32 32 33 #include "libstreaming/ StreamProcessor.h"33 #include "libstreaming/generic/StreamProcessor.h" 34 34 35 35 #include "debugmodule/debugmodule.h" trunk/libffado/src/devicemanager.h
r674 r734 32 32 33 33 #include "libutil/OptionContainer.h" 34 // #include "libosc/OscServer.h"35 // #include "libosc/OscNode.h"36 34 #include "libcontrol/BasicElements.h" 37 35 trunk/libffado/src/dice/dice_avdevice.cpp
r672 r734 28 28 #include "libieee1394/ieee1394service.h" 29 29 30 #include "libstreaming/AmdtpStreamProcessor.h"31 32 30 #include "debugmodule/debugmodule.h" 33 31 … … 51 49 // vendor id, model id, vendor name, model name 52 50 {FW_VENDORID_TCAT, 0x00000002, "TCAT", "DiceII EVM"}, 51 {FW_VENDORID_TCAT, 0x00000004, "TCAT", "DiceII EVM (vxx)"}, 53 52 }; 54 53 … … 448 447 bool 449 448 DiceAvDevice::prepare() { 450 int samplerate=getSamplingFrequency();451 452 449 // prepare receive SP's 453 450 for (unsigned int i=0;i<m_nb_tx;i++) { … … 494 491 p=new Streaming::AmdtpReceiveStreamProcessor( 495 492 m_p1394Service->getPort(), 496 samplerate,497 493 nb_channels); 498 494 … … 581 577 p=new Streaming::AmdtpTransmitStreamProcessor( 582 578 m_p1394Service->getPort(), 583 samplerate,584 579 nb_channels); 585 580 trunk/libffado/src/dice/dice_avdevice.h
r639 r734 30 30 #include "libavc/avc_definitions.h" 31 31 32 #include "libstreaming/AmdtpStreamProcessor.h" 33 #include "libstreaming/AmdtpPort.h" 32 #include "libstreaming/amdtp/AmdtpReceiveStreamProcessor.h" 33 #include "libstreaming/amdtp/AmdtpTransmitStreamProcessor.h" 34 #include "libstreaming/amdtp/AmdtpPort.h" 34 35 #include "libieee1394/ARMHandler.h" 35 36 trunk/libffado/src/ffadodevice.cpp
r674 r734 118 118 119 119 retval=setOption("id",idstr.str()); 120 /* if (retval) {121 setOscBase(idstr.str());122 }*/123 120 return retval; 124 121 } trunk/libffado/src/ffado_streaming.cpp
r554 r734 76 76 } 77 77 78 dev->m_deviceManager->setVerboseLevel(DEBUG_LEVEL_ VERBOSE);78 dev->m_deviceManager->setVerboseLevel(DEBUG_LEVEL_NORMAL); 79 79 if ( !dev->m_deviceManager->initialize( dev->options.port ) ) { 80 80 debugFatal( "Could not initialize device manager\n" ); … … 86 86 // create a processor manager to manage the actual stream 87 87 // processors 88 dev->processorManager = new StreamProcessorManager(dev->options.period_size,dev->options.nb_buffers); 88 dev->processorManager = new StreamProcessorManager( dev->options.period_size, 89 dev->options.sample_rate, 90 dev->options.nb_buffers); 89 91 if(!dev->processorManager) { 90 92 debugFatal("Could not create StreamProcessorManager\n"); … … 170 172 // prepare the device 171 173 device->prepare(); 172 173 174 int j=0; 174 175 for(j=0; j<device->getStreamCount();j++) { … … 176 177 debugOutput(DEBUG_LEVEL_VERBOSE, "Registering stream processor %d of device %d with processormanager\n",j,i); 177 178 if (!dev->processorManager->registerProcessor(streamproc)) { 178 debugWarning("Could not register stream processor (%p) with the Processor manager\n",streamproc); 179 delete dev->processorManager; 180 delete dev->m_deviceManager; 181 delete dev; 182 debugFatal("Could not register stream processor (%p) with the Processor manager\n", streamproc); 183 return 0; 179 184 } 180 185 } … … 331 336 332 337 int ffado_streaming_transfer_capture_buffers(ffado_device_t *dev) { 333 return dev->processorManager->transfer(StreamProcessor:: E_Receive);338 return dev->processorManager->transfer(StreamProcessor::ePT_Receive); 334 339 } 335 340 336 341 int ffado_streaming_transfer_playback_buffers(ffado_device_t *dev) { 337 return dev->processorManager->transfer(StreamProcessor:: E_Transmit);342 return dev->processorManager->transfer(StreamProcessor::ePT_Transmit); 338 343 } 339 344 trunk/libffado/src/genericavc/avc_avdevice.cpp
r716 r734 236 236 bool found=false; 237 237 for ( PlugVector::const_iterator it2 = syncMSUInputPlugs.begin(); 238 239 238 it2 != syncMSUInputPlugs.end(); 239 ++it2 ) 240 240 { 241 241 AVC::Plug* msuPlug = *it2; … … 422 422 } 423 423 424 int samplerate=outputPlug->getSampleRate();425 426 424 debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing receive processor...\n"); 427 425 // create & add streamprocessors 428 426 Streaming::StreamProcessor *p; 429 427 428 if ( outputPlug->getNrOfChannels() == 0 ) { 429 debugError("Receive plug has no channels\n"); 430 return false; 431 } 430 432 p=new Streaming::AmdtpReceiveStreamProcessor( 431 433 get1394Service().getPort(), 432 samplerate,433 434 outputPlug->getNrOfChannels()); 434 435 … … 455 456 p=new Streaming::AmdtpReceiveStreamProcessor( 456 457 get1394Service().getPort(), 457 samplerate,458 458 inputPlug->getNrOfChannels()); 459 459 } else { 460 460 p=new Streaming::AmdtpTransmitStreamProcessor( 461 461 get1394Service().getPort(), 462 samplerate,463 462 inputPlug->getNrOfChannels()); 464 463 } … … 596 595 AvDevice::getStreamCount() { 597 596 return m_receiveProcessors.size() + m_transmitProcessors.size(); 597 //return 1; 598 598 } 599 599 trunk/libffado/src/genericavc/avc_avdevice.h
r639 r734 34 34 #include "libavc/general/avc_plug.h" 35 35 36 #include "libstreaming/AmdtpStreamProcessor.h" 37 #include "libstreaming/AmdtpPort.h" 38 #include "libstreaming/AmdtpPortInfo.h" 36 #include "libstreaming/amdtp/AmdtpReceiveStreamProcessor.h" 37 #include "libstreaming/amdtp/AmdtpTransmitStreamProcessor.h" 38 #include "libstreaming/amdtp/AmdtpPort.h" 39 #include "libstreaming/amdtp/AmdtpPortInfo.h" 39 40 40 41 #include "debugmodule/debugmodule.h" trunk/libffado/src/libavc/audiosubunit/avc_audiosubunit.h
r716 r734 52 52 protected: 53 53 virtual bool serializeChild( Glib::ustring basePath, 54 Util::IOSerialize& ser ) const { return true; }54 Util::IOSerialize& ser ) const {return false;}; 55 55 virtual bool deserializeChild( Glib::ustring basePath, 56 56 Util::IODeserialize& deser, 57 Unit& avDevice ) { return true; }57 Unit& avDevice ) {return false;}; 58 58 59 59 }; trunk/libffado/src/libavc/descriptors/avc_descriptor.cpp
r626 r734 146 146 AVCDescriptor::reload() 147 147 { 148 m_loaded =false;148 m_loaded = false; 149 149 return load(); 150 150 } … … 178 178 } 179 179 180 debugOutput(DEBUG_LEVEL_VERBOSE, " Read statusdescriptor\n");180 debugOutput(DEBUG_LEVEL_VERBOSE, " Read descriptor\n"); 181 181 ReadDescriptorCmd readDescCmd(m_unit->get1394Service()); 182 182 readDescCmd.m_specifier=&m_specifier; … … 199 199 if (bytes_read < 2) { 200 200 debugOutput(DEBUG_LEVEL_VERBOSE, " Descriptor length field not present\n"); 201 return false; 202 } 203 201 return false; 202 } 203 204 #ifdef DEBUG 205 if(getDebugLevel() >= DEBUG_LEVEL_VERY_VERBOSE) { 206 debugOutput(DEBUG_LEVEL_VERBOSE, " Read result:\n"); 207 printBufferBytes( DEBUG_LEVEL_VERY_VERBOSE, bytes_read, readDescCmd.m_data ); 208 } 209 #endif 210 204 211 // obtain descriptor length 205 212 m_descriptor_length=(readDescCmd.m_data[0]<<8) + (readDescCmd.m_data[1]); … … 274 281 return false; 275 282 } 276 283 #ifdef DEBUG 284 if(getDebugLevel() >= DEBUG_LEVEL_VERY_VERBOSE) { 285 debugOutput(DEBUG_LEVEL_VERBOSE, " Descriptor content:\n"); 286 printBufferBytes( DEBUG_LEVEL_VERY_VERBOSE, m_descriptor_length, m_data ); 287 } 288 #endif 277 289 debugOutput(DEBUG_LEVEL_VERBOSE, " Parse descriptor\n"); 278 290 // parse the descriptor … … 347 359 } 348 360 361 void 362 AVCDescriptor::printBufferBytes( unsigned int level, size_t length, byte_t* buffer ) const 363 { 364 365 for ( unsigned int i=0; i < length; ++i ) { 366 if ( ( i % 16 ) == 0 ) { 367 if ( i > 0 ) { 368 debugOutputShort(level,"\n"); 369 } 370 debugOutputShort(level," %4d: ",i*16); 371 } 372 debugOutputShort(level,"%02X ",buffer[i]); 373 } 374 debugOutputShort(level,"\n"); 375 } 376 349 377 // --- Info block 350 378 AVCInfoBlock::AVCInfoBlock( ) trunk/libffado/src/libavc/descriptors/avc_descriptor.h
r618 r734 137 137 138 138 protected: 139 void printBufferBytes(unsigned int level, size_t length, byte_t* buffer) const; 139 140 140 141 Unit* m_unit; trunk/libffado/src/libavc/descriptors/avc_descriptor_cmd.cpp
r618 r734 179 179 return false; 180 180 } 181 return true;182 181 return true; 183 182 } trunk/libffado/src/libavc/general/avc_plug.cpp
r716 r734 1576 1576 } 1577 1577 1578 1579 bool 1580 Plug::serializePlugVector( Glib::ustring basePath, 1581 Util::IOSerialize& ser, 1582 const PlugVector& vec) const 1583 { 1584 bool result = true; 1585 int i = 0; 1586 for ( PlugVector::const_iterator it = vec.begin(); 1587 it != vec.end(); 1588 ++it ) 1589 { 1590 const Plug* pPlug = *it; 1591 std::ostringstream strstrm; 1592 strstrm << basePath << i; 1593 1594 result &= ser.write( strstrm.str() + "/global_id", pPlug->getGlobalId() ); 1595 i++; 1596 } 1597 return result; 1598 } 1599 1600 bool 1601 Plug::deserializePlugVector( Glib::ustring basePath, 1602 Util::IODeserialize& deser, 1603 PlugVector& vec ) 1604 { 1605 int i = 0; 1606 bool bFinished = false; 1607 bool result = true; 1608 do { 1609 std::ostringstream strstrm; 1610 strstrm << basePath << i; 1611 1612 // check for one element to exist. when one exist the other elements 1613 // must also be there. otherwise just return (last) result. 1614 if ( deser.isExisting( strstrm.str() + "/global_id" ) ) { 1615 unsigned int iPlugId; 1616 result &= deser.read( strstrm.str() + "/global_id", iPlugId ); 1617 1618 if ( result ) { 1619 Plug* pPlug = m_unit->getPlugManager().getPlug( iPlugId ); 1620 if ( pPlug ) { 1621 vec.push_back( pPlug ); 1622 } else { 1623 result = false; 1624 bFinished = true; 1625 } 1626 i++; 1627 } else { 1628 bFinished = true; 1629 } 1630 } else { 1631 bFinished = true; 1632 } 1633 } while ( !bFinished ); 1634 1635 return result; 1636 } 1637 1578 1638 bool 1579 1639 Plug::serialize( Glib::ustring basePath, Util::IOSerialize& ser ) const … … 1623 1683 bool result=true; 1624 1684 1625 result = deser.read( basePath + "m_subunitType", pPlug->m_subunitType ); 1626 result &= deser.read( basePath + "m_subunitId", pPlug->m_subunitId ); 1685 ESubunitType subunitType; 1686 result = deser.read( basePath + "m_subunitType", subunitType ); 1687 subunit_t subunitId; 1688 result &= deser.read( basePath + "m_subunitId", subunitId ); 1689 pPlug->m_subunit = unit.getSubunit( subunitType, subunitType ); 1690 1627 1691 result &= deser.read( basePath + "m_functionBlockType", pPlug->m_functionBlockType ); 1628 1692 result &= deser.read( basePath + "m_functionBlockId", pPlug->m_functionBlockId ); … … 1654 1718 bool 1655 1719 Plug::deserializeUpdate( Glib::ustring basePath, 1656 Util::IODeserialize& deser )1720 Util::IODeserialize& deser ) 1657 1721 { 1658 1722 bool result; 1659 1723 1660 result = deserializePlugVector( basePath + "m_inputConnections", deser, 1661 m_unit->getPlugManager(), m_inputConnections ); 1662 result &= deserializePlugVector( basePath + "m_outputConnections", deser, 1663 m_unit->getPlugManager(), m_outputConnections ); 1724 result = deserializePlugVector( basePath + "m_inputConnections", deser, m_inputConnections ); 1725 result &= deserializePlugVector( basePath + "m_outputConnections", deser, m_outputConnections ); 1664 1726 1665 1727 return result; 1666 }1667 1668 bool1669 Plug::deserializeUpdateSubunit()1670 {1671 m_subunit = m_unit->getSubunit( m_subunitType, m_subunitId );1672 return true;1673 1728 } 1674 1729 … … 2150 2205 } 2151 2206 2152 bool2153 PlugManager::deserializeUpdate()2154 {2155 bool result = true;2156 2157 for ( PlugVector::const_iterator it = m_plugs.begin();2158 it != m_plugs.end();2159 ++it )2160 {2161 Plug* pPlug = *it;2162 2163 result &= pPlug->deserializeUpdateSubunit();2164 }2165 2166 return result;2167 }2168 2207 2169 2208 //////////////////////////////////// … … 2300 2339 } 2301 2340 2302 bool 2303 serializePlugVector( Glib::ustring basePath, 2304 Util::IOSerialize& ser, 2305 const PlugVector& vec) 2306 { 2307 bool result = true; 2308 int i = 0; 2309 for ( PlugVector::const_iterator it = vec.begin(); 2310 it != vec.end(); 2311 ++it ) 2312 { 2313 const Plug* pPlug = *it; 2314 std::ostringstream strstrm; 2315 strstrm << basePath << i; 2316 2317 result &= ser.write( strstrm.str() + "/global_id", pPlug->getGlobalId() ); 2318 i++; 2319 } 2320 return result; 2321 } 2322 2323 bool 2324 deserializePlugVector( Glib::ustring basePath, 2325 Util::IODeserialize& deser, 2326 const PlugManager& plugManager, 2327 PlugVector& vec ) 2328 { 2329 int i = 0; 2330 bool bFinished = false; 2331 bool result = true; 2332 do { 2333 std::ostringstream strstrm; 2334 strstrm << basePath << i; 2335 2336 // check for one element to exist. when one exist the other elements 2337 // must also be there. otherwise just return (last) result. 2338 if ( deser.isExisting( strstrm.str() + "/global_id" ) ) { 2339 unsigned int iPlugId; 2340 result &= deser.read( strstrm.str() + "/global_id", iPlugId ); 2341 2342 if ( result ) { 2343 Plug* pPlug = plugManager.getPlug( iPlugId ); 2344 if ( pPlug ) { 2345 vec.push_back( pPlug ); 2346 } else { 2347 result = false; 2348 bFinished = true; 2349 } 2350 i++; 2351 } else { 2352 bFinished = true; 2353 } 2354 } else { 2355 bFinished = true; 2356 } 2357 } while ( !bFinished ); 2358 2359 return result; 2360 } 2361 2362 } 2341 } trunk/libffado/src/libavc/general/avc_plug.h
r716 r734 163 163 bool deserializeUpdate( Glib::ustring basePath, 164 164 Util::IODeserialize& deser ); 165 bool deserializeUpdateSubunit();166 165 167 166 public: … … 257 256 bool deserializeFormatInfos( Glib::ustring basePath, 258 257 Util::IODeserialize& deser ); 258 259 bool serializePlugVector( Glib::ustring basePath, 260 Util::IOSerialize& ser, 261 const PlugVector& vec) const; 262 bool deserializePlugVector( Glib::ustring basePath, 263 Util::IODeserialize& deser, 264 PlugVector& vec ); 259 265 260 266 protected: … … 279 285 Unit* m_unit; 280 286 Subunit* m_subunit; 281 ESubunitType m_subunitType;282 subunit_t m_subunitId;283 287 function_block_type_t m_functionBlockType; 284 288 function_block_id_t m_functionBlockId; … … 345 349 bool tidyPlugConnections(PlugConnectionVector&); 346 350 347 bool deserializeUpdate();348 349 351 private: 350 352 … … 377 379 typedef std::vector<PlugConnection> PlugConnectionOwnerVector; 378 380 379 380 bool serializePlugVector( Glib::ustring basePath,381 Util::IOSerialize& ser,382 const PlugVector& vec);383 384 bool deserializePlugVector( Glib::ustring basePath,385 Util::IODeserialize& deser,386 const PlugManager& plugManager,387 PlugVector& vec );388 389 381 } 390 382 trunk/libffado/src/libavc/general/avc_subunit.cpp
r716 r734 107 107 { 108 108 debugOutput(DEBUG_LEVEL_NORMAL, "Discovering plugs...\n"); 109 109 110 110 PlugInfoCmd plugInfoCmd( getUnit().get1394Service(), 111 111 PlugInfoCmd::eSF_SerialBusIsochronousAndExternalPlug ); … … 147 147 { 148 148 debugOutput(DEBUG_LEVEL_NORMAL, "Discovering connections...\n"); 149 149 150 150 for ( PlugVector::iterator it = getPlugs().begin(); 151 151 it != getPlugs().end(); … … 183 183 return false; 184 184 } 185 185 186 186 plug->setVerboseLevel(getDebugLevel()); 187 187 188 188 if ( !plug->discover() ) { 189 189 debugError( "plug discover failed\n" ); … … 232 232 bool 233 233 Subunit::serialize( Glib::ustring basePath, 234 Util::IOSerialize& ser ) const234 Util::IOSerialize& ser ) const 235 235 { 236 236 bool result; … … 239 239 result &= ser.write( basePath + "m_sbId", m_sbId ); 240 240 result &= ser.write( basePath + "m_verboseLevel", getDebugLevel() ); 241 result &= serializePlugVector( basePath + "m_plugs", ser, m_plugs );242 241 result &= serializeChild( basePath, ser ); 243 242 … … 260 259 261 260 Subunit* pSubunit = 0; 262 261 263 262 #warning FIXME: The derived class should be creating these 264 263 // FIXME: The derived class should be creating these, such that discover() can become pure virtual … … 281 280 pSubunit->m_sbType = sbType; 282 281 result &= deser.read( basePath + "m_sbId", pSubunit->m_sbId ); 283 result &= deserializePlugVector( basePath + "m_plugs", deser,284 unit.getPlugManager(), pSubunit->m_plugs );285 282 int verboseLevel; 286 283 result &= deser.read( basePath + "m_verboseLevel", verboseLevel ); trunk/libffado/src/libavc/general/avc_subunit.h
r716 r734 73 73 74 74 PlugVector& getPlugs() 75 75 { return m_plugs; } 76 76 Plug* getPlug(Plug::EPlugDirection direction, plug_id_t plugId); 77 77 … … 80 80 bool serialize( Glib::ustring basePath, Util::IOSerialize& ser ) const; 81 81 static Subunit* deserialize( Glib::ustring basePath, 82 82 Util::IODeserialize& deser, Unit& avDevice ); 83 83 protected: 84 84 Subunit(); trunk/libffado/src/libavc/general/avc_unit.cpp
r716 r734 975 975 result = ser.write( basePath + "m_verboseLevel_unit", getDebugLevel() ); 976 976 result &= serializeVector( basePath + "Subunit", ser, m_subunits ); 977 result &= serialize PlugVector( basePath + "PcrPlug", ser, m_pcrPlugs );978 result &= serialize PlugVector( basePath + "ExternalPlug", ser, m_externalPlugs );977 result &= serializeVector( basePath + "PcrPlug", ser, m_pcrPlugs ); 978 result &= serializeVector( basePath + "ExternalPlug", ser, m_externalPlugs ); 979 979 result &= serializeVector( basePath + "PlugConnection", ser, m_plugConnections ); 980 980 result &= m_pPlugManager->serialize( basePath + "Plug", ser ); // serialize all av plugs … … 1007 1007 setDebugLevel( verboseLevel ); 1008 1008 1009 result &= deserializeVector<Subunit>( basePath + "Subunit", deser, *this, m_subunits );1009 result &= deserializeVector<Subunit>( basePath + "Subunit", deser, *this, m_subunits ); 1010 1010 1011 1011 if (m_pPlugManager) … … 1017 1017 return false; 1018 1018 1019 result &= deserializePlugVector( basePath + "PcrPlug", deser, getPlugManager(), m_pcrPlugs ); 1020 result &= deserializePlugVector( basePath + "ExternalPlug", deser, getPlugManager(), m_externalPlugs ); 1019 // XXX We have to deserialize the m_pcrPlugs and m_externPlugs members somehow. 1020 // Of course the simple following simple approach wont work at the moment. Some 1021 // more hacking needed :) 1022 //result &= deserializeVector<Plug>( basePath + "PcrPlug", deser, *this, m_pcrPlugs ); 1023 //result &= deserializeVector<Plug>( basePath + "ExternalPlug", deser, *this, m_externalPlugs ); 1024 result &= deserializePlugUpdateConnections( basePath + "PcrPlug", deser, m_pcrPlugs ); 1025 result &= deserializePlugUpdateConnections( basePath + "ExternalPlug", deser, m_externalPlugs ); 1021 1026 result &= deserializeVector<PlugConnection>( basePath + "PlugConnnection", deser, *this, m_plugConnections ); 1022 1027 result &= deserializeVector<Subunit>( basePath + "Subunit", deser, *this, m_subunits ); 1023 1028 result &= deserializeSyncInfoVector( basePath + "SyncInfo", deser, m_syncInfos ); 1024 1029 1025 result &= deserializePlugUpdateConnections( basePath + "PcrPlug", deser, m_pcrPlugs );1026 result &= deserializePlugUpdateConnections( basePath + "ExternalPlug", deser, m_externalPlugs );1027 m_pPlugManager->deserializeUpdate();1028 1029 1030 unsigned int i; 1030 1031 result &= deser.read( basePath + "m_activeSyncInfo", i ); trunk/libffado/src/libavc/musicsubunit/avc_musicsubunit.cpp
r716 r734 63 63 { 64 64 debugOutput(DEBUG_LEVEL_NORMAL, "Discovering %s...\n", getName()); 65 65 66 66 // discover the AV/C generic part 67 67 if ( !Subunit::discover() ) { 68 68 return false; 69 69 } 70 70 71 71 // now we have the subunit plugs 72 72 73 73 return true; 74 74 } … … 79 79 debugOutput(DEBUG_LEVEL_VERBOSE, "Loading info from descriptor for plug: \n"); 80 80 bool result=true; 81 81 82 82 // load the descriptor (if not already loaded) 83 83 if (m_status_descriptor != NULL) { 84 84 result &= m_status_descriptor->load(); 85 85 } 86 86 87 87 AVCMusicSubunitPlugInfoBlock *info; 88 88 info = m_status_descriptor->getSubunitPlugInfoBlock(plug.getDirection(), plug.getPlugId()); 89 89 90 90 if (info == NULL) { 91 91 debugError("Could not find plug info block\n"); 92 92 return false; 93 93 } 94 94 95 95 debugOutput(DEBUG_LEVEL_VERBOSE, "Found plug: %s\n",info->getName().c_str()); 96 96 97 97 // plug name 98 98 result &= plug.setName(info->getName()); 99 99 100 100 // plug type 101 101 switch (info->m_plug_type) { … … 119 119 break; 120 120 } 121 121 122 122 // number of channels 123 123 result &= plug.setNrOfChannels(info->m_nb_channels); 124 124 125 125 int idx=1; 126 126 for ( AVCMusicClusterInfoBlockVectorIterator it = info->m_Clusters.begin(); 127 128 127 it != info->m_Clusters.end(); 128 ++it ) 129 129 { 130 130 struct Plug::ClusterInfo cinfo; 131 131 132 132 AVCMusicClusterInfoBlock *c=(*it); 133 133 134 134 cinfo.m_index=idx; //FIXME: is this correct? 135 135 cinfo.m_portType=c->m_port_type; … … 141 141 cinfo.m_index, cinfo.m_portType, cinfo.m_nrOfChannels, cinfo.m_streamFormat, cinfo.m_name.c_str()); 142 142 143 for ( AVCMusicClusterInfoBlock::SignalInfoVectorIterator sig_it 144 145 146 143 for ( AVCMusicClusterInfoBlock::SignalInfoVectorIterator sig_it 144 = c->m_SignalInfos.begin(); 145 sig_it != c->m_SignalInfos.end(); 146 ++sig_it ) 147 147 { 148 148 struct AVCMusicClusterInfoBlock::sSignalInfo s=(*sig_it); 149 149 struct Plug::ChannelInfo sinfo; 150 150 151 151 sinfo.m_streamPosition=s.stream_position; 152 152 sinfo.m_location=s.stream_location; 153 153 154 154 AVCMusicPlugInfoBlock *mplug=m_status_descriptor->getMusicPlugInfoBlock(s.music_plug_id); 155 155 156 156 if (mplug==NULL) { 157 157 debugWarning("No music plug found for this signal\n"); … … 160 160 sinfo.m_name=mplug->getName(); 161 161 } 162 162 163 163 if (plug.getDirection() == Plug::eAPD_Input) { 164 // it's an input plug to the subunit 164 // it's an input plug to the subunit 165 165 // so we have to check the source field of the music plug 166 166 if(s.stream_position != mplug->m_source_stream_position) { … … 177 177 } 178 178 } else if (plug.getDirection() == Plug::eAPD_Output) { 179 // it's an output plug from the subunit 179 // it's an output plug from the subunit 180 180 // so we have to check the destination field of the music plug 181 181 if(s.stream_position != mplug->m_dest_stream_position) { … … 194 194 debugWarning("Invalid plug direction.\n"); 195 195 } 196 196 197 197 debugOutput(DEBUG_LEVEL_VERBOSE, "Adding signal pos=%2d loc=%2d name=%s\n", 198 198 sinfo.m_streamPosition, sinfo.m_location, mplug->getName().c_str()); 199 199 200 200 cinfo.m_channelInfos.push_back(sinfo); 201 201 } … … 204 204 plug.getClusterInfos().push_back(cinfo); 205 205 } 206 207 206 207 208 208 return result; 209 209 … … 239 239 bool 240 240 SubunitMusic::serializeChild( Glib::ustring basePath, 241 Util::IOSerialize& ser ) const241 Util::IOSerialize& ser ) const 242 242 { 243 243 return true; … … 246 246 bool 247 247 SubunitMusic::deserializeChild( Glib::ustring basePath, 248 Util::IODeserialize& deser,249 Unit& unit )248 Util::IODeserialize& deser, 249 Unit& unit ) 250 250 { 251 251 return true; trunk/libffado/src/libieee1394/configrom.cpp
r711 r734 64 64 , m_1394Service( &ieee1394service ) 65 65 , m_nodeId( nodeId ) 66 , m_avcDevice( false ) // FIXME: this does not seem veryu66 , m_avcDevice( false ) 67 67 , m_guid( 0 ) 68 68 , m_vendorName( "" ) … … 91 91 , m_1394Service( 0 ) 92 92 , m_nodeId( -1 ) 93 , m_avcDevice( false ) // FIXME: this does not seem veryu93 , m_avcDevice( false ) 94 94 , m_guid( 0 ) 95 95 , m_vendorName( "" ) … … 292 292 if ( m_unit_specifier_id == 0x0000a02d ) // XXX 293 293 { 294 m_avcDevice = true; // FIXME: disable this check for the moment 295 if ( kv->value.immediate == 0x14001 ) { 294 if ( kv->value.immediate == 0x10001 ) { 296 295 m_avcDevice = true; 297 296 } trunk/libffado/src/libstreaming/StreamProcessorManager.cpp
r512 r734 23 23 24 24 #include "StreamProcessorManager.h" 25 #include "StreamProcessor.h" 26 #include "Port.h" 25 #include "generic/StreamProcessor.h" 26 #include "generic/Port.h" 27 #include "util/cycletimer.h" 28 27 29 #include <errno.h> 28 30 #include <assert.h> 29 30 #include "libstreaming/cycletimer.h" 31 32 #define CYCLES_TO_SLEEP_AFTER_RUN_SIGNAL 5 31 #include <math.h> 33 32 34 33 #define RUNNING_TIMEOUT_MSEC 4000 … … 36 35 #define ENABLE_TIMEOUT_MSEC 4000 37 36 38 //#define ENABLE_DELAY_CYCLES 100 39 #define ENABLE_DELAY_CYCLES 1000 37 // allows to add some processing margin. This shifts the time 38 // at which the buffer is transfer()'ed, making things somewhat 39 // more robust. It should be noted though that shifting the transfer 40 // time to a later time instant also causes the xmit buffer fill to be 41 // lower on average. 42 #define FFADO_SIGNAL_DELAY_TICKS 3072*4 40 43 41 44 namespace Streaming { 42 45 43 IMPL_DEBUG_MODULE( StreamProcessorManager, StreamProcessorManager, DEBUG_LEVEL_ NORMAL);44 45 StreamProcessorManager::StreamProcessorManager(unsigned int period, unsigned int nb_buffers)46 IMPL_DEBUG_MODULE( StreamProcessorManager, StreamProcessorManager, DEBUG_LEVEL_VERBOSE ); 47 48 StreamProcessorManager::StreamProcessorManager(unsigned int period, unsigned int framerate, unsigned int nb_buffers) 46 49 : m_is_slave( false ) 47 50 , m_SyncSource(NULL) 48 51 , m_nb_buffers(nb_buffers) 49 52 , m_period(period) 53 , m_nominal_framerate ( framerate ) 50 54 , m_xruns(0) 51 55 , m_isoManager(0) … … 57 61 StreamProcessorManager::~StreamProcessorManager() { 58 62 if (m_isoManager) delete m_isoManager; 59 60 63 } 61 64 … … 77 80 assert(m_isoManager); 78 81 79 if (processor->getType() ==StreamProcessor::E_Receive) {82 if (processor->getType() == StreamProcessor::ePT_Receive) { 80 83 processor->setVerboseLevel(getDebugLevel()); // inherit debug level 81 84 82 85 m_ReceiveProcessors.push_back(processor); 83 84 86 processor->setManager(this); 85 86 87 return true; 87 88 } 88 89 89 if (processor->getType() ==StreamProcessor::E_Transmit) {90 if (processor->getType() == StreamProcessor::ePT_Transmit) { 90 91 processor->setVerboseLevel(getDebugLevel()); // inherit debug level 91 92 92 93 m_TransmitProcessors.push_back(processor); 93 94 94 processor->setManager(this); 95 96 95 return true; 97 96 } 98 97 99 98 debugFatal("Unsupported processor type!\n"); 100 101 99 return false; 102 100 } … … 107 105 assert(processor); 108 106 109 if (processor->getType()==StreamProcessor:: E_Receive) {107 if (processor->getType()==StreamProcessor::ePT_Receive) { 110 108 111 109 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 112 it != m_ReceiveProcessors.end();113 ++it ) {114 110 it != m_ReceiveProcessors.end(); 111 ++it ) 112 { 115 113 if ( *it == processor ) { 116 m_ReceiveProcessors.erase(it); 117 118 processor->clearManager(); 119 120 if(!m_isoManager->unregisterStream(processor)) { 121 debugOutput(DEBUG_LEVEL_VERBOSE,"Could not unregister receive stream processor from the Iso manager\n"); 122 123 return false; 124 125 } 126 127 return true; 114 m_ReceiveProcessors.erase(it); 115 processor->clearManager(); 116 if(!m_isoManager->unregisterStream(processor)) { 117 debugOutput(DEBUG_LEVEL_VERBOSE,"Could not unregister receive stream processor from the Iso manager\n"); 118 return false; 128 119 } 129 } 130 } 131 132 if (processor->getType()==StreamProcessor::E_Transmit) { 120 return true; 121 } 122 } 123 } 124 125 if (processor->getType()==StreamProcessor::ePT_Transmit) { 133 126 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 134 it != m_TransmitProcessors.end();135 ++it ) {136 127 it != m_TransmitProcessors.end(); 128 ++it ) 129 { 137 130 if ( *it == processor ) { 138 m_TransmitProcessors.erase(it); 139 140 processor->clearManager(); 141 142 if(!m_isoManager->unregisterStream(processor)) { 143 debugOutput(DEBUG_LEVEL_VERBOSE,"Could not unregister transmit stream processor from the Iso manager\n"); 144 145 return false; 146 147 } 148 149 return true; 131 m_TransmitProcessors.erase(it); 132 processor->clearManager(); 133 if(!m_isoManager->unregisterStream(processor)) { 134 debugOutput(DEBUG_LEVEL_VERBOSE,"Could not unregister transmit stream processor from the Iso manager\n"); 135 return false; 150 136 } 137 return true; 138 } 151 139 } 152 140 } 153 141 154 142 debugFatal("Processor (%p) not found!\n",processor); 155 156 143 return false; //not found 157 158 144 } 159 145 160 146 bool StreamProcessorManager::setSyncSource(StreamProcessor *s) { 161 147 debugOutput( DEBUG_LEVEL_VERBOSE, "Setting sync source to (%p)\n", s); 162 163 148 m_SyncSource=s; 164 149 return true; 165 }166 167 StreamProcessor *StreamProcessorManager::getSyncSource() {168 return m_SyncSource;169 150 } 170 151 … … 172 153 { 173 154 debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n"); 174 175 m_isoManager=new IsoHandlerManager(m_thread_realtime, m_thread_priority); 176 155 m_isoManager = new IsoHandlerManager(m_thread_realtime, m_thread_priority + 1); 177 156 if(!m_isoManager) { 178 157 debugFatal("Could not create IsoHandlerManager\n"); 179 158 return false; 180 159 } 181 182 // propagate the debug level183 160 m_isoManager->setVerboseLevel(getDebugLevel()); 161 162 // try to queue up 75% of the frames in the transmit buffer 163 unsigned int nb_frames = (getNbBuffers() - 1) * getPeriodSize() * 1000 / 2000; 164 m_isoManager->setTransmitBufferNbFrames(nb_frames); 184 165 185 166 if(!m_isoManager->init()) { … … 189 170 190 171 m_xrun_happened=false; 191 192 172 return true; 193 173 } … … 207 187 } 208 188 189 // FIXME: put into separate method 190 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 191 it != m_ReceiveProcessors.end(); 192 ++it ) 193 { 194 if(m_SyncSource == NULL) { 195 debugWarning(" => Sync Source is %p.\n", *it); 196 m_SyncSource = *it; 197 } 198 } 199 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 200 it != m_TransmitProcessors.end(); 201 ++it ) 202 { 203 if(m_SyncSource == NULL) { 204 debugWarning(" => Sync Source is %p.\n", *it); 205 m_SyncSource = *it; 206 } 207 } 208 209 // now do the actual preparation of the SP's 210 debugOutput( DEBUG_LEVEL_VERBOSE, "Prepare Receive processors...\n"); 209 211 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 210 212 it != m_ReceiveProcessors.end(); 211 213 ++it ) { 212 if(m_SyncSource == NULL) {213 debugWarning(" => Sync Source is %p.\n", *it);214 m_SyncSource = *it;215 }216 }217 218 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();219 it != m_TransmitProcessors.end();220 ++it ) {221 if(m_SyncSource == NULL) {222 debugWarning(" => Sync Source is %p.\n", *it);223 m_SyncSource = *it;224 }225 }226 227 // now do the actual preparation228 debugOutput( DEBUG_LEVEL_VERBOSE, "Prepare Receive processors...\n");229 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();230 it != m_ReceiveProcessors.end();231 ++it ) {232 233 if(!(*it)->setSyncSource(m_SyncSource)) {234 debugFatal( " could not set sync source (%p)...\n",(*it));235 return false;236 }237 214 238 215 if(!(*it)->setOption("slaveMode", m_is_slave)) { … … 245 222 } 246 223 } 247 248 224 debugOutput( DEBUG_LEVEL_VERBOSE, "Prepare Transmit processors...\n"); 249 225 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 250 226 it != m_TransmitProcessors.end(); 251 227 ++it ) { 252 if(!(*it)->setSyncSource(m_SyncSource)) {253 debugFatal( " could not set sync source (%p)...\n",(*it));254 return false;255 }256 228 if(!(*it)->setOption("slaveMode", m_is_slave)) { 257 229 debugOutput(DEBUG_LEVEL_VERBOSE, " note: could not set slaveMode option for (%p)...\n",(*it)); … … 269 241 return false; 270 242 } 271 272 243 return true; 273 244 } 274 245 275 bool StreamProcessorManager::syncStartAll() { 276 277 debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for StreamProcessor streams to start running...\n"); 278 // we have to wait until all streamprocessors indicate that they are running 279 // i.e. that there is actually some data stream flowing 280 int wait_cycles=RUNNING_TIMEOUT_MSEC; // two seconds 281 bool notRunning=true; 282 while (notRunning && wait_cycles) { 283 wait_cycles--; 284 notRunning=false; 285 246 bool StreamProcessorManager::startDryRunning() { 247 debugOutput( DEBUG_LEVEL_VERBOSE, "Putting StreamProcessor streams into dry-running state...\n"); 248 debugOutput( DEBUG_LEVEL_VERBOSE, " Schedule start dry-running...\n"); 249 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 250 it != m_ReceiveProcessors.end(); 251 ++it ) { 252 if (!(*it)->isDryRunning()) { 253 if(!(*it)->scheduleStartDryRunning(-1)) { 254 debugError("Could not put SP %p into the dry-running state\n", *it); 255 return false; 256 } 257 } else { 258 debugOutput( DEBUG_LEVEL_VERBOSE, " SP %p already dry-running...\n", *it); 259 } 260 } 261 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 262 it != m_TransmitProcessors.end(); 263 ++it ) { 264 if (!(*it)->isDryRunning()) { 265 if(!(*it)->scheduleStartDryRunning(-1)) { 266 debugError("Could not put SP %p into the dry-running state\n", *it); 267 return false; 268 } 269 } else { 270 debugOutput( DEBUG_LEVEL_VERBOSE, " SP %p already dry-running...\n", *it); 271 } 272 } 273 debugOutput( DEBUG_LEVEL_VERBOSE, " Waiting for all SP's to be dry-running...\n"); 274 // wait for the syncsource to start running. 275 // that will block the waitForPeriod call until everyone has started (theoretically) 276 #define CYCLES_FOR_DRYRUN 40000 277 int cnt = CYCLES_FOR_DRYRUN; // by then it should have started 278 bool all_dry_running = false; 279 while (!all_dry_running && cnt) { 280 all_dry_running = true; 286 281 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 287 282 it != m_ReceiveProcessors.end(); 288 283 ++it ) { 289 if(!(*it)->isRunning()) notRunning=true; 290 } 291 284 all_dry_running &= (*it)->isDryRunning(); 285 } 292 286 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 293 287 it != m_TransmitProcessors.end(); 294 288 ++it ) { 295 if(!(*it)->isRunning()) notRunning=true; 296 } 297 298 // EXPERIMENT: 299 // the only stream that should be running is the sync 300 // source stream, as this is the one that defines 301 // when to signal buffers. Maybe we get an xrun at startup, 302 // but that should be handled. 303 304 // the problem is that otherwise a setup with a device 305 // that waits for decent input before sending output 306 // will not start up (e.g. the bounce device), because 307 // all streams are required to be running. 308 309 // other streams still have at least ENABLE_DELAY_CYCLES cycles 310 // to start up 311 // if(!m_SyncSource->isRunning()) notRunning=true; 312 313 usleep(1000); 314 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Running check: %d\n",notRunning); 315 } 316 317 if(!wait_cycles) { // timout has occurred 318 debugFatal("One or more streams are not starting up (timeout):\n"); 319 289 all_dry_running &= (*it)->isDryRunning(); 290 } 291 292 usleep(125); 293 cnt--; 294 } 295 if(cnt==0) { 296 debugOutput(DEBUG_LEVEL_VERBOSE, " Timeout waiting for the SP's to start dry-running\n"); 320 297 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 321 298 it != m_ReceiveProcessors.end(); 322 299 ++it ) { 323 if(!(*it)->isRunning()) { 324 debugFatal(" receive stream %p not running\n",*it); 325 } else { 326 debugFatal(" receive stream %p running\n",*it); 327 } 328 } 329 300 debugOutput( DEBUG_LEVEL_VERBOSE, " %s SP %p has state %s\n", 301 (*it)->getTypeString(), *it, (*it)->getStateString()); 302 } 330 303 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 331 304 it != m_TransmitProcessors.end(); 332 305 ++it ) { 333 if(!(*it)->isRunning()) { 334 debugFatal(" transmit stream %p not running\n",*it); 335 } else { 336 debugFatal(" transmit stream %p running\n",*it); 337 } 338 } 339 return false; 340 } 341 342 // we want to make sure that everything is running well, 343 // so wait for a while 344 usleep(USECS_PER_CYCLE * CYCLES_TO_SLEEP_AFTER_RUN_SIGNAL); 345 306 debugOutput( DEBUG_LEVEL_VERBOSE, " %s SP %p has state %s\n", 307 (*it)->getTypeString(), *it, (*it)->getStateString()); 308 } 309 return false; 310 } 311 debugOutput( DEBUG_LEVEL_VERBOSE, " StreamProcessor streams dry-running...\n"); 312 return true; 313 } 314 315 bool StreamProcessorManager::syncStartAll() { 316 // figure out when to get the SP's running. 317 // the xmit SP's should also know the base timestamp 318 // streams should be aligned here 319 320 // now find out how long we have to delay the wait operation such that 321 // the received frames will all be presented to the SP 322 debugOutput( DEBUG_LEVEL_VERBOSE, "Finding minimal sync delay...\n"); 323 int max_of_min_delay = 0; 324 int min_delay = 0; 325 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 326 it != m_ReceiveProcessors.end(); 327 ++it ) { 328 min_delay = (*it)->getMaxFrameLatency(); 329 if(min_delay > max_of_min_delay) max_of_min_delay = min_delay; 330 } 331 332 // add some processing margin. This only shifts the time 333 // at which the buffer is transfer()'ed. This makes things somewhat 334 // more robust. It should be noted though that shifting the transfer 335 // time to a later time instant also causes the xmit buffer fill to be 336 // lower on average. 337 max_of_min_delay += FFADO_SIGNAL_DELAY_TICKS; 338 debugOutput( DEBUG_LEVEL_VERBOSE, " sync delay = %d ticks (%03us %04uc %04ut)...\n", 339 max_of_min_delay, 340 (unsigned int)TICKS_TO_SECS(max_of_min_delay), 341 (unsigned int)TICKS_TO_CYCLES(max_of_min_delay), 342 (unsigned int)TICKS_TO_OFFSET(max_of_min_delay)); 343 m_SyncSource->setSyncDelay(max_of_min_delay); 344 345 //STEP X: when we implement such a function, we can wait for a signal from the devices that they 346 // have aquired lock 347 //debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for device(s) to indicate clock sync lock...\n"); 348 //sleep(2); // FIXME: be smarter here 349 350 // make sure that we are dry-running long enough for the 351 // DLL to have a decent sync (FIXME: does the DLL get updated when dry-running)? 352 debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for sync...\n"); 353 int nb_sync_runs=20; 354 int64_t time_till_next_period; 355 while(nb_sync_runs--) { // or while not sync-ed? 356 // check if we were woken up too soon 357 time_till_next_period = m_SyncSource->getTimeUntilNextPeriodSignalUsecs(); 358 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "waiting for %d usecs...\n", time_till_next_period); 359 if(time_till_next_period > 0) { 360 // wait for the period 361 usleep(time_till_next_period); 362 } 363 } 364 365 debugOutput( DEBUG_LEVEL_VERBOSE, "Propagate sync info...\n"); 366 // FIXME: in the SPM it would be nice to have system time instead of 367 // 1394 time 368 369 // we now should have decent sync info on the sync source 370 // determine a point in time where the system should start 371 // figure out where we are now 372 uint64_t time_of_first_sample = m_SyncSource->getTimeAtPeriod(); 373 debugOutput( DEBUG_LEVEL_VERBOSE, " sync at TS=%011llu (%03us %04uc %04ut)...\n", 374 time_of_first_sample, 375 (unsigned int)TICKS_TO_SECS(time_of_first_sample), 376 (unsigned int)TICKS_TO_CYCLES(time_of_first_sample), 377 (unsigned int)TICKS_TO_OFFSET(time_of_first_sample)); 378 379 #define CYCLES_FOR_STARTUP 2000 380 // start wet-running in CYCLES_FOR_STARTUP cycles 381 // this is the time window we have to setup all SP's such that they 382 // can start wet-running correctly. 383 time_of_first_sample = addTicks(time_of_first_sample, 384 CYCLES_FOR_STARTUP * TICKS_PER_CYCLE); 385 386 debugOutput( DEBUG_LEVEL_VERBOSE, " => first sample at TS=%011llu (%03us %04uc %04ut)...\n", 387 time_of_first_sample, 388 (unsigned int)TICKS_TO_SECS(time_of_first_sample), 389 (unsigned int)TICKS_TO_CYCLES(time_of_first_sample), 390 (unsigned int)TICKS_TO_OFFSET(time_of_first_sample)); 391 392 // we should start wet-running the transmit SP's some cycles in advance 393 // such that we know it is wet-running when it should output its first sample 394 #define PRESTART_CYCLES_FOR_XMIT 20 395 uint64_t time_to_start_xmit = substractTicks(time_of_first_sample, 396 PRESTART_CYCLES_FOR_XMIT * TICKS_PER_CYCLE); 397 398 #define PRESTART_CYCLES_FOR_RECV 0 399 uint64_t time_to_start_recv = substractTicks(time_of_first_sample, 400 PRESTART_CYCLES_FOR_RECV * TICKS_PER_CYCLE); 401 debugOutput( DEBUG_LEVEL_VERBOSE, " => xmit starts at TS=%011llu (%03us %04uc %04ut)...\n", 402 time_to_start_xmit, 403 (unsigned int)TICKS_TO_SECS(time_to_start_xmit), 404 (unsigned int)TICKS_TO_CYCLES(time_to_start_xmit), 405 (unsigned int)TICKS_TO_OFFSET(time_to_start_xmit)); 406 debugOutput( DEBUG_LEVEL_VERBOSE, " => recv starts at TS=%011llu (%03us %04uc %04ut)...\n", 407 time_to_start_recv, 408 (unsigned int)TICKS_TO_SECS(time_to_start_recv), 409 (unsigned int)TICKS_TO_CYCLES(time_to_start_recv), 410 (unsigned int)TICKS_TO_OFFSET(time_to_start_recv)); 411 412 // at this point the buffer head timestamp of the transmit buffers can be set 413 // this is the presentation time of the first sample in the buffer 414 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 415 it != m_TransmitProcessors.end(); 416 ++it ) { 417 (*it)->setBufferHeadTimestamp(time_of_first_sample); 418 } 419 420 // STEP X: switch SP's over to the running state 421 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 422 it != m_ReceiveProcessors.end(); 423 ++it ) { 424 if(!(*it)->scheduleStartRunning(time_to_start_recv)) { 425 debugError("%p->scheduleStartRunning(%11llu) failed\n", *it, time_to_start_recv); 426 return false; 427 } 428 } 429 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 430 it != m_TransmitProcessors.end(); 431 ++it ) { 432 if(!(*it)->scheduleStartRunning(time_to_start_xmit)) { 433 debugError("%p->scheduleStartRunning(%11llu) failed\n", *it, time_to_start_xmit); 434 return false; 435 } 436 } 437 // wait for the syncsource to start running. 438 // that will block the waitForPeriod call until everyone has started (theoretically) 439 int cnt = CYCLES_FOR_STARTUP * 2; // by then it should have started 440 while (!m_SyncSource->isRunning() && cnt) { 441 usleep(125); 442 cnt--; 443 } 444 if(cnt==0) { 445 debugOutput(DEBUG_LEVEL_VERBOSE, " Timeout waiting for the SyncSource to get started\n"); 446 return false; 447 } 448 449 // now align the received streams 450 if(!alignReceivedStreams()) { 451 debugError("Could not align streams\n"); 452 return false; 453 } 346 454 debugOutput( DEBUG_LEVEL_VERBOSE, " StreamProcessor streams running...\n"); 347 348 debugOutput( DEBUG_LEVEL_VERBOSE, "Finding minimal sync delay...\n"); 349 350 int max_of_min_delay=0; 351 int min_delay=0; 352 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 353 it != m_ReceiveProcessors.end(); 354 ++it ) { 355 min_delay=(*it)->getMinimalSyncDelay(); 356 if(min_delay>max_of_min_delay) max_of_min_delay=min_delay; 357 } 358 359 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 360 it != m_TransmitProcessors.end(); 361 ++it ) { 362 min_delay=(*it)->getMinimalSyncDelay(); 363 if(min_delay>max_of_min_delay) max_of_min_delay=min_delay; 364 } 365 366 debugOutput( DEBUG_LEVEL_VERBOSE, " %d ticks\n", max_of_min_delay); 367 m_SyncSource->setSyncDelay(max_of_min_delay); 368 369 370 debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting StreamProcessors...\n"); 371 // now we reset the frame counters 372 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 373 it != m_ReceiveProcessors.end(); 374 ++it ) { 375 (*it)->reset(); 376 } 377 378 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 379 it != m_TransmitProcessors.end(); 380 ++it ) { 381 (*it)->reset(); 382 } 383 384 debugOutput( DEBUG_LEVEL_VERBOSE, "Enabling StreamProcessors...\n"); 385 386 uint64_t now=m_SyncSource->getTimeNow(); // fixme: should be in usecs, not ticks 387 388 // FIXME: this should not be in cycles, but in 'time' 389 unsigned int enable_at=TICKS_TO_CYCLES(now)+ENABLE_DELAY_CYCLES; 390 if (enable_at > 8000) enable_at -= 8000; 391 392 if (!enableStreamProcessors(enable_at)) { 393 debugFatal("Could not enable StreamProcessors...\n"); 394 return false; 395 } 396 455 return true; 456 } 457 458 bool 459 StreamProcessorManager::alignReceivedStreams() 460 { 461 #define NB_PERIODS_FOR_ALIGN_AVERAGE 20 462 #define NB_ALIGN_TRIES 20 463 debugOutput( DEBUG_LEVEL_VERBOSE, "Aligning received streams...\n"); 464 unsigned int nb_sync_runs; 465 unsigned int nb_rcv_sp = m_ReceiveProcessors.size(); 466 int64_t diff_between_streams[nb_rcv_sp]; 467 int64_t diff; 468 469 unsigned int i; 470 471 bool aligned = false; 472 int cnt = NB_ALIGN_TRIES; 473 while (!aligned && cnt--) { 474 nb_sync_runs = NB_PERIODS_FOR_ALIGN_AVERAGE; 475 while(nb_sync_runs) { 476 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, " check (%d)...\n", nb_sync_runs); 477 waitForPeriod(); 478 479 i = 0; 480 for ( i = 0; i < nb_rcv_sp; i++) { 481 StreamProcessor *s = m_ReceiveProcessors.at(i); 482 diff = diffTicks(m_SyncSource->getTimeAtPeriod(), s->getTimeAtPeriod()); 483 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, " offset between SyncSP %p and SP %p is %lld ticks...\n", 484 m_SyncSource, s, diff); 485 if ( nb_sync_runs == NB_PERIODS_FOR_ALIGN_AVERAGE ) { 486 diff_between_streams[i] = diff; 487 } else { 488 diff_between_streams[i] += diff; 489 } 490 } 491 if(!transferSilence()) { 492 debugError("Could not transfer silence\n"); 493 return false; 494 } 495 nb_sync_runs--; 496 } 497 // calculate the average offsets 498 debugOutput( DEBUG_LEVEL_VERBOSE, " Average offsets:\n"); 499 int diff_between_streams_frames[nb_rcv_sp]; 500 aligned = true; 501 for ( i = 0; i < nb_rcv_sp; i++) { 502 StreamProcessor *s = m_ReceiveProcessors.at(i); 503 504 diff_between_streams[i] /= NB_PERIODS_FOR_ALIGN_AVERAGE; 505 diff_between_streams_frames[i] = roundf(diff_between_streams[i] / s->getTicksPerFrame()); 506 debugOutput( DEBUG_LEVEL_VERBOSE, " avg offset between SyncSP %p and SP %p is %lld ticks, %d frames...\n", 507 m_SyncSource, s, diff_between_streams[i], diff_between_streams_frames[i]); 508 509 aligned &= (diff_between_streams_frames[i] == 0); 510 511 // reposition the stream 512 if(!s->shiftStream(diff_between_streams_frames[i])) { 513 debugError("Could not shift SP %p %d frames\n", s, diff_between_streams_frames[i]); 514 return false; 515 } 516 } 517 if (!aligned) { 518 debugOutput(DEBUG_LEVEL_VERBOSE, "Streams not aligned, doing new round...\n"); 519 } 520 } 521 if (cnt == 0) { 522 debugError("Align failed\n"); 523 return false; 524 } 397 525 return true; 398 526 } … … 405 533 debugOutput( DEBUG_LEVEL_VERBOSE, " Receive processors...\n"); 406 534 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 407 it != m_ReceiveProcessors.end(); 408 ++it ) { 409 if (!(*it)->prepareForStart()) { 410 debugOutput(DEBUG_LEVEL_VERBOSE,"Receive stream processor (%p) failed to prepare for start\n", *it); 411 return false; 412 } 413 if (!m_isoManager->registerStream(*it)) { 414 debugOutput(DEBUG_LEVEL_VERBOSE,"Could not register receive stream processor (%p) with the Iso manager\n",*it); 415 return false; 416 } 417 } 418 535 it != m_ReceiveProcessors.end(); 536 ++it ) 537 { 538 if (!m_isoManager->registerStream(*it)) { 539 debugOutput(DEBUG_LEVEL_VERBOSE,"Could not register receive stream processor (%p) with the Iso manager\n",*it); 540 return false; 541 } 542 } 419 543 debugOutput( DEBUG_LEVEL_VERBOSE, " Transmit processors...\n"); 420 544 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 421 it != m_TransmitProcessors.end(); 422 ++it ) { 423 if (!(*it)->prepareForStart()) { 424 debugOutput(DEBUG_LEVEL_VERBOSE,"Transmit stream processor (%p) failed to prepare for start\n", *it); 425 return false; 426 } 427 if (!m_isoManager->registerStream(*it)) { 428 debugOutput(DEBUG_LEVEL_VERBOSE,"Could not register transmit stream processor (%p) with the Iso manager\n",*it); 429 return false; 430 } 431 } 545 it != m_TransmitProcessors.end(); 546 ++it ) 547 { 548 if (!m_isoManager->registerStream(*it)) { 549 debugOutput(DEBUG_LEVEL_VERBOSE,"Could not register transmit stream processor (%p) with the Iso manager\n",*it); 550 return false; 551 } 552 } 432 553 433 554 debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing IsoHandlerManager...\n"); … … 437 558 } 438 559 439 debugOutput( DEBUG_LEVEL_VERBOSE, "Disabling StreamProcessors...\n");440 if (!disableStreamProcessors()) {441 debugFatal("Could not disable StreamProcessors...\n");442 return false;443 }444 445 560 debugOutput( DEBUG_LEVEL_VERBOSE, "Starting IsoHandlers...\n"); 446 561 if (!m_isoManager->startHandlers(-1)) { … … 449 564 } 450 565 566 // put all SP's into dry-running state 567 if (!startDryRunning()) { 568 debugFatal("Could not put SP's in dry-running state\n"); 569 return false; 570 } 571 451 572 // start all SP's synchonized 452 573 if (!syncStartAll()) { … … 461 582 462 583 return true; 463 464 584 } 465 585 … … 468 588 assert(m_isoManager); 469 589 470 debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for all StreamProcessors to prepare to stop...\n"); 471 // Most stream processors can just stop without special treatment. However, some 472 // (like the MOTU) need to do a few things before it's safe to turn off the iso 473 // handling. 474 int wait_cycles=PREPARE_TIMEOUT_MSEC; // two seconds ought to be sufficient 475 bool allReady = false; 476 while (!allReady && wait_cycles) { 477 wait_cycles--; 478 allReady = true; 479 590 debugOutput( DEBUG_LEVEL_VERBOSE, " scheduling stop for all SP's...\n"); 591 592 // switch SP's over to the dry-running state 593 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 594 it != m_ReceiveProcessors.end(); 595 ++it ) { 596 if(!(*it)->scheduleStopRunning(-1)) { 597 debugError("%p->scheduleStopRunning(-1) failed\n", *it); 598 return false; 599 } 600 } 601 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 602 it != m_TransmitProcessors.end(); 603 ++it ) { 604 if(!(*it)->scheduleStopRunning(-1)) { 605 debugError("%p->scheduleStopRunning(-1) failed\n", *it); 606 return false; 607 } 608 } 609 // wait for the SP's to get into the dry-running state 610 int cnt = 200; 611 bool ready = false; 612 while (!ready && cnt) { 613 ready = true; 480 614 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 481 615 it != m_ReceiveProcessors.end(); 482 616 ++it ) { 483 if(!(*it)->prepareForStop()) allReady = false; 484 } 485 617 ready &= ((*it)->isDryRunning() || (*it)->isStopped()); 618 } 486 619 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 487 620 it != m_TransmitProcessors.end(); 488 621 ++it ) { 489 if(!(*it)->prepareForStop()) allReady = false; 490 } 491 usleep(1000); 492 } 493 622 ready &= ((*it)->isDryRunning() || (*it)->isStopped()); 623 } 624 usleep(125); 625 cnt--; 626 } 627 if(cnt==0) { 628 debugOutput(DEBUG_LEVEL_VERBOSE, " Timeout waiting for the SP's to start dry-running\n"); 629 return false; 630 } 631 632 // switch SP's over to the stopped state 633 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 634 it != m_ReceiveProcessors.end(); 635 ++it ) { 636 if(!(*it)->scheduleStopDryRunning(-1)) { 637 debugError("%p->scheduleStopDryRunning(-1) failed\n", *it); 638 return false; 639 } 640 } 641 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 642 it != m_TransmitProcessors.end(); 643 ++it ) { 644 if(!(*it)->scheduleStopDryRunning(-1)) { 645 debugError("%p->scheduleStopDryRunning(-1) failed\n", *it); 646 return false; 647 } 648 } 649 // wait for the SP's to get into the running state 650 cnt = 200; 651 ready = false; 652 while (!ready && cnt) { 653 ready = true; 654 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 655 it != m_ReceiveProcessors.end(); 656 ++it ) { 657 ready &= (*it)->isStopped(); 658 } 659 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 660 it != m_TransmitProcessors.end(); 661 ++it ) { 662 ready &= (*it)->isStopped(); 663 } 664 usleep(125); 665 cnt--; 666 } 667 if(cnt==0) { 668 debugOutput(DEBUG_LEVEL_VERBOSE, " Timeout waiting for the SP's to stop\n"); 669 return false; 670 } 494 671 495 672 debugOutput( DEBUG_LEVEL_VERBOSE, "Stopping handlers...\n"); … … 503 680 debugOutput( DEBUG_LEVEL_VERBOSE, " Receive processors...\n"); 504 681 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 505 it != m_ReceiveProcessors.end(); 506 ++it ) { 507 if (!m_isoManager->unregisterStream(*it)) { 508 debugOutput(DEBUG_LEVEL_VERBOSE,"Could not unregister receive stream processor (%p) from the Iso manager\n",*it); 509 return false; 510 } 511 512 } 513 682 it != m_ReceiveProcessors.end(); 683 ++it ) { 684 if (!m_isoManager->unregisterStream(*it)) { 685 debugOutput(DEBUG_LEVEL_VERBOSE,"Could not unregister receive stream processor (%p) from the Iso manager\n",*it); 686 return false; 687 } 688 } 514 689 debugOutput( DEBUG_LEVEL_VERBOSE, " Transmit processors...\n"); 515 690 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 516 it != m_TransmitProcessors.end(); 517 ++it ) { 518 if (!m_isoManager->unregisterStream(*it)) { 519 debugOutput(DEBUG_LEVEL_VERBOSE,"Could not unregister transmit stream processor (%p) from the Iso manager\n",*it); 520 return false; 521 } 522 523 } 524 525 return true; 526 527 } 528 529 /** 530 * Enables the registered StreamProcessors 531 * @return true if successful, false otherwise 532 */ 533 bool StreamProcessorManager::enableStreamProcessors(uint64_t time_to_enable_at) { 534 debugOutput( DEBUG_LEVEL_VERBOSE, "Enabling StreamProcessors at %llu...\n", time_to_enable_at); 535 536 debugOutput( DEBUG_LEVEL_VERBOSE, " Sync Source StreamProcessor (%p)...\n",m_SyncSource); 537 debugOutput( DEBUG_LEVEL_VERBOSE, " Prepare...\n"); 538 if (!m_SyncSource->prepareForEnable(time_to_enable_at)) { 539 debugFatal("Could not prepare Sync Source StreamProcessor for enable()...\n"); 540 return false; 541 } 542 543 debugOutput( DEBUG_LEVEL_VERBOSE, " Enable...\n"); 544 m_SyncSource->enable(time_to_enable_at); 545 546 debugOutput( DEBUG_LEVEL_VERBOSE, " Other StreamProcessors...\n"); 547 548 // we prepare the streamprocessors for enable 549 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 550 it != m_ReceiveProcessors.end(); 551 ++it ) { 552 if(*it != m_SyncSource) { 553 debugOutput( DEBUG_LEVEL_VERBOSE, " Prepare Receive SP (%p)...\n",*it); 554 (*it)->prepareForEnable(time_to_enable_at); 555 } 556 } 557 558 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 559 it != m_TransmitProcessors.end(); 560 ++it ) { 561 if(*it != m_SyncSource) { 562 debugOutput( DEBUG_LEVEL_VERBOSE, " Prepare Transmit SP (%p)...\n",*it); 563 (*it)->prepareForEnable(time_to_enable_at); 564 } 565 } 566 567 // then we enable the streamprocessors 568 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 569 it != m_ReceiveProcessors.end(); 570 ++it ) { 571 if(*it != m_SyncSource) { 572 debugOutput( DEBUG_LEVEL_VERBOSE, " Enable Receive SP (%p)...\n",*it); 573 (*it)->enable(time_to_enable_at); 574 } 575 } 576 577 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 578 it != m_TransmitProcessors.end(); 579 ++it ) { 580 if(*it != m_SyncSource) { 581 debugOutput( DEBUG_LEVEL_VERBOSE, " Enable Transmit SP (%p)...\n",*it); 582 (*it)->enable(time_to_enable_at); 583 } 584 } 585 586 // now we wait for the SP's to get enabled 587 debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for all StreamProcessors to be enabled...\n"); 588 // we have to wait until all streamprocessors indicate that they are running 589 // i.e. that there is actually some data stream flowing 590 int wait_cycles=ENABLE_TIMEOUT_MSEC; // two seconds 591 bool notEnabled=true; 592 while (notEnabled && wait_cycles) { 593 wait_cycles--; 594 notEnabled=false; 595 596 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 597 it != m_ReceiveProcessors.end(); 598 ++it ) { 599 if(!(*it)->isEnabled()) notEnabled=true; 600 } 601 602 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 603 it != m_TransmitProcessors.end(); 604 ++it ) { 605 if(!(*it)->isEnabled()) notEnabled=true; 606 } 607 usleep(1000); // one cycle 608 } 609 610 if(!wait_cycles) { // timout has occurred 611 debugFatal("One or more streams couldn't be enabled (timeout):\n"); 612 613 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 614 it != m_ReceiveProcessors.end(); 615 ++it ) { 616 if(!(*it)->isEnabled()) { 617 debugFatal(" receive stream %p not enabled\n",*it); 618 } else { 619 debugFatal(" receive stream %p enabled\n",*it); 620 } 621 } 622 623 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 624 it != m_TransmitProcessors.end(); 625 ++it ) { 626 if(!(*it)->isEnabled()) { 627 debugFatal(" transmit stream %p not enabled\n",*it); 628 } else { 629 debugFatal(" transmit stream %p enabled\n",*it); 630 } 631 } 632 return false; 633 } 634 635 debugOutput( DEBUG_LEVEL_VERBOSE, " => all StreamProcessors enabled...\n"); 636 637 return true; 638 } 639 640 /** 641 * Disables the registered StreamProcessors 642 * @return true if successful, false otherwise 643 */ 644 bool StreamProcessorManager::disableStreamProcessors() { 645 // we prepare the streamprocessors for disable 646 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 647 it != m_ReceiveProcessors.end(); 648 ++it ) { 649 (*it)->prepareForDisable(); 650 } 651 652 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 653 it != m_TransmitProcessors.end(); 654 ++it ) { 655 (*it)->prepareForDisable(); 656 } 657 658 // then we disable the streamprocessors 659 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 660 it != m_ReceiveProcessors.end(); 661 ++it ) { 662 (*it)->disable(); 663 } 664 665 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 666 it != m_TransmitProcessors.end(); 667 ++it ) { 668 (*it)->disable(); 669 } 670 671 // now we wait for the SP's to get disabled 672 debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for all StreamProcessors to be disabled...\n"); 673 // we have to wait until all streamprocessors indicate that they are running 674 // i.e. that there is actually some data stream flowing 675 int wait_cycles=ENABLE_TIMEOUT_MSEC; // two seconds 676 bool enabled=true; 677 while (enabled && wait_cycles) { 678 wait_cycles--; 679 enabled=false; 680 681 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 682 it != m_ReceiveProcessors.end(); 683 ++it ) { 684 if((*it)->isEnabled()) enabled=true; 685 } 686 687 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 688 it != m_TransmitProcessors.end(); 689 ++it ) { 690 if((*it)->isEnabled()) enabled=true; 691 } 692 usleep(1000); // one cycle 693 } 694 695 if(!wait_cycles) { // timout has occurred 696 debugFatal("One or more streams couldn't be disabled (timeout):\n"); 697 698 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 699 it != m_ReceiveProcessors.end(); 700 ++it ) { 701 if(!(*it)->isEnabled()) { 702 debugFatal(" receive stream %p not enabled\n",*it); 703 } else { 704 debugFatal(" receive stream %p enabled\n",*it); 705 } 706 } 707 708 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 709 it != m_TransmitProcessors.end(); 710 ++it ) { 711 if(!(*it)->isEnabled()) { 712 debugFatal(" transmit stream %p not enabled\n",*it); 713 } else { 714 debugFatal(" transmit stream %p enabled\n",*it); 715 } 716 } 717 return false; 718 } 719 720 debugOutput( DEBUG_LEVEL_VERBOSE, " => all StreamProcessors disabled...\n"); 721 691 it != m_TransmitProcessors.end(); 692 ++it ) { 693 if (!m_isoManager->unregisterStream(*it)) { 694 debugOutput(DEBUG_LEVEL_VERBOSE,"Could not unregister transmit stream processor (%p) from the Iso manager\n",*it); 695 return false; 696 } 697 } 722 698 return true; 723 699 } … … 733 709 734 710 debugOutput( DEBUG_LEVEL_VERBOSE, "Handling Xrun ...\n"); 711 712 dumpInfo(); 735 713 736 714 /* … … 743 721 * 3) Re-enable the SP's 744 722 */ 745 debugOutput( DEBUG_LEVEL_VERBOSE, "Disabling StreamProcessors...\n"); 746 if (!disableStreamProcessors()) { 747 debugFatal("Could not disable StreamProcessors...\n"); 723 724 // put all SP's back into dry-running state 725 if (!startDryRunning()) { 726 debugFatal("Could not put SP's in dry-running state\n"); 748 727 return false; 749 728 } … … 771 750 bool StreamProcessorManager::waitForPeriod() { 772 751 int time_till_next_period; 773 bool xrun_occurred =false;752 bool xrun_occurred = false; 774 753 775 754 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "enter...\n"); … … 799 778 xrun_occurred |= (*it)->xrunOccurred(); 800 779 } 780 if(xrun_occurred) break; 801 781 802 782 // check if we were waked up too soon 803 time_till_next_period=m_SyncSource->getTimeUntilNextPeriodSignalUsecs(); 804 } 805 806 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "delayed for %d usecs...\n", time_till_next_period); 807 808 // this is to notify the client of the delay 809 // that we introduced 810 m_delayed_usecs=time_till_next_period; 783 time_till_next_period = m_SyncSource->getTimeUntilNextPeriodSignalUsecs(); 784 } 811 785 812 786 // we save the 'ideal' time of the transfer at this point, … … 816 790 // NOTE: before waitForPeriod() is called again, both the transmit 817 791 // and the receive processors should have done their transfer. 818 m_time_of_transfer =m_SyncSource->getTimeAtPeriod();792 m_time_of_transfer = m_SyncSource->getTimeAtPeriod(); 819 793 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "transfer at %llu ticks...\n", 820 794 m_time_of_transfer); 795 796 // normally we can transfer frames at this time, but in some cases this is not true 797 // e.g. when there are not enough frames in the receive buffer. 798 // however this doesn't have to be a problem, since we can wait some more until we 799 // have enough frames. There is only a problem once the ISO xmit doesn't have packets 800 // to transmit, or if the receive buffer overflows. These conditions are signaled by 801 // the iso threads 802 // check if xruns occurred on the Iso side. 803 // also check if xruns will occur should we transfer() now 804 #ifdef DEBUG 805 int waited = 0; 806 #endif 807 bool ready_for_transfer = false; 808 xrun_occurred = false; 809 while (!ready_for_transfer && !xrun_occurred) { 810 ready_for_transfer = true; 811 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 812 it != m_ReceiveProcessors.end(); 813 ++it ) { 814 ready_for_transfer &= ((*it)->canClientTransferFrames(m_period)); 815 xrun_occurred |= (*it)->xrunOccurred(); 816 } 817 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 818 it != m_TransmitProcessors.end(); 819 ++it ) { 820 ready_for_transfer &= ((*it)->canClientTransferFrames(m_period)); 821 xrun_occurred |= (*it)->xrunOccurred(); 822 } 823 if (!ready_for_transfer) { 824 usleep(125); // MAGIC: one cycle sleep... 825 826 // in order to avoid this in the future, we increase the sync delay of the sync source SP 827 int d = m_SyncSource->getSyncDelay() + TICKS_PER_CYCLE; 828 m_SyncSource->setSyncDelay(d); 829 830 #ifdef DEBUG 831 waited++; 832 #endif 833 } 834 } // we are either ready or an xrun occurred 835 836 #ifdef DEBUG 837 if(waited > 0) { 838 debugOutput(DEBUG_LEVEL_VERBOSE, "Waited %d x 125us due to SP not ready for transfer\n", waited); 839 } 840 #endif 841 842 // this is to notify the client of the delay that we introduced by waiting 843 m_delayed_usecs = - m_SyncSource->getTimeUntilNextPeriodSignalUsecs(); 844 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "delayed for %d usecs...\n", m_delayed_usecs); 821 845 822 846 #ifdef DEBUG … … 833 857 } 834 858 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "XF at %011llu ticks, RBF=%d, XBF=%d, SUM=%d...\n", 835 m_time_of_transfer,rcv_bf,xmt_bf,rcv_bf+xmt_bf); 836 837 #endif 838 839 xrun_occurred=false; 859 m_time_of_transfer, rcv_bf, xmt_bf, rcv_bf+xmt_bf); 840 860 841 861 // check if xruns occurred on the Iso side. 842 862 // also check if xruns will occur should we transfer() now 843 844 863 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 845 864 it != m_ReceiveProcessors.end(); 846 865 ++it ) { 847 // a xrun has occurred on the Iso side 848 xrun_occurred |= (*it)->xrunOccurred(); 849 850 // if this is true, a xrun will occur 851 xrun_occurred |= !((*it)->canClientTransferFrames(m_period)); 852 853 #ifdef DEBUG 866 854 867 if ((*it)->xrunOccurred()) { 855 debugWarning("Xrun on RECV SP %p due to ISO xrun\n",*it);868 debugWarning("Xrun on RECV SP %p due to ISO side xrun\n",*it); 856 869 (*it)->dumpInfo(); 857 870 } 858 871 if (!((*it)->canClientTransferFrames(m_period))) { 859 debugWarning("Xrun on RECV SP %p due to buffer xrun\n",*it);872 debugWarning("Xrun on RECV SP %p due to buffer side xrun\n",*it); 860 873 (*it)->dumpInfo(); 861 874 } 862 #endif863 864 875 } 865 876 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 866 877 it != m_TransmitProcessors.end(); 867 878 ++it ) { 868 // a xrun has occurred on the Iso side869 xrun_occurred |= (*it)->xrunOccurred();870 871 // if this is true, a xrun will occur872 xrun_occurred |= !((*it)->canClientTransferFrames(m_period));873 874 #ifdef DEBUG875 879 if ((*it)->xrunOccurred()) { 876 debugWarning("Xrun on XMIT SP %p due to ISO xrun\n",*it);880 debugWarning("Xrun on XMIT SP %p due to ISO side xrun\n",*it); 877 881 } 878 882 if (!((*it)->canClientTransferFrames(m_period))) { 879 debugWarning("Xrun on XMIT SP %p due to buffer xrun\n",*it); 880 } 883 debugWarning("Xrun on XMIT SP %p due to buffer side xrun\n",*it); 884 } 885 } 881 886 #endif 882 }883 887 884 888 m_nbperiods++; 885 886 889 // now we can signal the client that we are (should be) ready 887 890 return !xrun_occurred; … … 896 899 */ 897 900 bool StreamProcessorManager::transfer() { 898 899 debugOutput( DEBUG_LEVEL_VERBOSE, "Transferring period...\n"); 900 901 if (!transfer(StreamProcessor::E_Receive)) return false; 902 if (!transfer(StreamProcessor::E_Transmit)) return false; 903 904 return true; 901 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n"); 902 bool retval=true; 903 retval &= transfer(StreamProcessor::ePT_Receive); 904 retval &= transfer(StreamProcessor::ePT_Transmit); 905 return retval; 905 906 } 906 907 … … 913 914 * @return true if successful, false otherwise (indicates xrun). 914 915 */ 915 916 bool StreamProcessorManager::transfer(enum StreamProcessor::EProcessorType t) { 917 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n"); 918 916 bool StreamProcessorManager::transfer(enum StreamProcessor::eProcessorType t) { 917 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "transfer(%d) at TS=%011llu (%03us %04uc %04ut)...\n", 918 t, m_time_of_transfer, 919 (unsigned int)TICKS_TO_SECS(m_time_of_transfer), 920 (unsigned int)TICKS_TO_CYCLES(m_time_of_transfer), 921 (unsigned int)TICKS_TO_OFFSET(m_time_of_transfer)); 922 923 bool retval = true; 919 924 // a static cast could make sure that there is no performance 920 925 // penalty for the virtual functions (to be checked) 921 if (t==StreamProcessor::E_Receive) { 922 923 // determine the time at which we want reception to start 924 float rate=m_SyncSource->getTicksPerFrame(); 925 int64_t one_frame_in_ticks=(int64_t)(((float)m_period)*rate); 926 927 int64_t receive_timestamp = substractTicks(m_time_of_transfer,one_frame_in_ticks); 928 929 if(receive_timestamp<0) { 930 debugWarning("receive ts < 0.0 : %lld, m_time_of_transfer= %llu, one_frame_in_ticks=%lld\n", 931 receive_timestamp, m_time_of_transfer, one_frame_in_ticks); 932 } 933 if(receive_timestamp>(128L*TICKS_PER_SECOND)) { 934 debugWarning("receive ts > 128L*TICKS_PER_SECOND : %lld, m_time_of_transfer= %llu, one_frame_in_ticks=%lld\n", 935 receive_timestamp, m_time_of_transfer, one_frame_in_ticks); 936 } 937 926 if (t==StreamProcessor::ePT_Receive) { 938 927 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 939 928 it != m_ReceiveProcessors.end(); 940 929 ++it ) { 941 942 if(!(*it)->getFrames(m_period, receive_timestamp)) { 943 debugOutput(DEBUG_LEVEL_VERBOSE,"could not getFrames(%u, %11llu) from stream processor (%p)\n", 930 if(!(*it)->getFrames(m_period, m_time_of_transfer)) { 931 debugWarning("could not getFrames(%u, %11llu) from stream processor (%p)\n", 944 932 m_period, m_time_of_transfer,*it); 945 return false; // buffer underrun 946 } 947 933 retval &= false; // buffer underrun 934 } 948 935 } 949 936 } else { 937 // FIXME: in the SPM it would be nice to have system time instead of 938 // 1394 time 939 float rate = m_SyncSource->getTicksPerFrame(); 940 int64_t one_ringbuffer_in_ticks=(int64_t)(((float)(m_nb_buffers * m_period)) * rate); 941 942 // the data we are putting into the buffer is intended to be transmitted 943 // one ringbuffer size after it has been received 944 int64_t transmit_timestamp = addTicks(m_time_of_transfer, one_ringbuffer_in_ticks); 945 950 946 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 951 947 it != m_TransmitProcessors.end(); 952 948 ++it ) { 953 954 if(!(*it)->putFrames(m_period, (int64_t)m_time_of_transfer)) { 955 debugOutput(DEBUG_LEVEL_VERBOSE, "could not putFrames(%u,%llu) to stream processor (%p)\n", 956 m_period, m_time_of_transfer, *it); 957 return false; // buffer overrun 958 } 959 960 } 961 } 962 963 return true; 949 // FIXME: in the SPM it would be nice to have system time instead of 950 // 1394 time 951 if(!(*it)->putFrames(m_period, transmit_timestamp)) { 952 debugWarning("could not putFrames(%u,%llu) to stream processor (%p)\n", 953 m_period, transmit_timestamp, *it); 954 retval &= false; // buffer underrun 955 } 956 } 957 } 958 return retval; 959 } 960 961 /** 962 * @brief Transfer one period of silence for both receive and transmit StreamProcessors 963 * 964 * Transfers one period of silence to the Iso side for transmit SP's 965 * or dump one period of frames for receive SP's 966 * 967 * @return true if successful, false otherwise (indicates xrun). 968 */ 969 bool StreamProcessorManager::transferSilence() { 970 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring silent period...\n"); 971 bool retval=true; 972 retval &= transferSilence(StreamProcessor::ePT_Receive); 973 retval &= transferSilence(StreamProcessor::ePT_Transmit); 974 return retval; 975 } 976 977 /** 978 * @brief Transfer one period of silence for either the receive or transmit StreamProcessors 979 * 980 * Transfers one period of silence to the Iso side for transmit SP's 981 * or dump one period of frames for receive SP's 982 * 983 * @param t The processor type to tranfer for (receive or transmit) 984 * @return true if successful, false otherwise (indicates xrun). 985 */ 986 bool StreamProcessorManager::transferSilence(enum StreamProcessor::eProcessorType t) { 987 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "transferSilence(%d) at TS=%011llu (%03us %04uc %04ut)...\n", 988 t, m_time_of_transfer, 989 (unsigned int)TICKS_TO_SECS(m_time_of_transfer), 990 (unsigned int)TICKS_TO_CYCLES(m_time_of_transfer), 991 (unsigned int)TICKS_TO_OFFSET(m_time_of_transfer)); 992 993 bool retval = true; 994 // a static cast could make sure that there is no performance 995 // penalty for the virtual functions (to be checked) 996 if (t==StreamProcessor::ePT_Receive) { 997 for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin(); 998 it != m_ReceiveProcessors.end(); 999 ++it ) { 1000 if(!(*it)->dropFrames(m_period, m_time_of_transfer)) { 1001 debugWarning("could not dropFrames(%u, %11llu) from stream processor (%p)\n", 1002 m_period, m_time_of_transfer,*it); 1003 retval &= false; // buffer underrun 1004 } 1005 } 1006 } else { 1007 // FIXME: in the SPM it would be nice to have system time instead of 1008 // 1394 time 1009 float rate = m_SyncSource->getTicksPerFrame(); 1010 int64_t one_ringbuffer_in_ticks=(int64_t)(((float)(m_nb_buffers * m_period)) * rate); 1011 1012 // the data we are putting into the buffer is intended to be transmitted 1013 // one ringbuffer size after it has been received 1014 int64_t transmit_timestamp = addTicks(m_time_of_transfer, one_ringbuffer_in_ticks); 1015 1016 for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin(); 1017 it != m_TransmitProcessors.end(); 1018 ++it ) { 1019 // FIXME: in the SPM it would be nice to have system time instead of 1020 // 1394 time 1021 if(!(*it)->putSilenceFrames(m_period, transmit_timestamp)) { 1022 debugWarning("could not putSilenceFrames(%u,%llu) to stream processor (%p)\n", 1023 m_period, transmit_timestamp, *it); 1024 retval &= false; // buffer underrun 1025 } 1026 } 1027 } 1028 return retval; 964 1029 } 965 1030 trunk/libffado/src/libstreaming/StreamProcessorManager.h
r445 r734 25 25 #define __FFADO_STREAMPROCESSORMANAGER__ 26 26 27 #include "generic/Port.h" 28 #include "generic/StreamProcessor.h" 29 #include "util/IsoHandlerManager.h" 30 27 31 #include "debugmodule/debugmodule.h" 28 32 #include "libutil/Thread.h" 29 33 #include "libutil/OptionContainer.h" 30 #include <semaphore.h>31 #include "Port.h"32 #include "StreamProcessor.h"33 #include "IsoHandlerManager.h"34 34 35 35 #include <vector> 36 #include <semaphore.h> 36 37 37 38 namespace Streaming { … … 52 53 public: 53 54 54 StreamProcessorManager(unsigned int period, unsigned int nb_buffers);55 StreamProcessorManager(unsigned int period, unsigned int rate, unsigned int nb_buffers); 55 56 virtual ~StreamProcessorManager(); 56 57 … … 61 62 bool stop(); 62 63 64 bool startDryRunning(); 63 65 bool syncStartAll(); 64 66 … … 67 69 bool unregisterProcessor(StreamProcessor *processor); ///< stop managing a streamprocessor 68 70 69 bool enableStreamProcessors(uint64_t time_to_enable_at); /// enable registered StreamProcessors70 bool disableStreamProcessors(); /// disable registered StreamProcessors71 72 71 void setPeriodSize(unsigned int period); 73 72 void setPeriodSize(unsigned int period, unsigned int nb_buffers); 74 int getPeriodSize() {return m_period;};73 unsigned int getPeriodSize() {return m_period;}; 75 74 76 75 void setNbBuffers(unsigned int nb_buffers); … … 82 81 83 82 // the client-side functions 83 bool waitForPeriod(); 84 bool transfer(); 85 bool transfer(enum StreamProcessor::eProcessorType); 86 private: 87 bool transferSilence(); 88 bool transferSilence(enum StreamProcessor::eProcessorType); 84 89 85 bool waitForPeriod(); ///< wait for the next period 86 87 bool transfer(); ///< transfer the buffer contents from/to client 88 bool transfer(enum StreamProcessor::EProcessorType); ///< transfer the buffer contents from/to client (single processor type) 89 90 bool alignReceivedStreams(); 91 public: 90 92 int getDelayedUsecs() {return m_delayed_usecs;}; 91 93 bool xrunOccurred(); 92 94 int getXrunCount() {return m_xruns;}; 95 96 unsigned int getNominalRate() {return m_nominal_framerate;}; 97 uint64_t getTimeOfLastTransfer() { return m_time_of_transfer;}; 93 98 94 99 private: … … 116 121 public: 117 122 bool setSyncSource(StreamProcessor *s); 118 StreamProcessor * getSyncSource(); 123 StreamProcessor& getSyncSource() 124 {return *m_SyncSource;}; 119 125 120 126 protected: … … 132 138 unsigned int m_nb_buffers; 133 139 unsigned int m_period; 140 unsigned int m_nominal_framerate; 134 141 unsigned int m_xruns; 135 142 trunk/libffado/src/libutil/StreamStatistics.cpp
r445 r734 26 26 27 27 namespace Streaming { 28 IMPL_DEBUG_MODULE( StreamStatistics, StreamStatistics, DEBUG_LEVEL_VERBOSE ); 28 29 29 30 StreamStatistics::StreamStatistics() … … 35 36 , m_sum(0) 36 37 { 37 38 } 39 40 41 StreamStatistics::~StreamStatistics() 42 { 38 reset(); 43 39 } 44 40 … … 51 47 } 52 48 49 void StreamStatistics::signal(unsigned int val) { 50 if (val <= MAX_SIGNAL_VALUE) { 51 m_signalled[val]++; 52 } 53 } 54 53 55 void StreamStatistics::dumpInfo() { 54 printf("--- Stats for %s: min=%ld avg=%f max=%ld cnt=%ld sum=%ld\n",m_name.c_str(), 55 m_min,m_average,m_max,m_count,m_sum); 56 debugOutputShort( DEBUG_LEVEL_VERBOSE, 57 "--- Stats for %s: min=%ld avg=%f max=%ld cnt=%ld sum=%ld\n", 58 m_name.c_str(), m_min, m_average, m_max, m_count, m_sum); 59 debugOutputShort( DEBUG_LEVEL_VERBOSE, " Signal stats\n"); 60 for (unsigned int i=0;i <= MAX_SIGNAL_VALUE; i++) { 61 debugOutputShort(DEBUG_LEVEL_VERBOSE, 62 " Stats for %3u: %8u\n", 63 i, m_signalled[i]); 64 } 56 65 } 57 66 … … 62 71 m_max=0; 63 72 m_sum=0; 73 74 for (unsigned int i=0;i <= MAX_SIGNAL_VALUE; i++) { 75 m_signalled[i]=0; 76 } 64 77 } 65 78 trunk/libffado/src/libutil/StreamStatistics.h
r445 r734 27 27 #include <string> 28 28 29 #include "debugmodule/debugmodule.h" 30 31 #define MAX_SIGNAL_VALUE 7 29 32 namespace Streaming { 30 33 … … 33 36 StreamStatistics(); 34 37 35 ~StreamStatistics() ;38 ~StreamStatistics() {}; 36 39 37 40 void setName(std::string n) {m_name=n;}; … … 50 53 long m_sum; 51 54 55 // some tools to do run statistics 56 // will keep a histogram of the number of times a certain value 57 // is added. 58 void signal(unsigned int val); 59 60 unsigned int m_signalled[MAX_SIGNAL_VALUE+1]; 61 52 62 private: 53 63 DECLARE_DEBUG_MODULE; 54 64 }; 55 65 trunk/libffado/src/libutil/TimestampedBuffer.cpp
r512 r734 28 28 29 29 #include "libutil/Atomic.h" 30 #include "libstreaming/ cycletimer.h"30 #include "libstreaming/util/cycletimer.h" 31 31 32 32 #include "TimestampedBuffer.h" … … 45 45 #define DLL_COEFF_C (DLL_OMEGA * DLL_OMEGA) 46 46 47 #define ENTER_CRITICAL_SECTION { \ 48 pthread_mutex_lock(&m_framecounter_lock); \ 49 } 50 #define EXIT_CRITICAL_SECTION { \ 51 pthread_mutex_unlock(&m_framecounter_lock); \ 52 } 53 47 54 namespace Util { 48 55 … … 53 60 m_event_size(0), m_events_per_frame(0), m_buffer_size(0), 54 61 m_bytes_per_frame(0), m_bytes_per_buffer(0), 62 m_enabled( false ), m_transparent ( true ), 55 63 m_wrap_at(0xFFFFFFFFFFFFFFFFLLU), 56 64 m_Client(c), m_framecounter(0), … … 122 130 ffado_timestamp_t diff; 123 131 124 pthread_mutex_lock(&m_framecounter_lock);132 ENTER_CRITICAL_SECTION; 125 133 diff=m_buffer_next_tail_timestamp - m_buffer_tail_timestamp; 126 pthread_mutex_unlock(&m_framecounter_lock);134 EXIT_CRITICAL_SECTION; 127 135 128 136 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"getRate: %f/%f=%f\n", … … 139 147 diff += m_wrap_at; 140 148 } 141 149 142 150 float rate=((float)diff)/((float) m_update_period); 151 if (rate<0.0) debugError("rate < 0! (%f)\n",rate); 143 152 if (fabsf(m_nominal_rate - rate)>(m_nominal_rate*0.1)) { 144 153 debugWarning("(%p) rate (%10.5f) more that 10%% off nominal (rate=%10.5f, diff="TIMESTAMP_FORMAT_SPEC", update_period=%d)\n", 145 154 this, rate,m_nominal_rate,diff, m_update_period); 146 dumpInfo(); 155 147 156 return m_nominal_rate; 148 157 } else { … … 208 217 // of the new offset. Doing so certainly makes for a smoother MOTU 209 218 // startup. 210 pthread_mutex_lock(&m_framecounter_lock);219 ENTER_CRITICAL_SECTION; 211 220 m_buffer_tail_timestamp = m_buffer_tail_timestamp - m_tick_offset + nticks; 212 221 m_buffer_next_tail_timestamp = (ffado_timestamp_t)((double)m_buffer_tail_timestamp + m_dll_e2); 213 222 m_tick_offset=nticks; 214 pthread_mutex_unlock(&m_framecounter_lock);223 EXIT_CRITICAL_SECTION; 215 224 216 225 return true; … … 225 234 * 226 235 * In order to get the number of frames in the buffer, use the 227 * get FrameCounter, getBufferHeadTimestamp, getBufferTailTimestamp236 * getBufferHeadTimestamp, getBufferTailTimestamp 228 237 * functions 229 238 * … … 257 266 * @return true if successful 258 267 */ 259 bool TimestampedBuffer::reset() { 268 bool TimestampedBuffer::clearBuffer() { 269 debugOutput(DEBUG_LEVEL_VERBOSE, "Clearing buffer\n"); 260 270 ffado_ringbuffer_reset(m_event_buffer); 261 262 271 resetFrameCounter(); 263 264 272 return true; 265 273 } … … 348 356 349 357 // increment without updating the DLL 350 pthread_mutex_lock(&m_framecounter_lock);358 ENTER_CRITICAL_SECTION; 351 359 m_framecounter++; 352 pthread_mutex_unlock(&m_framecounter_lock);360 EXIT_CRITICAL_SECTION; 353 361 354 362 return true; … … 370 378 unsigned int write_size=nframes*m_event_size*m_events_per_frame; 371 379 380 if (m_transparent) { 381 // while disabled, we don't update the DLL, nor do we write frames 382 // we just set the correct timestamp for the frames 383 setBufferTailTimestamp(ts); 384 } else { 385 // add the data payload to the ringbuffer 386 size_t written = ffado_ringbuffer_write(m_event_buffer, data, write_size); 387 if (written < write_size) 388 { 389 debugWarning("ringbuffer full, %u, %u\n", write_size, written); 390 return false; 391 } 392 incrementFrameCounter(nframes,ts); 393 } 394 return true; 395 } 396 397 /** 398 * @brief Preload frames into the buffer 399 * 400 * Preload \ref nframes of frames from the buffer pointed to by \ref data to the 401 * internal ringbuffer. Does not care about transparency. Keeps the buffer head or tail 402 * timestamp constant. 403 * 404 * @note not thread safe 405 * 406 * @param nframes number of frames to copy 407 * @param data pointer to the frame buffer 408 * @param keep_head_ts if true, keep the head timestamp constant. If false, keep the 409 * tail timestamp constant. 410 * @return true if successful 411 */ 412 bool TimestampedBuffer::preloadFrames(unsigned int nframes, char *data, bool keep_head_ts) { 413 unsigned int write_size = nframes * m_event_size * m_events_per_frame; 372 414 // add the data payload to the ringbuffer 373 if (ffado_ringbuffer_write(m_event_buffer,data,write_size) < write_size) 415 size_t written = ffado_ringbuffer_write(m_event_buffer, data, write_size); 416 if (written < write_size) 374 417 { 375 // debugWarning("writeFrames buffer overrun\n");418 debugWarning("ringbuffer full, request: %u, actual: %u\n", write_size, written); 376 419 return false; 377 420 } 378 379 incrementFrameCounter(nframes,ts); 380 381 return true; 382 383 } 421 422 // make sure the head timestamp remains identical 423 signed int fc; 424 ffado_timestamp_t ts; 425 426 if (keep_head_ts) { 427 getBufferHeadTimestamp(&ts, &fc); 428 } else { 429 getBufferTailTimestamp(&ts, &fc); 430 } 431 // update frame counter 432 m_framecounter += nframes; 433 if (keep_head_ts) { 434 setBufferHeadTimestamp(ts); 435 } else { 436 setBufferTailTimestamp(ts); 437 } 438 439 return true; 440 } 441 442 /** 443 * @brief Drop frames from the head of the buffer 444 * 445 * drops \ref nframes of frames from the head of internal buffer 446 * 447 * @param nframes number of frames to drop 448 * @return true if successful 449 */ 450 bool 451 TimestampedBuffer::dropFrames(unsigned int nframes) { 452 unsigned int read_size = nframes * m_event_size * m_events_per_frame; 453 ffado_ringbuffer_read_advance(m_event_buffer, read_size); 454 decrementFrameCounter(nframes); 455 return true; 456 } 457 384 458 /** 385 459 * @brief Read frames from the buffer … … 396 470 unsigned int read_size=nframes*m_event_size*m_events_per_frame; 397 471 398 // get the data payload to the ringbuffer 399 if ((ffado_ringbuffer_read(m_event_buffer,data,read_size)) < read_size) 400 { 401 // debugWarning("readFrames buffer underrun\n"); 402 return false; 403 } 404 405 decrementFrameCounter(nframes); 406 407 return true; 408 472 if (m_transparent) { 473 return true; // FIXME: the data still doesn't make sense! 474 } else { 475 // get the data payload to the ringbuffer 476 if ((ffado_ringbuffer_read(m_event_buffer,data,read_size)) < read_size) 477 { 478 debugWarning("readFrames buffer underrun\n"); 479 return false; 480 } 481 decrementFrameCounter(nframes); 482 } 483 return true; 409 484 } 410 485 … … 453 528 454 529 if(vec[0].len==0) { // this indicates a full event buffer 455 debugError("Event buffer overrun in buffer %p\n",this); 456 break; 530 debugError("Event buffer overrun in buffer %p, fill: %u, bytes2write: %u \n", 531 this, ffado_ringbuffer_read_space(m_event_buffer), bytes2write); 532 debugShowBackLog(); 533 return false; 457 534 } 458 535 … … 651 728 #endif 652 729 653 pthread_mutex_lock(&m_framecounter_lock);730 ENTER_CRITICAL_SECTION; 654 731 655 732 m_buffer_tail_timestamp = ts; … … 658 735 m_buffer_next_tail_timestamp = (ffado_timestamp_t)((double)m_buffer_tail_timestamp + m_dll_e2); 659 736 660 pthread_mutex_unlock(&m_framecounter_lock);661 662 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " Set buffer tail timestampfor (%p) to "737 EXIT_CRITICAL_SECTION; 738 739 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "for (%p) to " 663 740 TIMESTAMP_FORMAT_SPEC" => "TIMESTAMP_FORMAT_SPEC", NTS=" 664 741 TIMESTAMP_FORMAT_SPEC", DLL2=%f, RATE=%f\n", 665 this, new_timestamp, ts, m_buffer_next_tail_timestamp, m_dll_e2, m_nominal_rate);742 this, new_timestamp, ts, m_buffer_next_tail_timestamp, m_dll_e2, getRate()); 666 743 667 744 } … … 687 764 #endif 688 765 689 ffado_timestamp_t ts =new_timestamp;690 691 pthread_mutex_lock(&m_framecounter_lock);766 ffado_timestamp_t ts = new_timestamp; 767 768 ENTER_CRITICAL_SECTION; 692 769 693 770 // add the time … … 705 782 m_buffer_next_tail_timestamp = (ffado_timestamp_t)((double)m_buffer_tail_timestamp + m_dll_e2); 706 783 707 pthread_mutex_unlock(&m_framecounter_lock);708 709 debugOutput(DEBUG_LEVEL_VER Y_VERBOSE, "Set buffer head timestampfor (%p) to "TIMESTAMP_FORMAT_SPEC" => "784 EXIT_CRITICAL_SECTION; 785 786 debugOutput(DEBUG_LEVEL_VERBOSE, "for (%p) to "TIMESTAMP_FORMAT_SPEC" => " 710 787 TIMESTAMP_FORMAT_SPEC", NTS="TIMESTAMP_FORMAT_SPEC", DLL2=%f, RATE=%f\n", 711 this, new_timestamp, ts, m_buffer_next_tail_timestamp, m_dll_e2, m_nominal_rate); 712 788 this, new_timestamp, ts, m_buffer_next_tail_timestamp, m_dll_e2, getRate()); 789 790 } 791 792 /** 793 * @brief Synchronize the buffer head to a specified timestamp 794 * 795 * Try to synchronize the buffer head to a specific timestamp. This 796 * can mean adding or removing samples to/from the buffer such that 797 * the buffer head aligns with the specified timestamp. The alignment 798 * is within ts +/- Tsample/2 799 * 800 * @param target the timestamp to align to 801 * @return true if alignment succeeded, false if not 802 */ 803 bool 804 TimestampedBuffer::syncBufferHeadToTimestamp(ffado_timestamp_t target) 805 { 806 uint64_t ts_head; 807 uint64_t ts_target=(uint64_t)target; 808 signed int fc; 809 int32_t lag_ticks; 810 float lag_frames; 811 812 ffado_timestamp_t ts_head_tmp; 813 getBufferHeadTimestamp(&ts_head_tmp, &fc); 814 ts_head=(uint64_t)ts_head_tmp; 815 // if target > ts_head then the wanted buffer head timestamp 816 // is later than the actual. This means that we (might) have to drop 817 // some frames. 818 lag_ticks=diffTicks(ts_target, ts_head); 819 float rate=getRate(); 820 821 assert(rate!=0.0); 822 823 lag_frames=(((float)lag_ticks)/rate); 824 825 debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): HEAD=%llu, TS=%llu, diff=%ld = %10.5f frames (rate=%10.5f)\n", 826 this, ts_head, ts_target, lag_ticks, lag_frames, rate); 827 828 if (lag_frames>=1.0) { 829 // the buffer head is too early 830 // ditch frames until the buffer head is on time 831 char dummy[getBytesPerFrame()]; // one frame of garbage 832 int frames_to_ditch=(int)roundf(lag_frames); 833 debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): ditching %d frames (@ ts=%lld)\n",this,frames_to_ditch,ts_target); 834 835 while (frames_to_ditch--) { 836 readFrames(1, dummy); 837 } 838 839 } else if (lag_frames<=-1.0) { 840 // the buffer head is too late 841 // add some padding frames 842 int frames_to_add=(int)roundf(lag_frames); 843 debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): adding %d frames (@ ts=%lld)\n",this,-frames_to_add,ts_target); 844 845 while (frames_to_add++) { 846 writeDummyFrame(); 847 } 848 } 849 getBufferHeadTimestamp(&ts_head_tmp, &fc); 850 ts_head=(uint64_t)ts_head_tmp; 851 debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): new HEAD=%llu, fc=%d, target=%llu, new diff=%lld\n", 852 this, ts_head, fc, ts_target, diffTicks(ts_target, ts_head)); 853 // FIXME: of course this doesn't always succeed 854 return true; 855 } 856 857 /** 858 * @brief Synchronize the buffer tail to a specified timestamp 859 * 860 * Try to synchronize the buffer tail to a specific timestamp. This 861 * can mean adding or removing samples to/from the buffer such that 862 * the buffer tail aligns with the specified timestamp. The alignment 863 * is within ts +/- Tsample/2 864 * 865 * @param target the timestamp to align to 866 * @return true if alignment succeeded, false if not 867 */ 868 bool 869 TimestampedBuffer::syncBufferTailToTimestamp(ffado_timestamp_t target) 870 { 871 uint64_t ts_tail; 872 uint64_t ts_target=(uint64_t)target; 873 signed int fc; 874 int32_t lag_ticks; 875 float lag_frames; 876 877 debugWarning("Untested\n"); 878 879 ffado_timestamp_t ts_tail_tmp; 880 getBufferTailTimestamp(&ts_tail_tmp, &fc); 881 ts_tail=(uint64_t)ts_tail_tmp; 882 // if target < ts_tail then the wanted buffer head timestamp 883 // is later than the actual. This means that we (might) have to drop 884 // some frames. 885 lag_ticks=diffTicks(ts_tail, ts_target); 886 float rate=getRate(); 887 888 assert(rate!=0.0); 889 890 lag_frames=(((float)lag_ticks)/rate); 891 892 debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): HEAD=%llu, TS=%llu, diff=%ld = %10.5f frames (rate=%10.5f)\n", 893 this, ts_tail, ts_target, lag_ticks, lag_frames, rate); 894 895 if (lag_frames>=1.0) { 896 // the buffer head is too early 897 // ditch frames until the buffer head is on time 898 char dummy[getBytesPerFrame()]; // one frame of garbage 899 int frames_to_ditch=(int)roundf(lag_frames); 900 debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): ditching %d frames (@ ts=%lld)\n",this,frames_to_ditch,ts_target); 901 902 while (frames_to_ditch--) { 903 readFrames(1, dummy); 904 } 905 906 } else if (lag_frames<=-1.0) { 907 // the buffer head is too late 908 // add some padding frames 909 int frames_to_add=(int)roundf(lag_frames); 910 debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): adding %d frames (@ ts=%lld)\n",this,-frames_to_add,ts_target); 911 912 while (frames_to_add++) { 913 writeDummyFrame(); 914 } 915 } 916 getBufferHeadTimestamp(&ts_tail_tmp, &fc); 917 ts_tail=(uint64_t)ts_tail_tmp; 918 debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): new HEAD=%llu, fc=%d, target=%llu, new diff=%lld\n", 919 this, ts_tail, fc, ts_target, diffTicks(ts_target, ts_tail)); 920 // FIXME: of course this doesn't always succeed 921 return true; 922 } 923 924 /** 925 * @brief correct lag 926 * 927 * Try to synchronize the buffer tail to a specific timestamp. This 928 * can mean adding or removing samples to/from the buffer such that 929 * the buffer tail aligns with the specified timestamp. The alignment 930 * is within ts +/- Tsample/2 931 * 932 * @param target the timestamp to align to 933 * @return true if alignment succeeded, false if not 934 */ 935 bool 936 TimestampedBuffer::syncCorrectLag(int64_t lag_ticks) 937 { 938 float lag_frames; 939 float rate=getRate(); 940 assert(rate!=0.0); 941 942 lag_frames=(((float)lag_ticks)/rate); 943 if (lag_frames >= 1.0) { 944 // the buffer head is too late 945 // add some padding frames 946 int frames_to_add=(int)roundf(lag_frames); 947 debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): adding %d frames\n",this,frames_to_add); 948 949 while (frames_to_add++) { 950 writeDummyFrame(); 951 } 952 } else if (lag_frames <= -1.0) { 953 // the buffer head is too early 954 // ditch frames until the buffer head is on time 955 char dummy[getBytesPerFrame()]; // one frame of garbage 956 int frames_to_ditch=(int)roundf(lag_frames); 957 debugOutput( DEBUG_LEVEL_VERBOSE, "(%p): ditching %d frames\n",this,-frames_to_ditch); 958 959 while (frames_to_ditch--) { 960 readFrames(1, dummy); 961 } 962 } 963 return true; 713 964 } 714 965 … … 741 992 */ 742 993 void TimestampedBuffer::getBufferTailTimestamp(ffado_timestamp_t *ts, signed int *fc) { 743 pthread_mutex_lock(&m_framecounter_lock);994 ENTER_CRITICAL_SECTION; 744 995 *fc = m_framecounter; 745 996 *ts = m_buffer_tail_timestamp; 746 pthread_mutex_unlock(&m_framecounter_lock);997 EXIT_CRITICAL_SECTION; 747 998 } 748 999 … … 764 1015 ffado_timestamp_t timestamp; 765 1016 766 pthread_mutex_lock(&m_framecounter_lock);767 1017 ENTER_CRITICAL_SECTION; 1018 768 1019 diff=m_buffer_next_tail_timestamp - m_buffer_tail_timestamp; 769 1020 timestamp=m_buffer_tail_timestamp; 770 1021 771 pthread_mutex_unlock(&m_framecounter_lock);1022 EXIT_CRITICAL_SECTION; 772 1023 773 1024 if (diff < 0) diff += m_wrap_at; … … 804 1055 */ 805 1056 void TimestampedBuffer::resetFrameCounter() { 806 pthread_mutex_lock(&m_framecounter_lock);1057 ENTER_CRITICAL_SECTION; 807 1058 m_framecounter = 0; 808 pthread_mutex_unlock(&m_framecounter_lock);1059 EXIT_CRITICAL_SECTION; 809 1060 } 810 1061 … … 815 1066 */ 816 1067 void TimestampedBuffer::decrementFrameCounter(int nbframes) { 817 pthread_mutex_lock(&m_framecounter_lock);1068 ENTER_CRITICAL_SECTION; 818 1069 m_framecounter -= nbframes; 819 pthread_mutex_unlock(&m_framecounter_lock);1070 EXIT_CRITICAL_SECTION; 820 1071 } 821 1072 … … 835 1086 ffado_timestamp_t diff; 836 1087 837 pthread_mutex_lock(&m_framecounter_lock);838 diff =m_buffer_next_tail_timestamp - m_buffer_tail_timestamp;839 pthread_mutex_unlock(&m_framecounter_lock);1088 ENTER_CRITICAL_SECTION; 1089 diff = m_buffer_next_tail_timestamp - m_buffer_tail_timestamp; 1090 EXIT_CRITICAL_SECTION; 840 1091 841 1092 if (diff < 0) diff += m_wrap_at; … … 845 1096 #endif 846 1097 847 ffado_timestamp_t ts =new_timestamp;1098 ffado_timestamp_t ts = new_timestamp; 848 1099 ts += m_tick_offset; 849 1100 … … 854 1105 } 855 1106 856 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Setting buffer tail timestamp for (%p) to "857 TIMESTAMP_FORMAT_SPEC" => "TIMESTAMP_FORMAT_SPEC"\n",858 this, new_timestamp, ts);859 860 1107 #ifdef DEBUG 861 1108 if (new_timestamp >= m_wrap_at) { 862 debugWarning("timestamp not wrapped: "TIMESTAMP_FORMAT_SPEC"\n", new_timestamp);1109 debugWarning("timestamp not wrapped: "TIMESTAMP_FORMAT_SPEC"\n", new_timestamp); 863 1110 } 864 1111 if ((ts >= m_wrap_at) || (ts < 0 )) { … … 868 1115 // FIXME: JMW: at some points during startup the timestamp doesn't change. 869 1116 // This still needs to be verified in more detail. 870 if (ts>m_buffer_tail_timestamp-1 && ts<m_buffer_tail_timestamp+1) { 871 pthread_mutex_lock(&m_framecounter_lock); 872 m_framecounter += nbframes; 873 pthread_mutex_unlock(&m_framecounter_lock); 874 return; 875 } 876 877 // update the DLL 878 pthread_mutex_lock(&m_framecounter_lock); 879 diff = ts-m_buffer_next_tail_timestamp; 880 pthread_mutex_unlock(&m_framecounter_lock); 881 882 #ifdef DEBUG 883 if ((diff > ((ffado_timestamp_t)1000)) || (diff < ((ffado_timestamp_t)-1000))) { 884 debugWarning("(%p) difference rather large: "TIMESTAMP_FORMAT_SPEC", "TIMESTAMP_FORMAT_SPEC", "TIMESTAMP_FORMAT_SPEC"\n", 885 this, diff, ts, m_buffer_next_tail_timestamp); 886 } 887 #endif 888 889 // idea to implement it for nbframes values that differ from m_update_period: 890 // diff = diff * nbframes/m_update_period 891 // m_buffer_next_tail_timestamp = m_buffer_tail_timestamp + diff 1117 // if (ts>m_buffer_tail_timestamp-1 && ts<m_buffer_tail_timestamp+1) { 1118 // ENTER_CRITICAL_SECTION; 1119 // m_framecounter += nbframes; 1120 // EXIT_CRITICAL_SECTION; 1121 // return; 1122 // } 1123 ffado_timestamp_t pred_buffer_next_tail_timestamp; 1124 if(nbframes == m_update_period) { 1125 pred_buffer_next_tail_timestamp = m_buffer_next_tail_timestamp; 1126 } else { 1127 debugOutput( DEBUG_LEVEL_VERBOSE, 1128 "Number of frames (%u) != update period (%u)\n", 1129 nbframes, m_update_period ); 1130 // calculate the predicted timestamp for nframes (instead of m_update_period) 1131 // after the previous update. 1132 float rel_step = ((float)nbframes)/((float)m_update_period); 1133 ENTER_CRITICAL_SECTION; // FIXME: do we need these? 1134 ffado_timestamp_t corrected_step = (m_buffer_next_tail_timestamp - m_buffer_tail_timestamp) * rel_step; 1135 pred_buffer_next_tail_timestamp = m_buffer_tail_timestamp + corrected_step; 1136 EXIT_CRITICAL_SECTION; 1137 1138 debugOutput( DEBUG_LEVEL_VERBOSE, 1139 "Updated ("TIMESTAMP_FORMAT_SPEC","TIMESTAMP_FORMAT_SPEC") to ("TIMESTAMP_FORMAT_SPEC","TIMESTAMP_FORMAT_SPEC")\n", 1140 m_buffer_tail_timestamp, m_buffer_next_tail_timestamp, 1141 m_buffer_tail_timestamp, pred_buffer_next_tail_timestamp); 1142 1143 } 1144 1145 // the difference between the given TS and the one predicted for this time instant 1146 // this is the error for the DLL 1147 diff = ts - pred_buffer_next_tail_timestamp; 1148 1149 // check whether the update is within the allowed bounds 1150 const float max_deviation = (50.0/100.0); // maximal relative difference considered normal 1151 ffado_timestamp_t one_update_step = nbframes * getRate(); 1152 ffado_timestamp_t max_abs_diff = one_update_step * (1.0 + max_deviation); 1153 1154 if (diff > max_abs_diff) { 1155 debugWarning("(%p) difference rather large (+): diff="TIMESTAMP_FORMAT_SPEC", max="TIMESTAMP_FORMAT_SPEC", "TIMESTAMP_FORMAT_SPEC", "TIMESTAMP_FORMAT_SPEC"\n", 1156 this, diff, max_abs_diff, ts, pred_buffer_next_tail_timestamp); 1157 // debugShowBackLogLines(40); 1158 } else if (diff < -max_abs_diff) { 1159 debugWarning("(%p) difference rather large (-): diff="TIMESTAMP_FORMAT_SPEC", max="TIMESTAMP_FORMAT_SPEC", "TIMESTAMP_FORMAT_SPEC", "TIMESTAMP_FORMAT_SPEC"\n", 1160 this, diff, -max_abs_diff, ts, pred_buffer_next_tail_timestamp); 1161 // debugShowBackLogLines(40); 1162 } 892 1163 893 1164 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "(%p): diff="TIMESTAMP_FORMAT_SPEC" ", 894 1165 this, diff); 895 1166 896 // the maximal difference we can allow (64secs) 897 const ffado_timestamp_t max=m_wrap_at/2; 898 899 if(diff > max) { 900 diff -= m_wrap_at; 901 } else if (diff < -max) { 902 diff += m_wrap_at; 903 } 904 905 float err=diff; 1167 double err = diff; 906 1168 907 1169 debugOutputShort(DEBUG_LEVEL_VERY_VERBOSE, "diff2="TIMESTAMP_FORMAT_SPEC" err=%f\n", 908 1170 diff, err); 909 1171 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "B: FC=%10u, TS="TIMESTAMP_FORMAT_SPEC", NTS="TIMESTAMP_FORMAT_SPEC"\n", 910 m_framecounter, m_buffer_tail_timestamp, m_buffer_next_tail_timestamp);911 912 pthread_mutex_lock(&m_framecounter_lock);1172 m_framecounter, m_buffer_tail_timestamp, pred_buffer_next_tail_timestamp); 1173 1174 ENTER_CRITICAL_SECTION; 913 1175 m_framecounter += nbframes; 914 1176 915 m_buffer_tail_timestamp =m_buffer_next_tail_timestamp;916 m_buffer_next_tail_timestamp +=(ffado_timestamp_t)(m_dll_b * err + m_dll_e2);1177 m_buffer_tail_timestamp = pred_buffer_next_tail_timestamp; 1178 m_buffer_next_tail_timestamp = pred_buffer_next_tail_timestamp + (ffado_timestamp_t)(m_dll_b * err + m_dll_e2); 917 1179 // m_buffer_tail_timestamp=ts; 918 1180 // m_buffer_next_tail_timestamp += (ffado_timestamp_t)(m_dll_b * err + m_dll_e2); 919 1181 920 1182 m_dll_e2 += m_dll_c*err; 921 922 // debugOutputShort(DEBUG_LEVEL_VERBOSE, "%p %llu %lld %llu %llu %e %e\n", this, new_timestamp, diff, m_buffer_tail_timestamp, m_buffer_next_tail_timestamp, m_dll_e2, 24576000.0/getRate()); 1183 1184 EXIT_CRITICAL_SECTION; 1185 1186 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "tail for (%p) to " 1187 TIMESTAMP_FORMAT_SPEC" => "TIMESTAMP_FORMAT_SPEC", NTS=" 1188 TIMESTAMP_FORMAT_SPEC", DLL2=%f, RATE=%f\n", 1189 this, new_timestamp, ts, m_buffer_next_tail_timestamp, m_dll_e2, getRate()); 923 1190 924 1191 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "U: FC=%10u, TS="TIMESTAMP_FORMAT_SPEC", NTS="TIMESTAMP_FORMAT_SPEC"\n", 925 1192 m_framecounter, m_buffer_tail_timestamp, m_buffer_next_tail_timestamp); 926 1193 1194 ENTER_CRITICAL_SECTION; 927 1195 if (m_buffer_next_tail_timestamp >= m_wrap_at) { 928 1196 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Unwrapping next tail timestamp: "TIMESTAMP_FORMAT_SPEC"", … … 935 1203 936 1204 } 1205 EXIT_CRITICAL_SECTION; 937 1206 938 1207 debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "A: TS="TIMESTAMP_FORMAT_SPEC", NTS="TIMESTAMP_FORMAT_SPEC", DLLe2=%f, RATE=%f\n", 939 1208 m_buffer_tail_timestamp, m_buffer_next_tail_timestamp, m_dll_e2, rate); 940 1209 941 pthread_mutex_unlock(&m_framecounter_lock);942 1210 943 1211 if(m_buffer_tail_timestamp>=m_wrap_at) { … … 982 1250 debugOutputShort( DEBUG_LEVEL_NORMAL, " TimestampedBuffer (%p) info:\n",this); 983 1251 debugOutputShort( DEBUG_LEVEL_NORMAL, " Frame counter : %d\n", m_framecounter); 1252 debugOutputShort( DEBUG_LEVEL_NORMAL, " Events in buffer : %d\n", getBufferFill()); 984 1253 debugOutputShort( DEBUG_LEVEL_NORMAL, " Buffer head timestamp : "TIMESTAMP_FORMAT_SPEC"\n",ts_head); 985 1254 debugOutputShort( DEBUG_LEVEL_NORMAL, " Buffer tail timestamp : "TIMESTAMP_FORMAT_SPEC"\n",m_buffer_tail_timestamp); trunk/libffado/src/libutil/TimestampedBuffer.h
r554 r734 37 37 // #define TIMESTAMP_FORMAT_SPEC "%012lld" 38 38 39 namespace Util {40 39 namespace Util 40 { 41 41 42 42 class TimestampedBufferClient; 43 43 44 44 /** 45 * \brief Class implementing a frame buffer that is time-aware 46 * 47 * This class implements a buffer that is time-aware. Whenever new frames 48 * are written to the buffer, the timestamp corresponding to the last frame 49 * in the buffer is updated. This allows to calculate the timestamp of any 50 * other frame in the buffer. 51 * 52 * The buffer is a frame buffer, having the following parameters defining 53 * it's behaviour: 54 * - buff_size: buffer size in frames (setBufferSize()) 55 * - events_per_frame: the number of events per frame (setEventsPerFrame()) 56 * - event_size: the storage size of the events (in bytes) (setEventSize()) 57 * 58 * The total size of the buffer (in bytes) is at least 59 * buff_size*events_per_frame*event_size. 60 * 61 * Timestamp tracking is done by requiring that a timestamp is specified every 62 * time frames are added to the buffer. In combination with the buffer fill and 63 * the frame rate (calculated internally), this allows to calculate the timestamp 64 * of any frame in the buffer. In order to initialize the internal data structures, 65 * the setNominalRate() and setUpdatePeriod() functions are provided. 66 * 67 * \note Currently the class only supports fixed size writes of size update_period. 68 * This can change in the future, implementation ideas are already in place. 69 * 70 * The TimestampedBuffer class is time unit agnostic. It can handle any time unit 71 * as long as it fits in a 64 bit unsigned integer. The buffer supports wrapped 72 * timestamps using (...). 73 * 74 * There are two methods of reading and writing to the buffer. 75 * 76 * The first method uses conventional readFrames() and writeFrames() functions. 77 * 78 * The second method makes use of the TimestampedBufferClient interface. When a 79 * TimestampedBuffer is created, it is required that a TimestampedBufferClient is 80 * registered. This client implements the processReadBlock and processWriteBlock 81 * functions. These are block processing 'callbacks' that allow zero-copy processing 82 * of the buffer contents. In order to initiate block processing, the 83 * blockProcessWriteFrames and blockProcessReadFrames functions are provided by 84 * TimestampedBuffer. 85 * 86 */ 87 class TimestampedBuffer { 88 89 public: 90 91 92 TimestampedBuffer(TimestampedBufferClient *); 93 virtual ~TimestampedBuffer(); 94 95 bool writeDummyFrame(); 96 97 bool writeFrames(unsigned int nbframes, char *data, ffado_timestamp_t ts); 98 bool readFrames(unsigned int nbframes, char *data); 99 100 bool blockProcessWriteFrames(unsigned int nbframes, ffado_timestamp_t ts); 101 bool blockProcessReadFrames(unsigned int nbframes); 102 103 bool init(); 104 bool prepare(); 105 bool reset(); 106 107 bool setEventSize(unsigned int s); 108 bool setEventsPerFrame(unsigned int s); 109 bool setBufferSize(unsigned int s); 110 unsigned int getBufferSize() {return m_buffer_size;}; 111 112 unsigned int getBytesPerFrame() {return m_bytes_per_frame;}; 113 114 bool setWrapValue(ffado_timestamp_t w); 115 116 unsigned int getBufferFill(); 117 118 // timestamp stuff 119 int getFrameCounter() {return m_framecounter;}; 120 121 void getBufferHeadTimestamp(ffado_timestamp_t *ts, signed int *fc); 122 void getBufferTailTimestamp(ffado_timestamp_t *ts, signed int *fc); 123 124 void setBufferTailTimestamp(ffado_timestamp_t new_timestamp); 125 void setBufferHeadTimestamp(ffado_timestamp_t new_timestamp); 126 127 ffado_timestamp_t getTimestampFromTail(int nframes); 128 ffado_timestamp_t getTimestampFromHead(int nframes); 129 130 // buffer offset stuff 131 /// return the tick offset value 132 ffado_timestamp_t getTickOffset() {return m_tick_offset;}; 133 134 bool setFrameOffset(int nframes); 135 bool setTickOffset(ffado_timestamp_t); 136 137 // dll stuff 138 bool setNominalRate(float r); 139 float getRate(); 140 141 bool setUpdatePeriod(unsigned int t); 142 143 // misc stuff 144 void dumpInfo(); 145 void setVerboseLevel(int l) {setDebugLevel(l);}; 146 147 private: 148 void decrementFrameCounter(int nbframes); 149 void incrementFrameCounter(int nbframes, ffado_timestamp_t new_timestamp); 150 void resetFrameCounter(); 151 152 protected: 153 154 ffado_ringbuffer_t * m_event_buffer; 155 char* m_cluster_buffer; 156 157 unsigned int m_event_size; // the size of one event 158 unsigned int m_events_per_frame; // the number of events in a frame 159 unsigned int m_buffer_size; // the number of frames in the buffer 160 unsigned int m_bytes_per_frame; 161 unsigned int m_bytes_per_buffer; 162 163 ffado_timestamp_t m_wrap_at; // value to wrap at 164 165 TimestampedBufferClient *m_Client; 166 167 DECLARE_DEBUG_MODULE; 168 169 private: 170 // the framecounter gives the number of frames in the buffer 171 signed int m_framecounter; 172 173 // the offset that define the timing of the buffer 174 ffado_timestamp_t m_tick_offset; 175 176 // the buffer tail timestamp gives the timestamp of the last frame 177 // that was put into the buffer 178 ffado_timestamp_t m_buffer_tail_timestamp; 179 ffado_timestamp_t m_buffer_next_tail_timestamp; 180 181 // this mutex protects the access to the framecounter 182 // and the buffer head timestamp. 183 pthread_mutex_t m_framecounter_lock; 184 185 // tracking DLL variables 45 * \brief Class implementing a frame buffer that is time-aware 46 * 47 * This class implements a buffer that is time-aware. Whenever new frames 48 * are written to the buffer, the timestamp corresponding to the last frame 49 * in the buffer is updated. This allows to calculate the timestamp of any 50 * other frame in the buffer. 51 * 52 * The buffer is a frame buffer, having the following parameters defining 53 * it's behaviour: 54 * - buff_size: buffer size in frames (setBufferSize()) 55 * - events_per_frame: the number of events per frame (setEventsPerFrame()) 56 * - event_size: the storage size of the events (in bytes) (setEventSize()) 57 * 58 * The total size of the buffer (in bytes) is at least 59 * buff_size*events_per_frame*event_size. 60 * 61 * Timestamp tracking is done by requiring that a timestamp is specified every 62 * time frames are added to the buffer. In combination with the buffer fill and 63 * the frame rate (calculated internally), this allows to calculate the timestamp 64 * of any frame in the buffer. In order to initialize the internal data structures, 65 * the setNominalRate() and setUpdatePeriod() functions are provided. 66 * 67 * \note Currently the class only supports fixed size writes of size update_period. 68 * This can change in the future, implementation ideas are already in place. 69 * 70 * The TimestampedBuffer class is time unit agnostic. It can handle any time unit 71 * as long as it fits in a 64 bit unsigned integer. The buffer supports wrapped 72 * timestamps using (...). 73 * 74 * There are two methods of reading and writing to the buffer. 75 * 76 * The first method uses conventional readFrames() and writeFrames() functions. 77 * 78 * The second method makes use of the TimestampedBufferClient interface. When a 79 * TimestampedBuffer is created, it is required that a TimestampedBufferClient is 80 * registered. This client implements the processReadBlock and processWriteBlock 81 * functions. These are block processing 'callbacks' that allow zero-copy processing 82 * of the buffer contents. In order to initiate block processing, the 83 * blockProcessWriteFrames and blockProcessReadFrames functions are provided by 84 * TimestampedBuffer. 85 * 86 */ 87 class TimestampedBuffer 88 { 89 public: 90 TimestampedBuffer ( TimestampedBufferClient * ); 91 virtual ~TimestampedBuffer(); 92 93 bool writeDummyFrame(); 94 bool dropFrames ( unsigned int nbframes ); 95 96 bool writeFrames ( unsigned int nbframes, char *data, ffado_timestamp_t ts ); 97 bool readFrames ( unsigned int nbframes, char *data ); 98 99 bool preloadFrames ( unsigned int nbframes, char *data, bool keep_head_ts ); 100 101 bool blockProcessWriteFrames ( unsigned int nbframes, ffado_timestamp_t ts ); 102 bool blockProcessReadFrames ( unsigned int nbframes ); 103 104 bool init(); 105 bool prepare(); 106 bool clearBuffer(); 107 108 bool isEnabled() {return m_enabled;}; 109 void enable() {m_enabled=true;}; 110 void disable() {m_enabled=false;}; 111 112 bool isTransparent() {return m_transparent;}; 113 void setTransparent ( bool v ) {m_transparent=v;}; 114 115 bool setEventSize ( unsigned int s ); 116 bool setEventsPerFrame ( unsigned int s ); 117 bool setBufferSize ( unsigned int s ); 118 unsigned int getBufferSize() {return m_buffer_size;}; 119 120 unsigned int getBytesPerFrame() {return m_bytes_per_frame;}; 121 122 bool setWrapValue ( ffado_timestamp_t w ); 123 124 unsigned int getBufferFill(); 125 126 // timestamp stuff 127 int getFrameCounter() {return m_framecounter;}; 128 129 void getBufferHeadTimestamp ( ffado_timestamp_t *ts, signed int *fc ); 130 void getBufferTailTimestamp ( ffado_timestamp_t *ts, signed int *fc ); 131 132 void setBufferTailTimestamp ( ffado_timestamp_t new_timestamp ); 133 void setBufferHeadTimestamp ( ffado_timestamp_t new_timestamp ); 134 135 // sync related, also drops or add frames when necessary 136 bool syncBufferHeadToTimestamp ( ffado_timestamp_t ts ); 137 bool syncBufferTailToTimestamp ( ffado_timestamp_t ts ); 138 bool syncCorrectLag ( int64_t ts ); 139 140 ffado_timestamp_t getTimestampFromTail ( int nframes ); 141 ffado_timestamp_t getTimestampFromHead ( int nframes ); 142 143 // buffer offset stuff 144 /// return the tick offset value 145 ffado_timestamp_t getTickOffset() {return m_tick_offset;}; 146 147 bool setFrameOffset ( int nframes ); 148 bool setTickOffset ( ffado_timestamp_t ); 149 150 // dll stuff 151 bool setNominalRate ( float r ); 152 float getNominalRate() {return m_nominal_rate;}; 153 float getRate(); 154 155 bool setUpdatePeriod ( unsigned int t ); 156 157 // misc stuff 158 void dumpInfo(); 159 void setVerboseLevel ( int l ) {setDebugLevel ( l );}; 160 161 private: 162 void decrementFrameCounter ( int nbframes ); 163 void incrementFrameCounter ( int nbframes, ffado_timestamp_t new_timestamp ); 164 void resetFrameCounter(); 165 166 protected: 167 168 ffado_ringbuffer_t * m_event_buffer; 169 char* m_cluster_buffer; 170 171 unsigned int m_event_size; // the size of one event 172 unsigned int m_events_per_frame; // the number of events in a frame 173 unsigned int m_buffer_size; // the number of frames in the buffer 174 unsigned int m_bytes_per_frame; 175 unsigned int m_bytes_per_buffer; 176 bool m_enabled; // you can get frames FIXME: rename!! 177 bool m_transparent; // the buffer should hold the frames put in it. if true, discards all frames 178 179 ffado_timestamp_t m_wrap_at; // value to wrap at 180 181 TimestampedBufferClient *m_Client; 182 183 DECLARE_DEBUG_MODULE; 184 185 private: 186 // the framecounter gives the number of frames in the buffer 187 signed int m_framecounter; 188 189 // the offset that define the timing of the buffer 190 ffado_timestamp_t m_tick_offset; 191 192 // the buffer tail timestamp gives the timestamp of the last frame 193 // that was put into the buffer 194 ffado_timestamp_t m_buffer_tail_timestamp; 195 ffado_timestamp_t m_buffer_next_tail_timestamp; 196 197 // this mutex protects the access to the framecounter 198 // and the buffer head timestamp. 199 pthread_mutex_t m_framecounter_lock; 200 201 // tracking DLL variables 186 202 // JMW: try double for this too 187 203 // float m_dll_e2; 188 double m_dll_e2;189 float m_dll_b;190 float m_dll_c;191 192 float m_nominal_rate;193 unsigned int m_update_period;204 double m_dll_e2; 205 float m_dll_b; 206 float m_dll_c; 207 208 float m_nominal_rate; 209 unsigned int m_update_period; 194 210 }; 195 211 196 212 /** 197 * \brief Interface to be implemented by TimestampedBuffer clients 198 */ 199 class TimestampedBufferClient { 213 * \brief Interface to be implemented by TimestampedBuffer clients 214 */ 215 class TimestampedBufferClient 216 { 200 217 public: 201 218 TimestampedBufferClient() {}; 202 219 virtual ~TimestampedBufferClient() {}; 203 220 204 virtual bool processReadBlock (char *data, unsigned int nevents, unsigned int offset)=0;205 virtual bool processWriteBlock (char *data, unsigned int nevents, unsigned int offset)=0;221 virtual bool processReadBlock ( char *data, unsigned int nevents, unsigned int offset ) =0; 222 virtual bool processWriteBlock ( char *data, unsigned int nevents, unsigned int offset ) =0; 206 223 207 224 }; trunk/libffado/src/maudio/maudio_avdevice.h
r583 r734 32 32 #include "bebob/bebob_avdevice.h" 33 33 34 #include "libstreaming/AmdtpStreamProcessor.h" 35 #include "libstreaming/AmdtpPort.h" 36 #include "libstreaming/AmdtpPortInfo.h" 34 #include "libstreaming/amdtp/AmdtpReceiveStreamProcessor.h" 35 #include "libstreaming/amdtp/AmdtpTransmitStreamProcessor.h" 36 #include "libstreaming/amdtp/AmdtpPort.h" 37 #include "libstreaming/amdtp/AmdtpPortInfo.h" 37 38 38 39 #include "ffadodevice.h" trunk/libffado/src/metrichalo/mh_avdevice.h
r639 r734 30 30 #include "libavc/avc_definitions.h" 31 31 32 // #include "libstreaming/ MHStreamProcessor.h"32 // #include "libstreaming/mh/MHStreamProcessor.h" 33 33 34 34 class ConfigRom; trunk/libffado/src/motu/motu_avdevice.cpp
r660 r734 32 32 #include "debugmodule/debugmodule.h" 33 33 34 #include "libstreaming/MotuStreamProcessor.h" 35 #include "libstreaming/MotuPort.h" 34 #include "libstreaming/motu/MotuReceiveStreamProcessor.h" 35 #include "libstreaming/motu/MotuTransmitStreamProcessor.h" 36 #include "libstreaming/motu/MotuPort.h" 36 37 37 38 #include "libutil/DelayLockedLoop.h" … … 523 524 524 525 m_receiveProcessor=new Streaming::MotuReceiveStreamProcessor( 525 m_p1394Service->getPort(), samp_freq,event_size_in);526 m_p1394Service->getPort(), event_size_in); 526 527 527 528 // The first thing is to initialize the processor. This creates the … … 593 594 // Do the same for the transmit processor 594 595 m_transmitProcessor=new Streaming::MotuTransmitStreamProcessor( 595 m_p1394Service->getPort(), getSamplingFrequency(),event_size_out);596 m_p1394Service->getPort(), event_size_out); 596 597 597 598 m_transmitProcessor->setVerboseLevel(getDebugLevel()); trunk/libffado/src/motu/motu_avdevice.h
r660 r734 31 31 #include "libavc/avc_definitions.h" 32 32 33 #include "libstreaming/MotuStreamProcessor.h" 33 #include "libstreaming/motu/MotuReceiveStreamProcessor.h" 34 #include "libstreaming/motu/MotuTransmitStreamProcessor.h" 34 35 35 36 #define MOTUFW_BASE_ADDR 0xfffff0000000ULL trunk/libffado/src/rme/rme_avdevice.h
r639 r734 31 31 #include "libavc/avc_definitions.h" 32 32 33 // #include "libstreaming/ RmeStreamProcessor.h"33 // #include "libstreaming/rme/RmeStreamProcessor.h" 34 34 35 35 class ConfigRom; trunk/libffado/src/SConscript
r688 r734 42 42 libieee1394/ieee1394service.cpp \ 43 43 libieee1394/IEC61883.cpp \ 44 libosc/OscArgument.cpp \45 libosc/OscClient.cpp \46 libosc/OscMessage.cpp \47 libosc/OscNode.cpp \48 libosc/OscResponse.cpp \49 libosc/OscServer.cpp \50 libstreaming/cip.c \51 libstreaming/IsoHandler.cpp \52 libstreaming/IsoHandlerManager.cpp \53 libstreaming/IsoStream.cpp \54 libstreaming/Port.cpp \55 libstreaming/PortManager.cpp \56 libstreaming/StreamProcessor.cpp \57 44 libstreaming/StreamProcessorManager.cpp \ 45 libstreaming/util/cip.c \ 46 libstreaming/util/IsoHandler.cpp \ 47 libstreaming/util/IsoHandlerManager.cpp \ 48 libstreaming/generic/StreamProcessor.cpp \ 49 libstreaming/generic/IsoStream.cpp \ 50 libstreaming/generic/Port.cpp \ 51 libstreaming/generic/PortManager.cpp \ 58 52 libutil/cmd_serialize.cpp \ 59 53 libutil/DelayLockedLoop.cpp \ … … 127 121 motu_source = env.Split( '\ 128 122 motu/motu_avdevice.cpp \ 129 libstreaming/MotuPort.cpp \ 130 libstreaming/MotuPortInfo.cpp \ 131 libstreaming/MotuStreamProcessor.cpp \ 123 libstreaming/motu/MotuPort.cpp \ 124 libstreaming/motu/MotuPortInfo.cpp \ 125 libstreaming/motu/MotuReceiveStreamProcessor.cpp \ 126 libstreaming/motu/MotuTransmitStreamProcessor.cpp \ 132 127 ' ) 133 128 … … 151 146 152 147 amdtp_source = env.Split( '\ 153 libstreaming/AmdtpPort.cpp \ 154 libstreaming/AmdtpPortInfo.cpp \ 155 libstreaming/AmdtpStreamProcessor.cpp \ 148 libstreaming/amdtp/AmdtpPort.cpp \ 149 libstreaming/amdtp/AmdtpPortInfo.cpp \ 150 libstreaming/amdtp/AmdtpReceiveStreamProcessor.cpp \ 151 libstreaming/amdtp/AmdtpTransmitStreamProcessor.cpp \ 156 152 ' ) 157 153 … … 196 192 libenv.MergeFlags( env['ALSA_FLAGS'] ) 197 193 libenv.MergeFlags( env['LIBXML26_FLAGS'] ) 198 libenv.MergeFlags( env['LIBLO_FLAGS'] )199 194 200 195 #env1.AppendUnique( LINKFLAGS = env.Split("-Wl,-rpath $libdir -Wl,-soname -Wl,libffado.so.1 --version-info=1:0:0") ) … … 247 242 "test-dll" : "libutil/test-dll.cpp", \ 248 243 "test-unittests-util" : "libutil/unittests.cpp", \ 249 "test-unittests-osc" : "libosc/unittests.cpp" \250 244 } 251 245 trunk/libffado/support/firmware/SConscript
r689 r734 19 19 env.MergeFlags( env['ALSA_FLAGS'] ) 20 20 env.MergeFlags( env['LIBXML26_FLAGS'] ) 21 env.MergeFlags( env['LIBLO_FLAGS'] )22 21 23 22 apps = { … … 27 26 28 27 if env['ENABLE_BEBOB']: 29 apps[" bridgeco-downloader"] = "bridgeco-downloader.cpp"30 installapps += [ " bridgeco-downloader" ]28 apps["ffado-bridgeco-downloader"] = "bridgeco-downloader.cpp" 29 installapps += [ "ffado-bridgeco-downloader" ] 31 30 32 31 if env['ENABLE_FIREWORKS']: 33 apps["f ireworks-downloader"] = "fireworks-downloader.cpp"34 installapps += [ "f ireworks-downloader" ]32 apps["ffado-fireworks-downloader"] = "fireworks-downloader.cpp" 33 installapps += [ "ffado-fireworks-downloader" ] 35 34 36 35 for app in apps.keys(): trunk/libffado/support/SConscript
r688 r734 18 18 # 19 19 20 env.SConscript( dirs=["mixer","firmware" ], exports="env" )20 env.SConscript( dirs=["mixer","firmware","dbus"], exports="env" ) 21 21 trunk/libffado/tests/SConscript
r663 r734 5 5 env = env.Copy() 6 6 7 env.PrependUnique( CPPPATH=["#/src" , "#/external/dbus/include"] )8 env.PrependUnique( LIBPATH=[env['build_base']+"src" , env['build_base']+"external/dbus"] )9 env.PrependUnique( LIBS=["ffado" , "dbus-c++"] )7 env.PrependUnique( CPPPATH=["#/src"] ) 8 env.PrependUnique( LIBPATH=[env['build_base']+"src"] ) 9 env.PrependUnique( LIBS=["ffado"] ) 10 10 11 11 if not env.GetOption( "clean" ): 12 env.MergeFlags( env["DBUS1_FLAGS"] )13 12 env.MergeFlags( env['LIBRAW1394_FLAGS'] ) 14 13 env.MergeFlags( env['LIBXML26_FLAGS'] ) 15 16 env.Xml2Cpp_Proxy('controlclient-glue.h', 'control-interface.xml')17 env.Xml2Cpp_Adaptor('controlserver-glue.h', 'control-interface.xml')18 14 19 15 # … … 22 18 # 23 19 apps = { 24 "test-ffado" : "test-ffado.cpp controlserver.cpp",20 "test-ffado" : "test-ffado.cpp", 25 21 "test-fw410" : "test-fw410.cpp", 26 22 "test-avccmd" : "test-avccmd.cpp", … … 33 29 "test-streamdump" : "test-streamdump.cpp", 34 30 "test-sytmonitor" : "test-sytmonitor.cpp SytMonitor.cpp", 35 "test-dbus" : "test-dbus.cpp controlclient.cpp",36 "test-dbus-server" : "test-dbus-server.cpp controlserver.cpp",37 31 } 38 32 trunk/libffado/tests/streaming/test-isohandling.cpp
r445 r734 35 35 #include <netinet/in.h> 36 36 37 #include "src/libstreaming/IsoHandler.h"38 #include "src/libstreaming/IsoStream.h"39 #include "src/libstreaming/StreamProcessorManager.h"40 #include "src/libstreaming/AmdtpStreamProcessor.h"41 #include "src/libstreaming/IsoHandlerManager.h"42 37 #include "src/libutil/PosixThread.h" 43 #include "src/libstreaming/AmdtpPort.h" 38 39 #include "src/libstreaming/util/IsoHandler.h" 40 #include "src/libstreaming/util/StreamProcessorManager.h" 41 #include "src/libstreaming/util/IsoHandlerManager.h" 42 #include "src/libstreaming/amdtp/AmdtpStreamProcessor.h" 43 #include "src/libstreaming/amdtp/AmdtpPort.h" 44 44 45 45 using namespace Streaming; 46 47 46 48 47 int run; trunk/libffado/tests/SytMonitor.cpp
r445 r734 24 24 25 25 #include "SytMonitor.h" 26 #include "src/libstreaming/IsoStream.h"27 26 28 27 #include <netinet/in.h> … … 36 35 37 36 SytMonitor::SytMonitor(int port) 38 : IsoStream(IsoStream:: EST_Receive, port) {37 : IsoStream(IsoStream::eST_Receive, port) { 39 38 m_cinfo_buffer=ffado_ringbuffer_create(16384*sizeof(struct cycle_info)); 40 39 trunk/libffado/tests/SytMonitor.h
r445 r734 25 25 #ifndef __FFADO_SYTMONITOR__ 26 26 #define __FFADO_SYTMONITOR__ 27 #include "src/libstreaming/ IsoStream.h"28 #include "src/libstreaming/ cip.h"29 #include "src/libstreaming/ cycletimer.h"27 #include "src/libstreaming/generic/IsoStream.h" 28 #include "src/libstreaming/util/cip.h" 29 #include "src/libstreaming/util/cycletimer.h" 30 30 #include "src/libutil/ringbuffer.h" 31 31 trunk/libffado/tests/test-cycletimer.cpp
r445 r734 37 37 #include <netinet/in.h> 38 38 39 #include "src/libstreaming/ cycletimer.h"40 41 #include "src/libstreaming/ IsoHandler.h"42 #include "src/libstreaming/ IsoStream.h"43 #include "src/libstreaming/ IsoHandlerManager.h"39 #include "src/libstreaming/util/cycletimer.h" 40 41 #include "src/libstreaming/util/IsoHandler.h" 42 #include "src/libstreaming/generic/IsoStream.h" 43 #include "src/libstreaming/util/IsoHandlerManager.h" 44 44 #include "src/libutil/PosixThread.h" 45 45 … … 288 288 #ifdef TEST_PORT_0 289 289 // add a stream to the manager so that it has something to do 290 s=new IsoStream(IsoStream:: EST_Receive, 0);290 s=new IsoStream(IsoStream::eST_Receive, 0); 291 291 292 292 if (!s) { … … 296 296 297 297 s->setVerboseLevel(DEBUG_LEVEL_VERBOSE); 298 299 if (!s->init()) {300 debugOutput(DEBUG_LEVEL_NORMAL, "Could not init IsoStream\n");301 goto finish;302 }303 304 298 s->setChannel(0); 305 299 trunk/libffado/tests/test-ffado.cpp
r639 r734 36 36 #include "ffadodevice.h" 37 37 38 #include <dbus-c++/dbus.h>39 #include "controlserver.h"40 #include "libcontrol/BasicElements.h"41 42 38 #include <signal.h> 43 39 … … 52 48 #include <sstream> 53 49 54 #include <lo/lo.h>55 56 50 using namespace std; 57 51 58 52 DECLARE_GLOBAL_DEBUG_MODULE; 59 60 // prototypes & stuff for listing the OSC space61 void list_osc_paths(lo_server s, lo_address t, const char *path);62 void list_osc_params(lo_server s, lo_address t, const char *path);63 string osc_param_get_value(lo_server s, lo_address t, const char *path, const char *param);64 65 vector<string> osc_paths;66 vector<string> osc_params;67 string osc_value;68 69 int osc_path_response_handler(const char *path, const char *types, lo_arg **argv, int argc,70 void *data, void *user_data);71 72 int osc_param_response_handler(const char *path, const char *types, lo_arg **argv, int argc,73 void *data, void *user_data);74 75 int osc_data_response_handler(const char *path, const char *types, lo_arg **argv, int argc,76 void *data, void *user_data);77 78 void osc_error_handler(int num, const char *msg, const char *path);79 80 // DBUS stuff81 DBus::BusDispatcher dispatcher;82 83 // signal handler84 int run=1;85 static void sighandler (int sig)86 {87 run = 0;88 dispatcher.leave();89 }90 53 91 54 // global's … … 98 61 " SetSamplerate samplerate\n" 99 62 " SetClockSource [id]\n" 100 " ListOscSpace\n"101 " OscServer\n"102 " DBus\n"103 63 ; 104 64 … … 384 344 delete m_deviceManager; 385 345 return exitfunction(0); 386 } else if ( strcmp( arguments.args[0], "ListOscSpace" ) == 0 ) {387 // list osc space by using OSC messages388 // a server is assumed to be present389 390 /* start a new server.391 when sending a message from this context, the response392 address will be set to this server's address.393 */394 lo_server s = lo_server_new(NULL, osc_error_handler);395 lo_address t = lo_address_new(NULL, "17820");396 397 list_osc_paths(s, t, "/");398 399 lo_address_free(t);400 lo_server_free(s);401 402 } else if ( strcmp( arguments.args[0], "OscServer" ) == 0 ) {403 DeviceManager *m_deviceManager = new DeviceManager();404 if ( !m_deviceManager ) {405 fprintf( stderr, "Could not allocate device manager\n" );406 return exitfunction(-1);407 }408 if ( !m_deviceManager->initialize( arguments.port ) ) {409 fprintf( stderr, "Could not initialize device manager\n" );410 delete m_deviceManager;411 return exitfunction(-1);412 }413 if ( arguments.verbose ) {414 m_deviceManager->setVerboseLevel(arguments.verbose);415 }416 if ( !m_deviceManager->discover() ) {417 fprintf( stderr, "Could not discover devices\n" );418 delete m_deviceManager;419 return exitfunction(-1);420 }421 422 printf("server started\n");423 printf("press ctrl-c to stop it & continue\n");424 425 signal (SIGINT, sighandler);426 427 run=1;428 while(run) {429 sleep(1);430 fflush(stdout);431 fflush(stderr);432 }433 signal (SIGINT, SIG_DFL);434 435 printf("server stopped\n");436 delete m_deviceManager;437 return exitfunction(0);438 } else if ( strcmp( arguments.args[0], "DBus" ) == 0 ) {439 DeviceManager *m_deviceManager = new DeviceManager();440 if ( !m_deviceManager ) {441 fprintf( stderr, "Could not allocate device manager\n" );442 return exitfunction(-1);443 }444 if ( !m_deviceManager->initialize( arguments.port ) ) {445 fprintf( stderr, "Could not initialize device manager\n" );446 delete m_deviceManager;447 return exitfunction(-1);448 }449 if ( arguments.verbose ) {450 m_deviceManager->setVerboseLevel(arguments.verbose);451 }452 if ( !m_deviceManager->discover() ) {453 fprintf( stderr, "Could not discover devices\n" );454 delete m_deviceManager;455 return exitfunction(-1);456 }457 458 signal (SIGINT, sighandler);459 460 DBus::_init_threading();461 462 // test DBUS stuff463 DBus::default_dispatcher = &dispatcher;464 465 DBus::Connection conn = DBus::Connection::SessionBus();466 conn.request_name("org.ffado.Control");467 468 DBusControl::Container *container469 = new DBusControl::Container(conn, "/org/ffado/Control/DeviceManager", *m_deviceManager);470 471 printf("DBUS test service running\n");472 printf("press ctrl-c to stop it & continue\n");473 474 dispatcher.enter();475 476 delete container;477 478 signal (SIGINT, SIG_DFL);479 480 printf("server stopped\n");481 delete m_deviceManager;482 return exitfunction(0);483 } else {484 printf( "unknown operation\n" );485 346 } 486 487 347 } 488 489 void list_osc_paths(lo_server s, lo_address t, const char *path) {490 vector<string> my_paths;491 492 printf("listing path: %s\n", path);493 494 osc_paths.clear();495 lo_server_add_method(s, "/response", NULL, osc_path_response_handler, NULL);496 497 if (lo_send(t, path, "s", "list") == -1) {498 printf(" OSC error %d: %s\n", lo_address_errno(t), lo_address_errstr(t));499 }500 501 if (lo_server_recv_noblock(s, 1000) == 0) {502 printf("timeout\n");503 return;504 }505 506 lo_server_del_method(s, "/response", NULL);507 508 list_osc_params(s, t, path);509 510 my_paths=osc_paths;511 for ( vector<string>::iterator it = my_paths.begin();512 it != my_paths.end();513 ++it )514 {515 string new_path=string(path) + *it;516 new_path += string("/");517 list_osc_paths(s, t, new_path.c_str());518 }519 520 }521 522 void list_osc_params(lo_server s, lo_address t, const char *path) {523 vector<string> my_paths;524 printf("params for: %s\n", path);525 526 osc_params.clear();527 lo_server_add_method(s, "/response", NULL, osc_param_response_handler, NULL);528 529 if (lo_send(t, path, "s", "params") == -1) {530 printf(" OSC error %d: %s\n", lo_address_errno(t), lo_address_errstr(t));531 }532 533 if (lo_server_recv_noblock(s, 1000) == 0) {534 printf("timeout\n");535 return;536 }537 538 lo_server_del_method(s, "/response", NULL);539 540 vector<string> my_params=osc_params;541 542 for ( vector<string>::iterator it = my_params.begin();543 it != my_params.end();544 ++it )545 {546 string value=osc_param_get_value(s, t, path, (*it).c_str());547 printf(" %20s = %s\n", (*it).c_str(), value.c_str());548 }549 550 }551 552 string osc_param_get_value(lo_server s, lo_address t, const char *path, const char *param) {553 lo_server_add_method(s, "/response", NULL, osc_data_response_handler, NULL);554 555 if (lo_send(t, path, "ss", "get", param) == -1) {556 printf(" OSC error %d: %s\n", lo_address_errno(t), lo_address_errstr(t));557 }558 559 if (lo_server_recv_noblock(s, 1000) == 0) {560 return string("timeout");561 }562 563 lo_server_del_method(s, "/response", NULL);564 return osc_value;565 }566 567 void osc_error_handler(int num, const char *msg, const char *path)568 {569 printf("liblo server error %d in path %s: %s\n", num, path, msg);570 }571 572 int osc_path_response_handler(const char *path, const char *types, lo_arg **argv, int argc,573 void *data, void *user_data)574 {575 for (int i=0; i< argc;i++) {576 switch (lo_type(types[i])) {577 /** Standard C, NULL terminated string. */578 case LO_STRING:579 osc_paths.push_back(string(&(argv[i]->s)));580 break;581 default:582 printf("unexpected data type in response message\n");583 }584 }585 return 1;586 }587 588 int osc_param_response_handler(const char *path, const char *types, lo_arg **argv, int argc,589 void *data, void *user_data)590 {591 for (int i=0; i< argc;i++) {592 switch (lo_type(types[i])) {593 /** Standard C, NULL terminated string. */594 case LO_STRING:595 osc_params.push_back(string(&(argv[i]->s)));596 break;597 default:598 printf("unexpected data type in response message\n");599 }600 }601 return 1;602 }603 604 int osc_data_response_handler(const char *path, const char *types, lo_arg **argv, int argc,605 void *data, void *user_data)606 {607 std::ostringstream str;608 609 if(argc==1) {610 switch (lo_type(types[0])) {611 /* basic OSC types */612 /** 32 bit signed integer. */613 case LO_INT32:614 str << "0x" << std::hex << argv[0]->i;615 osc_value=str.str();616 break;617 case LO_INT64:618 str << "0x" << std::hex << argv[0]->h;619 osc_value=str.str();620 break;621 /** 32 bit IEEE-754 float. */622 case LO_FLOAT:623 str << argv[0]->f;624 osc_value=str.str();625 break;626 /** Standard C, NULL terminated string. */627 case LO_STRING:628 osc_value=string(&argv[0]->s);629 break;630 default:631 osc_value="unsupported response datatype";632 }633 } else {634 osc_value="invalid response";635 }636 return 1;637 }trunk/libffado/tests/test-sytmonitor.cpp
r445 r734 37 37 #include <netinet/in.h> 38 38 39 #include "src/libstreaming/ cycletimer.h"40 41 #include "src/libstreaming/ IsoHandlerManager.h"39 #include "src/libstreaming/util/cycletimer.h" 40 41 #include "src/libstreaming/util/IsoHandlerManager.h" 42 42 #include "SytMonitor.h" 43 43 … … 233 233 234 234 monitors[i]->setVerboseLevel(DEBUG_LEVEL_VERBOSE); 235 236 if (!monitors[i]->init()) {237 debugOutput(DEBUG_LEVEL_NORMAL, "Could not init SytMonitor %d\n", i);238 goto finish;239 }240 241 235 monitors[i]->setChannel(arguments.args[i].channel); 242 236 trunk/libffado/tests/test-timestampedbuffer.cpp
r494 r734 37 37 #include <netinet/in.h> 38 38 39 #include "src/libstreaming/ cycletimer.h"39 #include "src/libstreaming/util/cycletimer.h" 40 40 41 41 #include "src/libutil/TimestampedBuffer.h"