Changeset 809
- Timestamp:
- 01/05/08 09:40:06 (16 years ago)
- Files:
-
- branches/api-cleanup/libffado/ffado.h (modified) (2 diffs)
- branches/api-cleanup/SConstruct (modified) (1 diff)
- branches/api-cleanup/src/bounce/bounce_avdevice.cpp (modified) (4 diffs)
- branches/api-cleanup/src/dice/dice_avdevice.cpp (modified) (3 diffs)
- branches/api-cleanup/src/ffado.cpp (modified) (5 diffs)
- branches/api-cleanup/src/genericavc/avc_avdevice.cpp (modified) (7 diffs)
- branches/api-cleanup/src/libstreaming/amdtp/AmdtpPort.h (modified) (2 diffs)
- branches/api-cleanup/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.cpp (modified) (8 diffs)
- branches/api-cleanup/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.h (modified) (1 diff)
- branches/api-cleanup/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.cpp (modified) (12 diffs)
- branches/api-cleanup/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.h (modified) (1 diff)
- branches/api-cleanup/src/libstreaming/generic/Port.cpp (modified) (11 diffs)
- branches/api-cleanup/src/libstreaming/generic/Port.h (modified) (10 diffs)
- branches/api-cleanup/src/libstreaming/generic/PortManager.cpp (modified) (8 diffs)
- branches/api-cleanup/src/libstreaming/generic/PortManager.h (modified) (3 diffs)
- branches/api-cleanup/src/libstreaming/generic/StreamProcessor.cpp (modified) (5 diffs)
- branches/api-cleanup/src/libstreaming/generic/StreamProcessor.h (modified) (1 diff)
- branches/api-cleanup/src/libstreaming/motu/MotuPort.h (modified) (3 diffs)
- branches/api-cleanup/src/libstreaming/motu/MotuReceiveStreamProcessor.cpp (modified) (4 diffs)
- branches/api-cleanup/src/libstreaming/motu/MotuTransmitStreamProcessor.cpp (modified) (8 diffs)
- branches/api-cleanup/src/motu/motu_avdevice.cpp (modified) (3 diffs)
- branches/api-cleanup/tests/streaming/debugtools.c (deleted)
- branches/api-cleanup/tests/streaming/debugtools.h (deleted)
- branches/api-cleanup/tests/streaming/SConscript (modified) (1 diff)
- branches/api-cleanup/tests/streaming/testmidistreaming1.c (deleted)
- branches/api-cleanup/tests/streaming/teststreaming.c (deleted)
- branches/api-cleanup/tests/streaming/teststreaming2.c (deleted)
- branches/api-cleanup/tests/streaming/teststreaming3.cpp (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/api-cleanup/libffado/ffado.h
r742 r809 206 206 207 207 /** 208 * 208 * 209 209 * Buffer types known to the API 210 * 210 * 211 211 */ 212 212 typedef enum { 213 ffado_buffer_type_per_stream = -1, // use this to use the per-stream read functions214 213 ffado_buffer_type_int24 = 0, 215 214 ffado_buffer_type_float = 1, … … 412 411 413 412 /** 414 * Reads from a specific channel to a supplied buffer.415 *416 * @param dev the ffado device417 * @param number the stream number418 * @param buffer the buffer to copy the samples into419 * @param nsamples the number of samples to be read. the buffer has to be big enough for this amount of samples.420 *421 * @return the amount of samples actually read. -1 on error (xrun).422 */423 int ffado_streaming_read(ffado_device_t *dev, int number, ffado_sample_t *buffer, int nsamples);424 425 /**426 * Write to a specific channel from a supplied buffer.427 *428 * @param dev the ffado device429 * @param number the stream number430 * @param buffer the buffer to copy the samples from431 * @param nsamples the number of samples to be written.432 *433 * @return the amount of samples actually written. -1 on error.434 */435 int ffado_streaming_write(ffado_device_t *dev, int number, ffado_sample_t *buffer, int nsamples);436 437 /**438 413 * Transfer & decode the events from the packet buffer to the sample buffers 439 414 * branches/api-cleanup/SConstruct
r806 r809 331 331 env['REVISION'] = '' 332 332 333 env['FFADO_API_VERSION']=" 5"333 env['FFADO_API_VERSION']="6" 334 334 335 335 env['PACKAGE'] = "libffado" 336 env['VERSION'] = "1.999.1 1"336 env['VERSION'] = "1.999.12" 337 337 env['LIBVERSION'] = "1.0.0" 338 338 branches/api-cleanup/src/bounce/bounce_avdevice.cpp
r742 r809 212 212 Streaming::Port *p=NULL; 213 213 p=new Streaming::AmdtpAudioPort( 214 *processor, 214 215 buff, 215 216 direction, … … 224 225 if (!p) { 225 226 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff); 226 } else {227 228 if (!processor->addPort(p)) {229 debugWarning("Could not register port with stream processor\n");230 free(buff);231 return false;232 } else {233 debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);234 }235 227 } 236 228 free(buff); … … 243 235 Streaming::Port *p=NULL; 244 236 p=new Streaming::AmdtpMidiPort( 237 *processor, 245 238 buff, 246 239 direction, … … 255 248 if (!p) { 256 249 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff); 257 } else {258 259 if (!processor->addPort(p)) {260 debugWarning("Could not register port with stream processor\n");261 free(buff);262 return false;263 } else {264 debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);265 }266 250 } 267 251 free(buff); branches/api-cleanup/src/dice/dice_avdevice.cpp
r785 r809 839 839 case ePT_Analog: 840 840 p=new Streaming::AmdtpAudioPort( 841 *processor, 841 842 portname.str(), 842 843 direction, … … 849 850 case ePT_MIDI: 850 851 p=new Streaming::AmdtpMidiPort( 852 *processor, 851 853 portname.str(), 852 854 direction, … … 864 866 if (!p) { 865 867 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",channelInfo->name.c_str()); 866 } else {867 868 if (!processor->addPort(p)) {869 debugWarning("Could not register port with stream processor\n");870 return false;871 }872 868 } 873 869 branches/api-cleanup/src/ffado.cpp
r807 r809 263 263 } 264 264 265 266 int ffado_streaming_write(ffado_device_t *dev, int i, ffado_sample_t *buffer, int nsamples) {267 Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Playback);268 // use an assert here performancewise,269 // it should already have failed before, if not correct270 assert(p);271 272 return p->writeEvents((void *)buffer, nsamples);273 }274 275 int ffado_streaming_read(ffado_device_t *dev, int i, ffado_sample_t *buffer, int nsamples) {276 Streaming::Port *p=dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Capture);277 // use an assert here performancewise,278 // it should already have failed before, if not correct279 assert(p);280 281 return p->readEvents((void *)buffer, nsamples);282 }283 284 265 int ffado_streaming_get_nb_capture_streams(ffado_device_t *dev) { 285 266 return dev->m_deviceManager->getStreamProcessorManager().getPortCount(Streaming::Port::E_Capture); … … 370 351 return -1; 371 352 } 372 if (!p->setBufferType(Streaming::Port::E_PointerBuffer)) {373 debugWarning("%s: Could not set buffer type to Pointerbuffer\n",p->getName().c_str());374 return -1;375 }376 353 break; 377 354 case ffado_buffer_type_float: 378 355 if (!p->setDataType(Streaming::Port::E_Float)) { 379 356 debugWarning("%s: Could not set data type to Float\n",p->getName().c_str()); 380 return -1;381 }382 if (!p->setBufferType(Streaming::Port::E_PointerBuffer)) {383 debugWarning("%s: Could not set buffer type to Pointerbuffer\n",p->getName().c_str());384 357 return -1; 385 358 } … … 390 363 return -1; 391 364 } 392 if (!p->setBufferType(Streaming::Port::E_RingBuffer)) {393 debugWarning("%s: Could not set buffer type to Ringbuffer\n",p->getName().c_str());394 return -1;395 }396 365 break; 397 366 default: 398 debugWarning("%s: Unsupported buffer type \n",p->getName().c_str());367 debugWarning("%s: Unsupported buffer type (%d)\n", p->getName().c_str(), t); 399 368 return -1; 400 369 } … … 435 404 } 436 405 437 // TODO: the way port buffers are set in the C api doesn't satisfy me438 406 int ffado_streaming_set_capture_stream_buffer(ffado_device_t *dev, int i, char *buff) { 439 407 Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Capture); 440 441 408 // use an assert here performancewise, 442 409 // it should already have failed before, if not correct 443 410 assert(p); 444 445 p->useExternalBuffer(true); 446 p->setExternalBufferAddress((void *)buff); 447 448 return 0; 449 411 p->setBufferAddress((void *)buff); 412 return 0; 450 413 } 451 414 … … 455 418 // it should already have failed before, if not correct 456 419 assert(p); 457 458 p->useExternalBuffer(true); 459 p->setExternalBufferAddress((void *)buff); 460 461 return 0; 462 } 420 p->setBufferAddress((void *)buff); 421 return 0; 422 } branches/api-cleanup/src/genericavc/avc_avdevice.cpp
r784 r809 443 443 } 444 444 445 if (!addPlugToProcessor(*outputPlug, p,445 if (!addPlugToProcessor(*outputPlug, p, 446 446 Streaming::Port::E_Capture)) { 447 447 debugFatal("Could not add plug to processor!\n"); … … 472 472 473 473 if (snoopMode) { 474 if (!addPlugToProcessor(*inputPlug, p,474 if (!addPlugToProcessor(*inputPlug, p, 475 475 Streaming::Port::E_Capture)) { 476 476 debugFatal("Could not add plug to processor!\n"); … … 478 478 } 479 479 } else { 480 if (!addPlugToProcessor(*inputPlug, p,480 if (!addPlugToProcessor(*inputPlug, p, 481 481 Streaming::Port::E_Playback)) { 482 482 debugFatal("Could not add plug to processor!\n"); … … 532 532 channelInfo->m_name.c_str(), channelInfo->m_streamPosition, channelInfo->m_location); 533 533 p=new Streaming::AmdtpAudioPort( 534 *processor, 534 535 portname.str(), 535 536 direction, … … 544 545 channelInfo->m_name.c_str(), channelInfo->m_streamPosition, processor->getPortCount(Streaming::Port::E_Midi)); 545 546 p=new Streaming::AmdtpMidiPort( 547 *processor, 546 548 portname.str(), 547 549 direction, … … 565 567 channelInfo->m_name.c_str(), channelInfo->m_streamPosition, channelInfo->m_location); 566 568 p=new Streaming::AmdtpAudioPort( 569 *processor, 567 570 portname.str(), 568 571 direction, … … 581 584 if (!p) { 582 585 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",channelInfo->m_name.c_str()); 583 } else {584 585 if (!processor->addPort(p)) {586 debugWarning("Could not register port with stream processor\n");587 return false;588 }589 586 } 590 587 } branches/api-cleanup/src/libstreaming/amdtp/AmdtpPort.h
r742 r809 47 47 public: 48 48 49 AmdtpAudioPort(std::string name, 50 enum E_Direction direction, 49 AmdtpAudioPort(PortManager &m, 50 std::string name, 51 enum E_Direction direction, 51 52 int position, 52 53 int location, 53 54 enum E_Formats format) 54 : AudioPort( name, direction),55 : AudioPort(m, name, direction), 55 56 AmdtpPortInfo(position, location, format) 56 57 {}; 57 58 58 59 virtual ~AmdtpAudioPort() {}; 59 60 protected:61 62 60 }; 63 61 … … 74 72 public: 75 73 76 AmdtpMidiPort(std::string name, 77 enum E_Direction direction, 78 int position, 79 int location, 80 enum E_Formats format) 81 : MidiPort(name, direction), 74 AmdtpMidiPort(PortManager &m, 75 std::string name, 76 enum E_Direction direction, 77 int position, 78 int location, 79 enum E_Formats format) 80 : MidiPort(m, name, direction), 82 81 AmdtpPortInfo(position, location, format) 83 82 {}; 84 83 85 86 84 virtual ~AmdtpMidiPort() {}; 87 88 protected:89 90 85 }; 91 86 branches/api-cleanup/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.cpp
r790 r809 167 167 168 168 if(m_data_buffer->writeFrames(nevents, (char *)(data+8), m_last_timestamp)) { 169 // process all ports that should be handled on a per-packet base170 // this is MIDI for AMDTP (due to the need of DBC)171 if(isRunning()) {172 if (!decodePacketPorts((quadlet_t *)(data+8), nevents, packet->dbc)) {173 debugWarning("Problem decoding Packet Ports\n");174 }175 }176 169 return eCRV_OK; 177 170 } else { … … 193 186 bool no_problem=true; 194 187 195 for ( PortVectorIterator it = m_P eriodPorts.begin();196 it != m_P eriodPorts.end();188 for ( PortVectorIterator it = m_Ports.begin(); 189 it != m_Ports.end(); 197 190 ++it ) 198 191 { … … 213 206 case AmdtpPortInfo::E_SPDIF: // still unimplemented 214 207 break; 215 /* for this processor, midi is a packet based port216 208 case AmdtpPortInfo::E_Midi: 217 break;*/ 209 if(decodeMidiEventsToPort(static_cast<AmdtpMidiPort *>(*it), (quadlet_t *)data, offset, nevents)) { 210 debugWarning("Could not decode packet Midi to port %s",(*it)->getName().c_str()); 211 no_problem=false; 212 } 213 break; 218 214 default: // ignore 219 215 break; … … 223 219 } 224 220 225 /**226 * @brief decode a packet for the packet-based ports227 *228 * @param data Packet data229 * @param nevents number of events in data (including events of other ports & port types)230 * @param dbc DataBlockCount value for this packet231 * @return true if all successfull232 */233 bool AmdtpReceiveStreamProcessor::decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc)234 {235 bool ok=true;236 237 quadlet_t *target_event=NULL;238 unsigned int j;239 240 for ( PortVectorIterator it = m_PacketPorts.begin();241 it != m_PacketPorts.end();242 ++it )243 {244 245 #ifdef DEBUG246 AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);247 assert(pinfo); // this should not fail!!248 249 // the only packet type of events for AMDTP is MIDI in mbla250 assert(pinfo->getFormat()==AmdtpPortInfo::E_Midi);251 #endif252 AmdtpMidiPort *mp=static_cast<AmdtpMidiPort *>(*it);253 254 // we decode this directly (no function call) due to the high frequency255 /* idea:256 spec says: current_midi_port=(dbc+j)%8;257 => if we start at (dbc+stream->location-1)%8,258 we'll start at the right event for the midi port.259 => if we increment j with 8, we stay at the right event.260 */261 // FIXME: as we know in advance how big a packet is (syt_interval) we can262 // predict how much loops will be present here263 for(j = (dbc & 0x07)+mp->getLocation(); j < nevents; j += 8) {264 target_event=(quadlet_t *)(data + ((j * m_dimension) + mp->getPosition()));265 quadlet_t sample_int=ntohl(*target_event);266 // FIXME: this assumes that 2X and 3X speed isn't used,267 // because only the 1X slot is put into the ringbuffer268 if(IEC61883_AM824_GET_LABEL(sample_int) != IEC61883_AM824_LABEL_MIDI_NO_DATA) {269 sample_int=(sample_int >> 16) & 0x000000FF;270 if(!mp->writeEvent(&sample_int)) {271 debugWarning("Packet port events lost\n");272 ok=false;273 }274 }275 }276 277 }278 279 return ok;280 }281 282 221 #if USE_SSE 222 #error broken 283 223 typedef float v4sf __attribute__ ((vector_size (16))); 284 224 typedef int v4si __attribute__ ((vector_size (16))); … … 306 246 switch(p->getDataType()) { 307 247 default: 248 debugError("bad type: %d\n", p->getDataType()); 249 return -1; 308 250 case Port::E_Int24: 309 251 { … … 374 316 } 375 317 318 int 319 AmdtpReceiveStreamProcessor::decodeMidiEventsToPort( 320 AmdtpMidiPort *p, quadlet_t *data, 321 unsigned int offset, unsigned int nevents) 322 { 323 #warning implement 324 } 325 376 326 #else 377 327 … … 388 338 switch(p->getDataType()) { 389 339 default: 340 debugError("bad type: %d\n", p->getDataType()); 341 return -1; 390 342 case Port::E_Int24: 391 343 { … … 429 381 return 0; 430 382 } 383 384 int 385 AmdtpReceiveStreamProcessor::decodeMidiEventsToPort( 386 AmdtpMidiPort *p, quadlet_t *data, 387 unsigned int offset, unsigned int nevents) 388 { 389 unsigned int j=0; 390 quadlet_t *target_event; 391 quadlet_t sample_int; 392 unsigned int position = p->getPosition(); 393 unsigned int location = p->getLocation(); 394 395 switch(p->getDataType()) { 396 default: 397 debugError("bad type: %d\n", p->getDataType()); 398 return -1; 399 case Port::E_MidiEvent: 400 { 401 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); 402 403 assert(nevents + offset <= p->getBufferSize()); 404 405 buffer+=offset; 406 407 // clear 408 memset(buffer, 0, nevents * 4); 409 410 // assumes that dbc%8 == 0, which is always true if data points to the 411 // start of a packet in blocking mode 412 // midi events that belong to the same time mpx-ed block should all be 413 // timed at the SYT timestamp of the packet. This basically means that they 414 // all correspond to the first audio frame in the packet. 415 for(j = location; j < nevents; j += 8) { 416 target_event=(quadlet_t *)(data + ((j * m_dimension) + position)); 417 sample_int=ntohl(*target_event); 418 // FIXME: this assumes that 2X and 3X speed isn't used, 419 // because only the 1X slot is put into the ringbuffer 420 if(IEC61883_AM824_GET_LABEL(sample_int) != IEC61883_AM824_LABEL_MIDI_NO_DATA) { 421 sample_int=(sample_int >> 16) & 0x000000FF; 422 sample_int |= 0x01000000; // flag that there is a midi event present 423 } 424 *buffer = sample_int; 425 buffer += 8; // skip 8 frames 426 } 427 } 428 break; 429 } 430 431 return 0; 432 } 433 431 434 #endif 432 435 } // end of namespace Streaming branches/api-cleanup/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.h
r750 r809 101 101 102 102 private: 103 bool decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc);104 103 int decodeMBLAEventsToPort(AmdtpAudioPort *, quadlet_t *data, unsigned int offset, unsigned int nevents); 104 int decodeMidiEventsToPort(AmdtpMidiPort *p, quadlet_t *data, unsigned int offset, unsigned int nevents); 105 105 106 106 unsigned int getSytInterval(); branches/api-cleanup/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.cpp
r798 r809 249 249 int cycle, unsigned int dropped, unsigned int max_length ) 250 250 { 251 struct iec61883_packet *packet = ( struct iec61883_packet * ) data;252 251 if ( m_data_buffer->readFrames ( m_syt_interval, ( char * ) ( data + 8 ) ) ) 253 252 { 254 // process all ports that should be handled on a per-packet base255 // this is MIDI for AMDTP (due to the need of DBC)256 if ( !encodePacketPorts ( ( quadlet_t * ) ( data+8 ), m_syt_interval, packet->dbc ) )257 {258 debugWarning ( "Problem encoding Packet Ports\n" );259 }260 253 debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "XMIT DATA (cy %04d): TSP=%011llu (%04u)\n", 261 254 cycle, m_last_timestamp, ( unsigned int ) TICKS_TO_CYCLES ( m_last_timestamp ) ); … … 395 388 m_syt_interval ); 396 389 397 for ( PortVectorIterator it = m_Ports.begin();398 it != m_Ports.end();399 ++it )400 {401 if ( ( *it )->getPortType() == Port::E_Midi )402 {403 // we use a timing unit of 10ns404 // this makes sure that for the max syt interval405 // we don't have rounding, and keeps the numbers low406 // we have 1 slot every 8 events407 // we have syt_interval events per packet408 // => syt_interval/8 slots per packet409 // packet rate is 8000pkt/sec => interval=125us410 // so the slot interval is (1/8000)/(syt_interval/8)411 // or: 1/(1000 * syt_interval) sec412 // which is 1e9/(1000*syt_interval) nsec413 // or 100000/syt_interval 'units'414 // the event interval is fixed to 320us = 32000 'units'415 if ( ! ( *it )->useRateControl ( true, ( 100000/m_syt_interval ),32000, false ) )416 {417 debugFatal ( "Could not set signal type to PeriodSignalling" );418 return false;419 }420 break;421 }422 }423 390 return true; 424 391 } … … 432 399 bool no_problem = true; 433 400 434 for ( PortVectorIterator it = m_P eriodPorts.begin();435 it != m_P eriodPorts.end();401 for ( PortVectorIterator it = m_Ports.begin(); 402 it != m_Ports.end(); 436 403 ++it ) 437 404 { … … 453 420 case AmdtpPortInfo::E_SPDIF: // still unimplemented 454 421 break; 422 case AmdtpPortInfo::E_Midi: 423 if( encodePortToMidiEvents(static_cast<AmdtpMidiPort *>(*it), (quadlet_t *)data, offset, nevents) ) 424 { 425 debugWarning ( "Could not encode port %s to Midi events", (*it)->getName().c_str() ); 426 no_problem = false; 427 } 428 break; 455 429 default: // ignore 456 430 break; … … 465 439 { 466 440 bool no_problem = true; 467 for(PortVectorIterator it = m_P eriodPorts.begin();468 it != m_P eriodPorts.end();441 for(PortVectorIterator it = m_Ports.begin(); 442 it != m_Ports.end(); 469 443 ++it ) 470 444 { … … 478 452 if ( encodeSilencePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents) ) 479 453 { 480 debugWarning("Could not encode port %s to MBLA events", (*it)->getName().c_str());454 debugWarning("Could not encode silence for port %s to MBLA events", (*it)->getName().c_str()); 481 455 no_problem = false; 482 456 } … … 484 458 case AmdtpPortInfo::E_SPDIF: // still unimplemented 485 459 break; 460 case AmdtpPortInfo::E_Midi: 461 if( encodeSilencePortToMidiEvents(static_cast<AmdtpMidiPort *>(*it), (quadlet_t *)data, offset, nevents) ) 462 { 463 debugWarning ( "Could not encode silence for port %s to Midi events", (*it)->getName().c_str() ); 464 no_problem = false; 465 } 466 break; 486 467 default: // ignore 487 468 break; … … 491 472 } 492 473 493 /**494 * @brief decode a packet for the packet-based ports495 *496 * @param data Packet data497 * @param nevents number of events in data (including events of other ports & port types)498 * @param dbc DataBlockCount value for this packet499 * @return true if all successfull500 */501 bool AmdtpTransmitStreamProcessor::encodePacketPorts ( quadlet_t *data, unsigned int nevents, unsigned int dbc )502 {503 bool ok=true;504 quadlet_t byte;505 506 quadlet_t *target_event=NULL;507 unsigned int j;508 509 for ( PortVectorIterator it = m_PacketPorts.begin();510 it != m_PacketPorts.end();511 ++it )512 {513 514 #ifdef DEBUG515 AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *> ( *it );516 assert ( pinfo ); // this should not fail!!517 518 // the only packet type of events for AMDTP is MIDI in mbla519 assert ( pinfo->getFormat() ==AmdtpPortInfo::E_Midi );520 #endif521 522 AmdtpMidiPort *mp=static_cast<AmdtpMidiPort *> ( *it );523 524 // we encode this directly (no function call) due to the high frequency525 /* idea:526 spec says: current_midi_port=(dbc+j)%8;527 => if we start at (dbc+stream->location-1)%8,528 we'll start at the right event for the midi port.529 => if we increment j with 8, we stay at the right event.530 */531 // FIXME: as we know in advance how big a packet is (syt_interval) we can532 // predict how much loops will be present here533 // first prefill the buffer with NO_DATA's on all time muxed channels534 535 for ( j = ( dbc & 0x07 ) +mp->getLocation(); j < nevents; j += 8 )536 {537 538 quadlet_t tmpval;539 540 target_event= ( quadlet_t * ) ( data + ( ( j * m_dimension ) + mp->getPosition() ) );541 542 if ( mp->canRead() ) // we can send a byte543 {544 mp->readEvent ( &byte );545 byte &= 0xFF;546 tmpval=htonl (547 IEC61883_AM824_SET_LABEL ( ( byte ) <<16,548 IEC61883_AM824_LABEL_MIDI_1X ) );549 550 debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "MIDI port %s, pos=%d, loc=%d, dbc=%d, nevents=%d, dim=%d\n",551 mp->getName().c_str(), mp->getPosition(), mp->getLocation(), dbc, nevents, m_dimension );552 debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "base=%p, target=%p, value=%08X\n",553 data, target_event, tmpval );554 555 }556 else557 {558 // can't send a byte, either because there is no byte,559 // or because this would exceed the maximum rate560 tmpval=htonl (561 IEC61883_AM824_SET_LABEL ( 0,IEC61883_AM824_LABEL_MIDI_NO_DATA ) );562 }563 564 *target_event=tmpval;565 }566 567 }568 return ok;569 }570 571 474 #if USE_SSE 475 #error Broken 572 476 typedef float v4sf __attribute__ ((vector_size (16))); 573 477 typedef int v4si __attribute__ ((vector_size (16))); … … 600 504 { 601 505 default: 506 debugError("bad type: %d\n", p->getDataType()); 507 return -1; 602 508 case Port::E_Int24: 603 509 { … … 687 593 { 688 594 default: 595 debugError("bad type: %d\n", p->getDataType()); 596 return -1; 689 597 case Port::E_Int24: 690 598 { … … 729 637 return 0; 730 638 } 639 640 // note: make sure that the midi events in the port buffer are only placed on (buffer+offset+x)%8 == 0 641 // i.e. 8 frame aligned 642 int AmdtpTransmitStreamProcessor::encodePortToMidiEvents ( AmdtpMidiPort *p, quadlet_t *data, 643 unsigned int offset, unsigned int nevents ) 644 { 645 unsigned int j=0; 646 unsigned int position = p->getPosition(); 647 unsigned int location = p->getLocation(); 648 char byte; 649 650 quadlet_t *target_event; 651 quadlet_t tmpval; 652 653 switch ( p->getDataType() ) 654 { 655 default: 656 debugError("bad type: %d\n", p->getDataType()); 657 return -1; 658 case Port::E_Midi: 659 { 660 quadlet_t *buffer = (quadlet_t *)(p->getBufferAddress()); 661 662 assert(nevents + offset <= p->getBufferSize()); 663 664 buffer+=offset; 665 666 for ( j = location; j < nevents; j += 8 ) 667 { 668 target_event = (quadlet_t *) (data + ((j * m_dimension) + position)); 669 670 if ( *buffer & 0xFF000000 ) // we can send a byte 671 { 672 byte = *buffer & 0xFF; 673 tmpval=htonl(IEC61883_AM824_SET_LABEL((byte)<<16, IEC61883_AM824_LABEL_MIDI_1X)); 674 675 // debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "MIDI port %s, pos=%d, loc=%d, nevents=%d, dim=%d\n", 676 // p->getName().c_str(), position, location, nevents, m_dimension ); 677 // debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "base=%p, target=%p, value=%08X\n", 678 // data, target_event, tmpval ); 679 } else { 680 // can't send a byte, either because there is no byte, 681 // or because this would exceed the maximum rate 682 tmpval=htonl(IEC61883_AM824_SET_LABEL(0, IEC61883_AM824_LABEL_MIDI_NO_DATA)); 683 } 684 *target_event=tmpval; 685 buffer+=8; 686 } 687 } 688 break; 689 } 690 return 0; 691 } 692 731 693 #endif 732 694 … … 758 720 } 759 721 722 int AmdtpTransmitStreamProcessor::encodeSilencePortToMidiEvents ( AmdtpMidiPort *p, quadlet_t *data, 723 unsigned int offset, unsigned int nevents ) 724 { 725 unsigned int j=0; 726 unsigned int position = p->getPosition(); 727 unsigned int location = p->getLocation(); 728 729 quadlet_t *target_event; 730 731 switch ( p->getDataType() ) 732 { 733 default: 734 debugError("bad type: %d\n", p->getDataType()); 735 return -1; 736 case Port::E_Midi: 737 { 738 assert(nevents + offset <= p->getBufferSize()); 739 for ( j = location; j < nevents; j += 8 ) 740 { 741 target_event = (quadlet_t *) (data + ((j * m_dimension) + position)); 742 *target_event=htonl(IEC61883_AM824_SET_LABEL(0, IEC61883_AM824_LABEL_MIDI_NO_DATA)); 743 } 744 } 745 break; 746 } 747 return 0; 748 } 749 760 750 } // end of namespace Streaming branches/api-cleanup/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.h
r750 r809 115 115 unsigned int offset); 116 116 117 bool encodePacketPorts(quadlet_t *data, unsigned int nevents,118 unsigned int dbc);119 120 117 int encodePortToMBLAEvents(AmdtpAudioPort *, quadlet_t *data, 121 unsigned int offset, unsigned int nevents); 118 unsigned int offset, unsigned int nevents); 119 int encodePortToMidiEvents(AmdtpMidiPort *p, quadlet_t *data, 120 unsigned int offset, unsigned int nevents); 122 121 int encodeSilencePortToMBLAEvents(AmdtpAudioPort *, quadlet_t *data, 123 unsigned int offset, unsigned int nevents); 122 unsigned int offset, unsigned int nevents); 123 int encodeSilencePortToMidiEvents(AmdtpMidiPort *p, quadlet_t *data, 124 unsigned int offset, unsigned int nevents); 124 125 125 126 unsigned int getFDF(); branches/api-cleanup/src/libstreaming/generic/Port.cpp
r750 r809 23 23 24 24 #include "Port.h" 25 #include "PortManager.h" 25 26 26 27 #include <stdlib.h> … … 31 32 IMPL_DEBUG_MODULE( Port, Port, DEBUG_LEVEL_NORMAL ); 32 33 33 Port::Port(std::string name, enum E_PortType porttype, enum E_Direction direction) 34 : m_Name(name), 35 m_SignalType(E_PeriodSignalled), 36 m_BufferType(E_PointerBuffer), 37 m_disabled(true), 38 m_buffersize(0), 39 m_eventsize(0), 40 m_DataType(E_Int24), 41 m_PortType(porttype), 42 m_Direction(direction), 43 m_buffer(0), 44 m_ringbuffer(0), 45 m_use_external_buffer(false), 46 m_do_ratecontrol(false), 47 m_event_interval(0), 48 m_slot_interval(0), 49 m_rate_counter(0), 50 m_rate_counter_minimum(0), 51 m_average_ratecontrol(false), 52 m_State(E_Created) 34 Port::Port(PortManager& m, std::string name, 35 enum E_PortType porttype, enum E_Direction direction, enum E_DataType d) 36 : m_Name( name ) 37 , m_disabled( true ) 38 , m_buffersize( 0 ) 39 , m_eventsize( 0 ) 40 , m_DataType( d ) 41 , m_PortType( porttype ) 42 , m_Direction( direction ) 43 , m_buffer( NULL ) 44 , m_manager( m ) 45 , m_State( E_Created ) 53 46 { 54 47 m_manager.registerPort(this); 48 } 49 50 Port::~Port() { 51 m_manager.unregisterPort(this); 55 52 } 56 53 … … 74 71 } 75 72 76 switch (m_BufferType) { 77 case E_PointerBuffer: 78 if (m_use_external_buffer) { 79 // don't do anything 80 } else if (!allocateInternalBuffer()) { 81 debugFatal("Could not allocate internal buffer!\n"); 82 return false; 83 } 84 break; 85 86 case E_RingBuffer: 87 if (m_use_external_buffer) { 88 debugFatal("Cannot use an external ringbuffer! \n"); 89 return false; 90 } else if (!allocateInternalRingBuffer()) { 91 debugFatal("Could not allocate internal ringbuffer!\n"); 92 return false; 93 } 94 break; 95 default: 96 debugFatal("Unsupported buffer type! (%d)\n",(int)m_BufferType); 97 return false; 98 break; 99 } 100 101 m_eventsize=getEventSize(); // this won't change, so cache it 102 73 m_eventsize = getEventSize(); // this won't change, so cache it 74 103 75 m_State = E_Initialized; 104 76 return true; … … 106 78 107 79 bool Port::reset() { 108 if (m_BufferType==E_RingBuffer) { 109 ffado_ringbuffer_reset(m_ringbuffer); 110 } 111 return true; 112 }; 80 return true; 81 } 113 82 114 83 bool Port::setName(std::string name) { … … 138 107 return sizeof(float); 139 108 case E_Int24: // 24 bit 2's complement, packed in a 32bit integer (LSB's) 109 return sizeof(int32_t); 110 case E_MidiEvent: 140 111 return sizeof(uint32_t); 141 case E_ MidiEvent:112 case E_ControlEvent: 142 113 return sizeof(uint32_t); 143 114 default: … … 164 135 break; 165 136 case E_Control: 166 if(d == E_ Default) type_is_ok=true;137 if(d == E_ControlEvent) type_is_ok=true; 167 138 break; 168 139 default: … … 179 150 } 180 151 181 bool Port::setSignalType(enum E_SignalType s) {182 debugOutput( DEBUG_LEVEL_VERBOSE, "Setting signaltype to %d for port %s\n",(int)s,m_Name.c_str());183 if (m_State != E_Created) {184 debugFatal("Port (%s) not in E_Created state: %d\n",m_Name.c_str(),m_State);185 return false;186 }187 188 // do some sanity checks189 bool type_is_ok=false;190 switch (m_PortType) {191 case E_Audio:192 if(s == E_PeriodSignalled) type_is_ok=true;193 break;194 case E_Midi:195 if(s == E_PacketSignalled) type_is_ok=true;196 break;197 case E_Control:198 if(s == E_PeriodSignalled) type_is_ok=true;199 break;200 default:201 break;202 }203 if(!type_is_ok) {204 debugFatal("Signalling type not supported by this type of port!\n");205 return false;206 }207 m_SignalType=s;208 return true;209 }210 211 bool Port::setBufferType(enum E_BufferType b) {212 debugOutput( DEBUG_LEVEL_VERBOSE, "Setting buffer type to %d for port %s\n",(int)b,m_Name.c_str());213 if (m_State != E_Created) {214 debugFatal("Port (%s) not in E_Created state: %d\n",m_Name.c_str(),m_State);215 return false;216 }217 // do some sanity checks218 bool type_is_ok=false;219 switch (m_PortType) {220 case E_Audio:221 if(b == E_PointerBuffer) type_is_ok=true;222 break;223 case E_Midi:224 if(b == E_RingBuffer) type_is_ok=true;225 break;226 case E_Control:227 break;228 default:229 break;230 }231 if(!type_is_ok) {232 debugFatal("Buffer type not supported by this type of port!\n");233 return false;234 }235 m_BufferType=b;236 return true;237 }238 239 bool Port::useExternalBuffer(bool b) {240 // If called on an initialised stream but the request isn't for a change silently241 // allow it (relied on by C API as used by jack backend driver)242 if (m_State==E_Initialized && m_use_external_buffer==b)243 return true;244 245 debugOutput( DEBUG_LEVEL_VERBOSE, "Setting external buffer use to %d for port %s\n",(int)b,m_Name.c_str());246 247 if (m_State != E_Created) {248 debugFatal("Port (%s) not in E_Created state: %d\n",m_Name.c_str(),m_State);249 return false;250 }251 m_use_external_buffer=b;252 return true;253 }254 255 152 // buffer handling api's for pointer buffers 256 153 /** 257 * Get the buffer address (being the external or the internal one).154 * Get the buffer address 258 155 * 259 156 * @param buff 260 157 */ 261 158 void *Port::getBufferAddress() { 262 assert(m_BufferType==E_PointerBuffer);263 159 return m_buffer; 264 160 }; … … 266 162 /** 267 163 * Set the external buffer address. 268 * only call this when you have specified that you will use269 * an external buffer before doing the init()270 164 * 271 165 * @param buff 272 166 */ 273 void Port::setExternalBufferAddress(void *buff) { 274 assert(m_BufferType==E_PointerBuffer); 275 assert(m_use_external_buffer); // don't call this with an internal buffer! 167 void Port::setBufferAddress(void *buff) { 276 168 m_buffer=buff; 277 };278 279 // buffer handling api's for ringbuffers280 bool Port::writeEvent(void *event) {281 282 #ifdef DEBUG283 if (m_State != E_Initialized) {284 debugFatal("Port (%s) not in E_Initialized state: %d\n",m_Name.c_str(),m_State);285 return false;286 }287 288 if(m_BufferType!=E_RingBuffer) {289 debugError("operation not allowed on non E_RingBuffer ports\n");290 show();291 return false;292 }293 assert(m_ringbuffer);294 #endif295 296 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Writing event %08X with size %d to port %s\n",*((quadlet_t *)event),m_eventsize, m_Name.c_str());297 298 return (ffado_ringbuffer_write(m_ringbuffer, (char *)event, m_eventsize)==m_eventsize);299 }300 301 bool Port::readEvent(void *event) {302 303 #ifdef DEBUG304 if (m_State != E_Initialized) {305 debugFatal("Port (%s) not in E_Initialized state: %d\n",m_Name.c_str(),m_State);306 return false;307 }308 309 if(m_BufferType!=E_RingBuffer) {310 debugError("operation not allowed on non E_RingBuffer ports\n");311 show();312 return false;313 }314 assert(m_ringbuffer);315 #endif316 317 318 unsigned int read=ffado_ringbuffer_read(m_ringbuffer, (char *)event, m_eventsize);319 320 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Reading event %X with size %d from port %s\n",*((quadlet_t *)event),m_eventsize,m_Name.c_str());321 322 323 return (read==m_eventsize);324 }325 326 int Port::writeEvents(void *event, unsigned int nevents) {327 328 #ifdef DEBUG329 if (m_State != E_Initialized) {330 debugFatal("Port (%s) not in E_Initialized state: %d\n",m_Name.c_str(),m_State);331 return false;332 }333 334 if(m_BufferType!=E_RingBuffer) {335 debugError("operation not allowed on non E_RingBuffer ports\n");336 show();337 return false;338 }339 assert(m_ringbuffer);340 #endif341 342 343 unsigned int bytes2write=m_eventsize*nevents;344 345 unsigned int written=ffado_ringbuffer_write(m_ringbuffer, (char *)event,bytes2write)/m_eventsize;346 347 #ifdef DEBUG348 if(written) {349 unsigned int i=0;350 quadlet_t * tmp=(quadlet_t *)event;351 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Written %d events (",written);352 for (i=0;i<written;i++) {353 debugOutputShort(DEBUG_LEVEL_VERY_VERBOSE, "%X ", *(tmp+i));354 }355 debugOutputShort(DEBUG_LEVEL_VERY_VERBOSE, ") to port %s\n",m_Name.c_str());356 }357 #endif358 359 return written;360 361 }362 363 int Port::readEvents(void *event, unsigned int nevents) {364 365 #ifdef DEBUG366 if (m_State != E_Initialized) {367 debugFatal("Port (%s) not in E_Initialized state: %d\n",m_Name.c_str(),m_State);368 return false;369 }370 if(m_BufferType!=E_RingBuffer) {371 debugError("operation not allowed on non E_RingBuffer ports\n");372 show();373 return false;374 }375 assert(m_ringbuffer);376 #endif377 378 379 unsigned int bytes2read=m_eventsize*nevents;380 381 unsigned int read=ffado_ringbuffer_read(m_ringbuffer, (char *)event, bytes2read)/m_eventsize;382 383 #ifdef DEBUG384 if(read) {385 unsigned int i=0;386 quadlet_t * tmp=(quadlet_t *)event;387 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Read %d events (",read);388 for (i=0;i<read;i++) {389 debugOutputShort(DEBUG_LEVEL_VERY_VERBOSE, "%X ", *(tmp+i));390 }391 debugOutputShort(DEBUG_LEVEL_VERY_VERBOSE, ") from port %s\n",m_Name.c_str());392 }393 #endif394 395 return read;396 }397 398 /* rate control */399 bool Port::canRead() {400 bool byte_present_in_buffer;401 402 bool retval=false;403 404 assert(m_ringbuffer);405 406 byte_present_in_buffer=(ffado_ringbuffer_read_space(m_ringbuffer) >= m_eventsize);407 408 if(byte_present_in_buffer) {409 410 if(!m_do_ratecontrol) {411 return true;412 }413 414 if(m_rate_counter <= 0) {415 // update the counter416 if(m_average_ratecontrol) {417 m_rate_counter += m_event_interval;418 assert(m_rate_counter<m_event_interval);419 } else {420 m_rate_counter = m_event_interval;421 }422 423 retval=true;424 } else {425 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Rate limit (%s)! rate_counter=%d \n",m_Name.c_str(),m_rate_counter);426 427 }428 }429 430 431 m_rate_counter -= m_slot_interval;432 433 // we have to limit the decrement of the ratecounter somehow.434 // m_rate_counter_minimum is initialized when enabling ratecontrol435 if(m_rate_counter < m_rate_counter_minimum) {436 m_rate_counter = m_rate_counter_minimum;437 }438 439 return retval;440 }441 442 bool Port::useRateControl(bool use, unsigned int slot_interval,443 unsigned int event_interval, bool average) {444 445 if (use) {446 debugOutput(DEBUG_LEVEL_VERBOSE, "Enabling rate control for port %s...\n",m_Name.c_str());447 if(slot_interval>event_interval) {448 debugWarning("Rate control not needed!\n",m_Name.c_str());449 m_do_ratecontrol=false;450 return false;451 }452 if(slot_interval==0) {453 debugFatal("Cannot have slot interval == 0!\n");454 m_do_ratecontrol=false;455 return false;456 }457 if(event_interval==0) {458 debugFatal("Cannot have event interval == 0!\n");459 m_do_ratecontrol=false;460 return false;461 }462 m_do_ratecontrol=use;463 m_event_interval=event_interval;464 m_slot_interval=slot_interval;465 m_rate_counter=0;466 467 // NOTE: pretty arbitrary, but in average mode this limits the peak stream rate468 m_rate_counter_minimum=-(2*event_interval);469 470 m_average_ratecontrol=average;471 472 } else {473 debugOutput(DEBUG_LEVEL_VERBOSE, "Disabling rate control for port %s...\n",m_Name.c_str());474 m_do_ratecontrol=use;475 }476 return true;477 169 } 478 170 … … 482 174 debugOutput(DEBUG_LEVEL_VERBOSE, "Enabling port %s...\n",m_Name.c_str()); 483 175 m_disabled=false; 484 } ;176 } 485 177 486 178 /// Disable the port. (this can be called anytime) … … 489 181 debugOutput(DEBUG_LEVEL_VERBOSE, "Disabling port %s...\n",m_Name.c_str()); 490 182 m_disabled=false; 491 };492 493 494 /* Private functions */495 496 bool Port::allocateInternalBuffer() {497 int event_size=getEventSize();498 499 debugOutput(DEBUG_LEVEL_VERBOSE,500 "Allocating internal buffer of %d events with size %d (%s)\n",501 m_buffersize, event_size, m_Name.c_str());502 503 if(m_buffer) {504 debugWarning("already has an internal buffer attached, re-allocating\n");505 freeInternalBuffer();506 }507 508 m_buffer=calloc(m_buffersize,event_size);509 if (!m_buffer) {510 debugFatal("could not allocate internal buffer\n");511 m_buffersize=0;512 return false;513 }514 515 return true;516 }517 518 void Port::freeInternalBuffer() {519 debugOutput(DEBUG_LEVEL_VERBOSE,520 "Freeing internal buffer (%s)\n",m_Name.c_str());521 522 if(m_buffer) {523 free(m_buffer);524 m_buffer=0;525 }526 }527 528 bool Port::allocateInternalRingBuffer() {529 int event_size=getEventSize();530 531 debugOutput(DEBUG_LEVEL_VERBOSE,532 "Allocating internal buffer of %d events with size %d (%s)\n",533 m_buffersize, event_size, m_Name.c_str());534 535 if(m_ringbuffer) {536 debugWarning("already has an internal ringbuffer attached, re-allocating\n");537 freeInternalRingBuffer();538 }539 540 m_ringbuffer=ffado_ringbuffer_create(m_buffersize * event_size);541 if (!m_ringbuffer) {542 debugFatal("could not allocate internal ringbuffer\n");543 m_buffersize=0;544 return false;545 }546 547 return true;548 }549 550 void Port::freeInternalRingBuffer() {551 debugOutput(DEBUG_LEVEL_VERBOSE,552 "Freeing internal ringbuffer (%s)\n",m_Name.c_str());553 554 if(m_ringbuffer) {555 ffado_ringbuffer_free(m_ringbuffer);556 m_ringbuffer=0;557 }558 183 } 559 184 560 185 void Port::show() { 561 186 debugOutput(DEBUG_LEVEL_VERBOSE,"Name : %s\n", m_Name.c_str()); 562 debugOutput(DEBUG_LEVEL_VERBOSE,"Signal Type : %d\n", m_SignalType);563 debugOutput(DEBUG_LEVEL_VERBOSE,"Buffer Type : %d\n", m_BufferType);564 187 debugOutput(DEBUG_LEVEL_VERBOSE,"Enabled? : %d\n", m_disabled); 565 188 debugOutput(DEBUG_LEVEL_VERBOSE,"State? : %d\n", m_State); … … 569 192 debugOutput(DEBUG_LEVEL_VERBOSE,"Port Type : %d\n", m_PortType); 570 193 debugOutput(DEBUG_LEVEL_VERBOSE,"Direction : %d\n", m_Direction); 571 debugOutput(DEBUG_LEVEL_VERBOSE,"Rate Control? : %d\n", m_do_ratecontrol);572 194 } 573 195 branches/api-cleanup/src/libstreaming/generic/Port.h
r742 r809 33 33 34 34 namespace Streaming { 35 class PortManager; 35 36 36 37 /*! … … 53 54 OK. 54 55 55 \todo rework the implementation into something more beautifull56 56 */ 57 57 class Port { 58 58 59 59 public: 60 friend class PortManager;61 62 /*63 * IMPORTANT: if you add something to any of these enum's, be sure to64 * check the code where they are used.65 */66 67 /*!68 \brief Specifies the buffer type for ports69 70 A PointerBuffer uses the getBufferAddress() and setBufferAddres() interface71 A Ringbuffer uses the read/write interface72 */73 enum E_BufferType {74 E_PointerBuffer,75 E_RingBuffer76 };77 78 /*!79 \brief Specifies the signalling type for ports80 */81 enum E_SignalType {82 E_PacketSignalled, ///< the port is to be processed for every packet83 E_PeriodSignalled, ///< the port is to be processed after a period of frames84 // E_SampleSignalled ///< the port is to be processed after each frame (sample)85 };86 87 60 /*! 88 61 \brief The datatype of the port buffer … … 92 65 E_Int24, 93 66 E_MidiEvent, 94 E_ Default,67 E_ControlEvent, 95 68 }; 96 69 … … 112 85 }; 113 86 114 Port(std::string name, enum E_PortType porttype, enum E_Direction direction); 115 116 virtual ~Port() 117 {}; 87 Port(PortManager&, std::string name, enum E_PortType, enum E_Direction, enum E_DataType); 88 89 virtual ~Port(); 118 90 119 91 … … 151 123 enum E_DataType getDataType() {return m_DataType;}; 152 124 153 /**154 * \brief sets the event type for the port buffer155 *156 * \note use before calling init()157 */158 virtual bool setSignalType(enum E_SignalType );159 160 enum E_SignalType getSignalType() {return m_SignalType;}; ///< returns the signalling type of the port161 162 /**163 * \brief sets the buffer type for the port164 *165 * \note use before calling init()166 */167 virtual bool setBufferType(enum E_BufferType );168 169 enum E_BufferType getBufferType() {return m_BufferType;}; ///< returns the buffer type of the port170 171 125 enum E_PortType getPortType() {return m_PortType;}; ///< returns the port type (is fixed) 172 126 enum E_Direction getDirection() {return m_Direction;}; ///< returns the direction (is fixed) … … 193 147 virtual bool setBufferSize(unsigned int); 194 148 195 /** 196 * \brief use an external buffer (or not) 197 * 198 * \note use before calling init() 199 */ 200 virtual bool useExternalBuffer(bool b); 201 202 void setExternalBufferAddress(void *buff); 203 204 205 /** 206 * \brief enable/disable ratecontrol 207 * 208 * Rate control is nescessary for some types of ports (most notably 209 * midi). The StreamProcessor that handles the port should call canRead() 210 * everytime a 'slot' that could be filled with an event passes. The canRead 211 * function will return true if 212 * (1) there is an event ready in the buffer 213 * (2) we are allowed to send an event in this slot 214 * 215 * Setting the rate works is done with the slot_interval and the event_interval 216 * parameters. On every call to canRead(), a counter is decremented with 217 * slot_interval. If the counter drops below 0, canRead() returns true and resets 218 * the counter to event_interval. 219 * 220 * e.g. for AMDTP midi, we are only allowed to send a midi byte every 320us 221 * if the SYT interval is 8, there is exactly one midi slot every packet. 222 * therefore the slot_interval is 1/8000s (=125us), and the event_interval 223 * is 320us. 224 * 225 * Note that the interval parameters are unitless, so you can adapt them 226 * to your needs. In the AMDTP case for example, when the SYT interval is 32 227 * (when the samplerate is 192kHz for example) there are 4 midi slots in 228 * each packet, making the slot time interval 125us/4 = 31.25us. 229 * The event time interval stays the same (320us). We can however set the 230 * slot_interval to 3125 and the event_interval to 32000, as we can choose 231 * the unit of the counter time step (chosen to be 10ns in this case). 232 * 233 * The average argument deserves some attention too. If average is true, we use 234 * average rate control. This means that on average there will be a delay of 235 * event_interval between two events, but that sometimes there can be a smaller 236 * delay. This mode fixes the average rate of the stream. 237 * If average is false, there will always be a minimal delay of event_interval 238 * between two events. This means that the maximum rate of the stream is fixed, 239 * and that the average rate will be lower than (or at max equal to) the rate in 240 * average mode. 241 * 242 * 243 * \note only works for the E_RingBuffer ports 244 * \note use before calling init() 245 * 246 * @param use set this to true to use rate control 247 * @param slot_interval the interval between slots 248 * @param event_interval the interval between events 249 * @param average use average rate control 250 * @return true if rate control was enabled/disabled successfully 251 */ 252 virtual bool useRateControl(bool use, unsigned int slot_interval, 253 unsigned int event_interval, bool average); 254 255 bool usingRateControl() { return m_do_ratecontrol;}; ///< are we using rate control? 256 257 /** 258 * Can we send an event in this slot. subject to rate control and 259 * byte availability. 260 * @return true if we can send an event on this slot 261 */ 262 bool canRead(); 263 264 // FIXME: this is not really OO, but for performance??? 149 void setBufferAddress(void *buff); 265 150 void *getBufferAddress(); 266 151 267 // TODO: extend this with a blocking interface 268 bool writeEvent(void *event); ///< write one event 269 bool readEvent(void *event); ///< read one event 270 int writeEvents(void *event, unsigned int nevents); ///< write multiple events 271 int readEvents(void *event, unsigned int nevents); ///< read multiple events 152 PortManager& getManager() { return m_manager; }; 272 153 273 154 virtual void setVerboseLevel(int l); 274 155 virtual void show(); 275 156 276 157 protected: 277 158 std::string m_Name; ///< Port name, [at construction] 278 279 enum E_SignalType m_SignalType; ///< Signalling type, [at construction]280 enum E_BufferType m_BufferType; ///< Buffer type, [at construction]281 282 159 bool m_disabled; ///< is the port disabled?, [anytime] 283 160 … … 290 167 291 168 void *m_buffer; 292 ffado_ringbuffer_t *m_ringbuffer; 293 bool m_use_external_buffer; 294 295 bool m_do_ratecontrol; 296 int m_event_interval; 297 int m_slot_interval; 298 int m_rate_counter; 299 int m_rate_counter_minimum; 300 bool m_average_ratecontrol; 301 302 bool allocateInternalBuffer(); 303 void freeInternalBuffer(); 304 305 bool allocateInternalRingBuffer(); 306 void freeInternalRingBuffer(); 169 170 PortManager& m_manager; 307 171 308 172 DECLARE_DEBUG_MODULE; 309 310 311 312 313 314 315 316 317 318 319 320 173 174 // the state machine 175 protected: 176 enum EStates { 177 E_Created, 178 E_Initialized, 179 E_Prepared, 180 E_Running, 181 E_Error 182 }; 183 184 enum EStates m_State; 321 185 }; 322 186 … … 330 194 public: 331 195 332 AudioPort( std::string name, enum E_Direction direction)333 : Port( name, E_Audio, direction)196 AudioPort(PortManager& m, std::string name, enum E_Direction direction) 197 : Port(m, name, E_Audio, direction, E_Int24) 334 198 {}; 335 199 336 200 virtual ~AudioPort() {}; 337 338 protected:339 340 341 201 }; 342 202 … … 350 210 public: 351 211 352 MidiPort( std::string name, enum E_Direction direction)353 : Port( name, E_Midi, direction)212 MidiPort(PortManager& m, std::string name, enum E_Direction direction) 213 : Port(m, name, E_Midi, direction, E_MidiEvent) 354 214 {}; 355 215 virtual ~MidiPort() {}; 356 357 358 protected:359 360 361 216 }; 362 217 … … 370 225 public: 371 226 372 ControlPort( std::string name, enum E_Direction direction)373 : Port( name, E_Control, direction)227 ControlPort(PortManager& m, std::string name, enum E_Direction direction) 228 : Port(m, name, E_Control, direction, E_ControlEvent) 374 229 {}; 375 230 virtual ~ControlPort() {}; 376 377 378 protected:379 380 381 231 }; 382 232 branches/api-cleanup/src/libstreaming/generic/PortManager.cpp
r750 r809 40 40 41 41 PortManager::~PortManager() { 42 // deleteAllPorts(); 43 } 44 45 // bool PortManager::setPortBuffersize(unsigned int newsize) { 46 // debugOutput( DEBUG_LEVEL_VERBOSE, "setting port buffer size to %d\n",newsize); 47 // 48 // 49 // for ( PortVectorIterator it = m_Ports.begin(); 50 // it != m_Ports.end(); 51 // ++it ) 52 // { 53 // if(!(*it)->setBufferSize(newsize)) { 54 // debugFatal("Could not set buffer size for port %s\n",(*it)->getName().c_str()); 55 // return false; 56 // } 57 // } 58 // 59 // return true; //not found 60 // 61 // } 42 // delete all ports that are still registered to the manager 43 for ( PortVectorIterator it = m_Ports.begin(); 44 it != m_Ports.end(); 45 ++it ) 46 { 47 delete *it; 48 } 49 } 62 50 63 51 bool PortManager::makeNameUnique(Port *port) … … 96 84 * @return 97 85 */ 98 bool PortManager:: addPort(Port *port)86 bool PortManager::registerPort(Port *port) 99 87 { 100 88 assert(port); … … 113 101 } 114 102 115 bool PortManager:: deletePort(Port *port)103 bool PortManager::unregisterPort(Port *port) 116 104 { 117 105 assert(port); … … 124 112 if(*it == port) { 125 113 m_Ports.erase(it); 126 // delete *it;127 114 return true; 128 115 } … … 132 119 133 120 return false; //not found 134 135 }136 137 void PortManager::deleteAllPorts()138 {139 debugOutput( DEBUG_LEVEL_VERBOSE, "deleting all ports\n");140 141 for ( PortVectorIterator it = m_Ports.begin();142 it != m_Ports.end();143 ++it )144 {145 m_Ports.erase(it);146 // delete *it;147 }148 149 return;150 121 151 122 } … … 213 184 { 214 185 if(!(*it)->init()) { 215 debugFatal("Could not init port %s ",(*it)->getName().c_str());186 debugFatal("Could not init port %s\n", (*it)->getName().c_str()); 216 187 return false; 217 188 } … … 222 193 bool PortManager::preparePorts() { 223 194 debugOutput( DEBUG_LEVEL_VERBOSE, "preparing ports\n"); 224 225 // clear the cache lists226 m_PeriodPorts.clear();227 m_PacketPorts.clear();228 195 229 196 for ( PortVectorIterator it = m_Ports.begin(); … … 236 203 } 237 204 238 // now prepare the cache lists239 switch((*it)->getSignalType()) {240 case Port::E_PacketSignalled:241 m_PacketPorts.push_back(*it);242 break;243 case Port::E_PeriodSignalled:244 m_PeriodPorts.push_back(*it);245 break;246 default:247 debugWarning("%s has unsupported port type\n",248 (*it)->getName().c_str());249 break;250 }251 205 } 252 206 return true; branches/api-cleanup/src/libstreaming/generic/PortManager.h
r742 r809 33 33 namespace Streaming { 34 34 35 class Port;36 35 typedef std::vector<Port *> PortVector; 37 36 typedef std::vector<Port *>::iterator PortVectorIterator; … … 50 49 51 50 virtual bool makeNameUnique(Port *port); 52 virtual bool addPort(Port *port); 53 virtual bool deletePort(Port *port); 54 virtual void deleteAllPorts(); 51 virtual bool registerPort(Port *port); 52 virtual bool unregisterPort(Port *port); 55 53 56 54 int getPortCount(enum Port::E_PortType); 57 55 int getPortCount(); 58 59 // virtual bool setPortBuffersize(unsigned int newsize);60 56 61 57 Port *getPortAtIdx(unsigned int index); … … 69 65 protected: 70 66 PortVector m_Ports; 71 PortVector m_PacketPorts;72 PortVector m_PeriodPorts;73 // PortVector m_SamplePorts;74 67 75 68 DECLARE_DEBUG_MODULE; 76 77 69 }; 78 70 branches/api-cleanup/src/libstreaming/generic/StreamProcessor.cpp
r807 r809 960 960 { 961 961 bool no_problem=true; 962 for ( PortVectorIterator it = m_P eriodPorts.begin();963 it != m_P eriodPorts.end();962 for ( PortVectorIterator it = m_Ports.begin(); 963 it != m_Ports.end(); 964 964 ++it ) { 965 965 if((*it)->isDisabled()) {continue;}; 966 966 967 //FIXME: make this into a static_cast when not DEBUG? 968 Port *port=dynamic_cast<Port *>(*it); 969 970 switch(port->getPortType()) { 971 972 case Port::E_Audio: 973 if(provideSilenceToPort(static_cast<AudioPort *>(*it), offset, nevents)) { 974 debugWarning("Could not put silence into to port %s",(*it)->getName().c_str()); 975 no_problem=false; 976 } 977 break; 978 // midi is a packet based port, don't process 979 // case MotuPortInfo::E_Midi: 980 // break; 981 982 default: // ignore 983 break; 967 if(provideSilenceToPort((*it), offset, nevents)) { 968 debugWarning("Could not put silence into to port %s",(*it)->getName().c_str()); 969 no_problem=false; 984 970 } 985 971 } … … 988 974 989 975 int 990 StreamProcessor::provideSilenceToPort( 991 AudioPort *p, unsigned int offset, unsigned int nevents) 976 StreamProcessor::provideSilenceToPort(Port *p, unsigned int offset, unsigned int nevents) 992 977 { 993 978 unsigned int j=0; 994 979 switch(p->getDataType()) { 995 980 default: 981 debugError("Invalid port type: %d\n", p->getDataType()); 982 return -1; 996 983 case Port::E_Int24: 984 case Port::E_MidiEvent: 985 case Port::E_ControlEvent: 997 986 { 998 987 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); … … 1000 989 buffer+=offset; 1001 990 1002 for(j = 0; j < nevents; j += 1) { // decode max nsamples991 for(j = 0; j < nevents; j += 1) { 1003 992 *(buffer)=0; 1004 993 buffer++; … … 1012 1001 buffer+=offset; 1013 1002 1014 for(j = 0; j < nevents; j += 1) { // decode max nsamples1003 for(j = 0; j < nevents; j += 1) { 1015 1004 *buffer = 0.0; 1016 1005 buffer++; … … 1320 1309 return false; 1321 1310 } 1322 switch ((*it)->getPortType()) {1323 case Port::E_Audio:1324 if(!(*it)->setSignalType(Port::E_PeriodSignalled)) {1325 debugFatal("Could not set signal type to PeriodSignalling");1326 return false;1327 }1328 // buffertype and datatype are dependant on the API1329 debugWarning("---------------- ! Doing hardcoded dummy setup ! --------------\n");1330 // buffertype and datatype are dependant on the API1331 if(!(*it)->setBufferType(Port::E_PointerBuffer)) {1332 debugFatal("Could not set buffer type");1333 return false;1334 }1335 if(!(*it)->useExternalBuffer(true)) {1336 debugFatal("Could not set external buffer usage");1337 return false;1338 }1339 if(!(*it)->setDataType(Port::E_Float)) {1340 debugFatal("Could not set data type");1341 return false;1342 }1343 break;1344 case Port::E_Midi:1345 if(!(*it)->setSignalType(Port::E_PacketSignalled)) {1346 debugFatal("Could not set signal type to PacketSignalling");1347 return false;1348 }1349 // buffertype and datatype are dependant on the API1350 debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n");1351 // buffertype and datatype are dependant on the API1352 if(!(*it)->setBufferType(Port::E_RingBuffer)) {1353 debugFatal("Could not set buffer type");1354 return false;1355 }1356 if(!(*it)->setDataType(Port::E_MidiEvent)) {1357 debugFatal("Could not set data type");1358 return false;1359 }1360 break;1361 default:1362 debugWarning("Unsupported port type specified\n");1363 break;1364 }1365 1311 } 1366 1312 // the API specific settings of the ports should already be set, branches/api-cleanup/src/libstreaming/generic/StreamProcessor.h
r807 r809 292 292 {debugWarning("call not allowed\n"); return false;}; 293 293 protected: // some generic helpers 294 int provideSilenceToPort( AudioPort *p, unsigned int offset, unsigned int nevents);294 int provideSilenceToPort(Port *p, unsigned int offset, unsigned int nevents); 295 295 bool provideSilenceBlock(unsigned int nevents, unsigned int offset); 296 296 branches/api-cleanup/src/libstreaming/motu/MotuPort.h
r742 r809 48 48 public: 49 49 50 MotuAudioPort(std::string name, 51 enum E_Direction direction, 52 int position, 53 int size) 54 : AudioPort(name, direction), 50 MotuAudioPort(PortManager &m, 51 std::string name, 52 enum E_Direction direction, 53 int position, 54 int size) 55 : AudioPort(m, name, direction), 55 56 MotuPortInfo( position, size) // TODO: add more port information parameters here if nescessary 56 57 {}; 57 58 58 59 virtual ~MotuAudioPort() {}; 59 60 protected:61 62 60 }; 63 61 … … 73 71 public: 74 72 75 MotuMidiPort(std::string name, 76 enum E_Direction direction, 77 int position) 78 : MidiPort(name, direction), 73 MotuMidiPort(PortManager &m, 74 std::string name, 75 enum E_Direction direction, 76 int position) 77 : MidiPort(m, name, direction), 79 78 MotuPortInfo(position, 0) // TODO: add more port information parameters here if nescessary 80 79 {}; 81 80 82 83 81 virtual ~MotuMidiPort() {}; 84 85 protected:86 87 82 }; 88 83 … … 98 93 public: 99 94 100 MotuControlPort(std::string name, 101 enum E_Direction direction, 102 int position) 103 : ControlPort(name, direction), 95 MotuControlPort(PortManager &m, 96 std::string name, 97 enum E_Direction direction, 98 int position) 99 : ControlPort(m, name, direction), 104 100 MotuPortInfo(position, 2) // TODO: add more port information parameters here if nescessary 105 101 {}; 106 102 107 108 103 virtual ~MotuControlPort() {}; 109 110 protected:111 112 104 }; 113 105 branches/api-cleanup/src/libstreaming/motu/MotuReceiveStreamProcessor.cpp
r750 r809 187 187 188 188 if(m_data_buffer->writeFrames(n_events, (char *)(data+8), m_last_timestamp)) { 189 int dbc = get_bits(ntohl(quadlet[0]), 8, 8);190 // process all ports that should be handled on a per-packet base191 // this is MIDI for AMDTP (due to the need of DBC)192 if(isRunning()) {193 if (!decodePacketPorts((quadlet_t *)(data+8), n_events, dbc)) {194 debugWarning("Problem decoding Packet Ports\n");195 }196 }197 189 return eCRV_OK; 198 190 } else { … … 211 203 { 212 204 bool no_problem=true; 213 for ( PortVectorIterator it = m_P eriodPorts.begin();214 it != m_P eriodPorts.end();205 for ( PortVectorIterator it = m_Ports.begin(); 206 it != m_Ports.end(); 215 207 ++it ) { 216 208 if((*it)->isDisabled()) {continue;}; 217 209 218 //FIXME: make this into a static_cast when not DEBUG? 219 Port *port=dynamic_cast<Port *>(*it); 210 Port *port=(*it); 220 211 221 212 switch(port->getPortType()) { … … 227 218 } 228 219 break; 229 // midi is a packet based port, don't process 230 // case MotuPortInfo::E_Midi: 231 // break; 220 case Port::E_Midi: 221 // if(decodeMotuMidiEventsToPort(static_cast<MotuMidiPort *>(*it), (quadlet_t *)data, offset, nevents)) { 222 // debugWarning("Could not decode packet midi data to port %s",(*it)->getName().c_str()); 223 // no_problem=false; 224 // } 225 break; 232 226 233 227 default: // ignore … … 236 230 } 237 231 return no_problem; 238 }239 240 /**241 * @brief decode a packet for the packet-based ports242 *243 * @param data Packet data244 * @param nevents number of events in data (including events of other ports & port types)245 * @param dbc DataBlockCount value for this packet246 * @return true if all successfull247 */248 bool MotuReceiveStreamProcessor::decodePacketPorts(quadlet_t *data, unsigned int nevents,249 unsigned int dbc) {250 bool ok=true;251 252 // Use char here since the source address won't necessarily be253 // aligned; use of an unaligned quadlet_t may cause issues on254 // certain architectures. Besides, the source for MIDI data going255 // directly to the MOTU isn't structured in quadlets anyway; it is a256 // sequence of 3 unaligned bytes.257 unsigned char *src = NULL;258 259 for ( PortVectorIterator it = m_PacketPorts.begin();260 it != m_PacketPorts.end();261 ++it ) {262 263 Port *port=dynamic_cast<Port *>(*it);264 assert(port); // this should not fail!!265 266 // Currently the only packet type of events for MOTU267 // is MIDI in mbla. However in future control data268 // might also be sent via "packet" events, so allow269 // for this possible expansion.270 271 // FIXME: MIDI input is completely untested at present.272 switch (port->getPortType()) {273 case Port::E_Midi: {274 MotuMidiPort *mp=static_cast<MotuMidiPort *>(*it);275 signed int sample;276 unsigned int j = 0;277 // Get MIDI bytes if present anywhere in the278 // packet. MOTU MIDI data is sent using a279 // 3-byte sequence starting at the port's280 // position. It's thought that there can never281 // be more than one MIDI byte per packet, but282 // for completeness we'll check the entire packet283 // anyway.284 src = (unsigned char *)data + mp->getPosition();285 while (j < nevents) {286 if (*src==0x01 && *(src+1)==0x00) {287 sample = *(src+2);288 if (!mp->writeEvent(&sample)) {289 debugWarning("MIDI packet port events lost\n");290 ok = false;291 }292 }293 j++;294 src += m_event_size;295 }296 break;297 }298 default:299 debugOutput(DEBUG_LEVEL_VERBOSE, "Unknown packet-type port format %d\n",port->getPortType());300 return ok;301 }302 }303 304 return ok;305 232 } 306 233 branches/api-cleanup/src/libstreaming/motu/MotuTransmitStreamProcessor.cpp
r798 r809 62 62 {} 63 63 64 65 64 unsigned int 66 65 MotuTransmitStreamProcessor::getMaxPacketSize() { … … 310 309 } 311 310 312 // Process all ports that should be handled on a per-packet base313 // this is MIDI for AMDTP (due to the need of DBC, which is lost314 // when putting the events in the ringbuffer)315 // for motu this might also be control data, however as control316 // data isn't time specific I would also include it in the period317 // based processing318 319 // FIXME: m_tx_dbc probably needs to be initialised to a non-zero320 // value somehow so MIDI sync is possible. For now we ignore321 // this issue.322 if (!encodePacketPorts((quadlet_t *)(data+8), n_events, m_tx_dbc)) {323 debugWarning("Problem encoding Packet Ports\n");324 }325 326 311 return eCRV_OK; 327 312 } … … 403 388 { 404 389 debugOutput ( DEBUG_LEVEL_VERBOSE, "Preparing (%p)...\n", this ); 405 406 407 #if 0408 for ( PortVectorIterator it = m_Ports.begin();409 it != m_Ports.end();410 ++it )411 {412 if ( ( *it )->getPortType() == Port::E_Midi )413 {414 // we use a timing unit of 10ns415 // this makes sure that for the max syt interval416 // we don't have rounding, and keeps the numbers low417 // we have 1 slot every 8 events418 // we have syt_interval events per packet419 // => syt_interval/8 slots per packet420 // packet rate is 8000pkt/sec => interval=125us421 // so the slot interval is (1/8000)/(syt_interval/8)422 // or: 1/(1000 * syt_interval) sec423 // which is 1e9/(1000*syt_interval) nsec424 // or 100000/syt_interval 'units'425 // the event interval is fixed to 320us = 32000 'units'426 if ( ! ( *it )->useRateControl ( true, ( 100000/m_syt_interval ),32000, false ) )427 {428 debugFatal ( "Could not set signal type to PeriodSignalling" );429 return false;430 }431 break;432 }433 }434 #endif435 390 return true; 436 391 } … … 450 405 } 451 406 452 for ( PortVectorIterator it = m_P eriodPorts.begin();453 it != m_P eriodPorts.end();407 for ( PortVectorIterator it = m_Ports.begin(); 408 it != m_Ports.end(); 454 409 ++it ) { 455 410 // If this port is disabled, don't process it 456 411 if((*it)->isDisabled()) {continue;}; 457 412 458 //FIXME: make this into a static_cast when not DEBUG? 459 Port *port=dynamic_cast<Port *>(*it); 413 Port *port=(*it); 460 414 461 415 switch(port->getPortType()) { … … 463 417 case Port::E_Audio: 464 418 if (encodePortToMotuEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) { 465 debugWarning("Could not encode port %s to M BLAevents",(*it)->getName().c_str());419 debugWarning("Could not encode port %s to Motu events",(*it)->getName().c_str()); 466 420 no_problem=false; 467 421 } 468 422 break; 469 // midi is a packet based port, don't process 470 // case MotuPortInfo::E_Midi: 471 // break; 472 423 case Port::E_Midi: 424 // if (encodePortToMotuMidiEvents(static_cast<MotuMidiPort *>(*it), (quadlet_t *)data, offset, nevents)) { 425 // debugWarning("Could not encode port %s to Midi events",(*it)->getName().c_str()); 426 // no_problem=false; 427 // } 428 break; 473 429 default: // ignore 474 430 break; … … 484 440 // doesn't read from the port buffers. 485 441 bool no_problem = true; 486 for ( PortVectorIterator it = m_P eriodPorts.begin();487 it != m_P eriodPorts.end();442 for ( PortVectorIterator it = m_Ports.begin(); 443 it != m_Ports.end(); 488 444 ++it ) { 489 //FIXME: make this into a static_cast when not DEBUG? 490 Port *port=dynamic_cast<Port *>(*it); 445 Port *port=(*it); 491 446 492 447 switch(port->getPortType()) { … … 498 453 } 499 454 break; 500 // midi is a packet based port, don't process 501 // case MotuPortInfo::E_Midi: 502 // break; 503 455 case Port::E_Midi: 456 // if (encodeSilencePortToMotuMidiEvents(static_cast<MotuMidiPort *>(*it), (quadlet_t *)data, offset, nevents)) { 457 // debugWarning("Could not encode port %s to Midi events",(*it)->getName().c_str()); 458 // no_problem = false; 459 // } 460 break; 504 461 default: // ignore 505 462 break; … … 507 464 } 508 465 return no_problem; 509 }510 511 /**512 * @brief encode a packet for the packet-based ports513 *514 * @param data Packet data515 * @param nevents number of events in data (including events of other ports & port types)516 * @param dbc DataBlockCount value for this packet517 * @return true if all successfull518 */519 bool MotuTransmitStreamProcessor::encodePacketPorts(quadlet_t *data, unsigned int nevents,520 unsigned int dbc) {521 bool ok=true;522 char byte;523 524 // Use char here since the target address won't necessarily be525 // aligned; use of an unaligned quadlet_t may cause issues on526 // certain architectures. Besides, the target for MIDI data going527 // directly to the MOTU isn't structured in quadlets anyway; it is a528 // sequence of 3 unaligned bytes.529 unsigned char *target = NULL;530 531 for ( PortVectorIterator it = m_PacketPorts.begin();532 it != m_PacketPorts.end();533 ++it ) {534 535 Port *port=static_cast<Port *>(*it);536 assert(port); // this should not fail!!537 538 // Currently the only packet type of events for MOTU539 // is MIDI in mbla. However in future control data540 // might also be sent via "packet" events.541 // assert(pinfo->getFormat()==MotuPortInfo::E_Midi);542 543 // FIXME: MIDI output is completely untested at present.544 switch (port->getPortType()) {545 case Port::E_Midi: {546 MotuMidiPort *mp=static_cast<MotuMidiPort *>(*it);547 548 // Send a byte if we can. MOTU MIDI data is549 // sent using a 3-byte sequence starting at550 // the port's position. For now we'll551 // always send in the first event of a552 // packet, but this might need refinement553 // later.554 if (mp->canRead()) {555 mp->readEvent(&byte);556 target = (unsigned char *)data + mp->getPosition();557 *(target++) = 0x01;558 *(target++) = 0x00;559 *(target++) = byte;560 }561 break;562 }563 default:564 debugOutput(DEBUG_LEVEL_VERBOSE, "Unknown packet-type port type %d\n",port->getPortType());565 return ok;566 }567 }568 569 return ok;570 466 } 571 467 branches/api-cleanup/src/motu/motu_avdevice.cpp
r785 r809 554 554 // event data. 555 555 asprintf(&buff,"%s_cap_MIDI0",id.c_str()); 556 p = new Streaming::MotuMidiPort( buff,556 p = new Streaming::MotuMidiPort(*m_receiveProcessor, buff, 557 557 Streaming::Port::E_Capture, 4); 558 558 if (!p) { 559 559 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff); 560 } else {561 if (!m_receiveProcessor->addPort(p)) {562 debugWarning("Could not register port with stream processor\n");563 free(buff);564 return false;565 } else {566 debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n", buff);567 }568 560 } 569 561 free(buff); … … 613 605 // of the event data. 614 606 asprintf(&buff,"%s_pbk_MIDI0",id.c_str()); 615 p = new Streaming::MotuMidiPort( buff,607 p = new Streaming::MotuMidiPort(*m_transmitProcessor, buff, 616 608 Streaming::Port::E_Capture, 4); 617 609 if (!p) { 618 610 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff); 619 } else {620 if (!m_receiveProcessor->addPort(p)) {621 debugWarning("Could not register port with stream processor\n");622 free(buff);623 return false;624 } else {625 debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n", buff);626 }627 611 } 628 612 free(buff); … … 862 846 Streaming::Port *p=NULL; 863 847 864 p = new Streaming::MotuAudioPort( name, direction, position, size);848 p = new Streaming::MotuAudioPort(*s_processor, name, direction, position, size); 865 849 866 850 if (!p) { 867 851 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",name); 868 } else {869 if (!s_processor->addPort(p)) {870 debugWarning("Could not register port with stream processor\n");871 free(name);872 return false;873 } else {874 debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",name);875 }876 p->enable();877 852 } 878 853 free(name); branches/api-cleanup/tests/streaming/SConscript
r792 r809 30 30 env.PrependUnique( LIBS=["ffado"] ) 31 31 32 apps = "teststreaming teststreaming2"33 if env.GetOption('clean') or env['ALSA_SEQ_OUTPUT']:34 apps += " testmidistreaming1"35 36 for app in env.Split( apps ):37 env.Program( target=app, source = [ app+".c", "debugtools.c" ] )38 39 32 cppapps = "teststreaming3" 40 33 branches/api-cleanup/tests/streaming/teststreaming3.cpp
r807 r809 321 321 for (i=0; i < nb_in_channels; i++) { 322 322 audiobuffers_in[i] = (float *)calloc(arguments.period+1, sizeof(float)); 323 323 324 324 switch (ffado_streaming_get_capture_stream_type(dev,i)) { 325 325 case ffado_stream_type_audio: … … 331 331 // this is done with read/write routines because the nb of bytes can differ. 332 332 case ffado_stream_type_midi: 333 // note that using a float * buffer for midievents is a HACK 334 ffado_streaming_set_capture_stream_buffer(dev, i, (char *)(audiobuffers_in[i])); 335 ffado_streaming_set_capture_buffer_type(dev, i, ffado_buffer_type_midi); 336 ffado_streaming_capture_stream_onoff(dev, i, 1); 333 337 default: 334 338 break; 335 339 } 336 340 } 337 341 338 342 audiobuffers_out = (float **)calloc(nb_out_channels, sizeof(float)); 339 343 for (i=0; i < nb_out_channels; i++) { 340 344 audiobuffers_out[i] = (float *)calloc(arguments.period+1, sizeof(float)); 341 345 342 346 switch (ffado_streaming_get_playback_stream_type(dev,i)) { 343 347 case ffado_stream_type_audio: … … 349 353 // this is done with read/write routines because the nb of bytes can differ. 350 354 case ffado_stream_type_midi: 355 ffado_streaming_set_playback_buffer_type(dev, i, ffado_buffer_type_midi); 356 ffado_streaming_playback_stream_onoff(dev, i, 0); 351 357 default: 352 358 break; … … 413 419 } 414 420 } else { 421 uint32_t *midibuffer; 422 int idx; 415 423 for (i=0; i < min_ch_count; i++) { 416 424 switch (ffado_streaming_get_capture_stream_type(dev,i)) { … … 423 431 // this is done with read/write routines because the nb of bytes can differ. 424 432 case ffado_stream_type_midi: 433 midibuffer=(uint32_t *)audiobuffers_in[i]; 434 for(idx=0; idx < arguments.period; idx++) { 435 uint32_t midievent = *(midibuffer + idx); 436 if(midievent & 0xFF000000) { 437 debugOutput(DEBUG_LEVEL_NORMAL, " Received midi event %08X on idx %d of period %d\n", 438 midievent, idx, nb_periods); 439 } 440 } 425 441 default: 426 442 break;