Index: /branches/api-cleanup/src/libstreaming/motu/MotuPort.h =================================================================== --- /branches/api-cleanup/src/libstreaming/motu/MotuPort.h (revision 742) +++ /branches/api-cleanup/src/libstreaming/motu/MotuPort.h (revision 809) @@ -48,16 +48,14 @@ public: - MotuAudioPort(std::string name, - enum E_Direction direction, - int position, - int size) - : AudioPort(name, direction), + MotuAudioPort(PortManager &m, + std::string name, + enum E_Direction direction, + int position, + int size) + : AudioPort(m, name, direction), MotuPortInfo( position, size) // TODO: add more port information parameters here if nescessary {}; virtual ~MotuAudioPort() {}; - -protected: - }; @@ -73,16 +71,13 @@ public: - MotuMidiPort(std::string name, - enum E_Direction direction, - int position) - : MidiPort(name, direction), + MotuMidiPort(PortManager &m, + std::string name, + enum E_Direction direction, + int position) + : MidiPort(m, name, direction), MotuPortInfo(position, 0) // TODO: add more port information parameters here if nescessary {}; - virtual ~MotuMidiPort() {}; - -protected: - }; @@ -98,16 +93,13 @@ public: - MotuControlPort(std::string name, - enum E_Direction direction, - int position) - : ControlPort(name, direction), + MotuControlPort(PortManager &m, + std::string name, + enum E_Direction direction, + int position) + : ControlPort(m, name, direction), MotuPortInfo(position, 2) // TODO: add more port information parameters here if nescessary {}; - virtual ~MotuControlPort() {}; - -protected: - }; Index: /branches/api-cleanup/src/libstreaming/motu/MotuTransmitStreamProcessor.cpp =================================================================== --- /branches/api-cleanup/src/libstreaming/motu/MotuTransmitStreamProcessor.cpp (revision 798) +++ /branches/api-cleanup/src/libstreaming/motu/MotuTransmitStreamProcessor.cpp (revision 809) @@ -62,5 +62,4 @@ {} - unsigned int MotuTransmitStreamProcessor::getMaxPacketSize() { @@ -310,18 +309,4 @@ } - // Process all ports that should be handled on a per-packet base - // this is MIDI for AMDTP (due to the need of DBC, which is lost - // when putting the events in the ringbuffer) - // for motu this might also be control data, however as control - // data isn't time specific I would also include it in the period - // based processing - - // FIXME: m_tx_dbc probably needs to be initialised to a non-zero - // value somehow so MIDI sync is possible. For now we ignore - // this issue. - if (!encodePacketPorts((quadlet_t *)(data+8), n_events, m_tx_dbc)) { - debugWarning("Problem encoding Packet Ports\n"); - } - return eCRV_OK; } @@ -403,34 +388,4 @@ { debugOutput ( DEBUG_LEVEL_VERBOSE, "Preparing (%p)...\n", this ); - - -#if 0 - for ( PortVectorIterator it = m_Ports.begin(); - it != m_Ports.end(); - ++it ) - { - if ( ( *it )->getPortType() == Port::E_Midi ) - { - // we use a timing unit of 10ns - // this makes sure that for the max syt interval - // we don't have rounding, and keeps the numbers low - // we have 1 slot every 8 events - // we have syt_interval events per packet - // => syt_interval/8 slots per packet - // packet rate is 8000pkt/sec => interval=125us - // so the slot interval is (1/8000)/(syt_interval/8) - // or: 1/(1000 * syt_interval) sec - // which is 1e9/(1000*syt_interval) nsec - // or 100000/syt_interval 'units' - // the event interval is fixed to 320us = 32000 'units' - if ( ! ( *it )->useRateControl ( true, ( 100000/m_syt_interval ),32000, false ) ) - { - debugFatal ( "Could not set signal type to PeriodSignalling" ); - return false; - } - break; - } - } -#endif return true; } @@ -450,12 +405,11 @@ } - for ( PortVectorIterator it = m_PeriodPorts.begin(); - it != m_PeriodPorts.end(); + for ( PortVectorIterator it = m_Ports.begin(); + it != m_Ports.end(); ++it ) { // If this port is disabled, don't process it if((*it)->isDisabled()) {continue;}; - //FIXME: make this into a static_cast when not DEBUG? - Port *port=dynamic_cast(*it); + Port *port=(*it); switch(port->getPortType()) { @@ -463,12 +417,14 @@ case Port::E_Audio: if (encodePortToMotuEvents(static_cast(*it), (quadlet_t *)data, offset, nevents)) { - debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str()); + debugWarning("Could not encode port %s to Motu events",(*it)->getName().c_str()); no_problem=false; } break; - // midi is a packet based port, don't process - // case MotuPortInfo::E_Midi: - // break; - + case Port::E_Midi: +// if (encodePortToMotuMidiEvents(static_cast(*it), (quadlet_t *)data, offset, nevents)) { +// debugWarning("Could not encode port %s to Midi events",(*it)->getName().c_str()); +// no_problem=false; +// } + break; default: // ignore break; @@ -484,9 +440,8 @@ // doesn't read from the port buffers. bool no_problem = true; - for ( PortVectorIterator it = m_PeriodPorts.begin(); - it != m_PeriodPorts.end(); + for ( PortVectorIterator it = m_Ports.begin(); + it != m_Ports.end(); ++it ) { - //FIXME: make this into a static_cast when not DEBUG? - Port *port=dynamic_cast(*it); + Port *port=(*it); switch(port->getPortType()) { @@ -498,8 +453,10 @@ } break; - // midi is a packet based port, don't process - // case MotuPortInfo::E_Midi: - // break; - + case Port::E_Midi: +// if (encodeSilencePortToMotuMidiEvents(static_cast(*it), (quadlet_t *)data, offset, nevents)) { +// debugWarning("Could not encode port %s to Midi events",(*it)->getName().c_str()); +// no_problem = false; +// } + break; default: // ignore break; @@ -507,65 +464,4 @@ } return no_problem; -} - -/** - * @brief encode a packet for the packet-based ports - * - * @param data Packet data - * @param nevents number of events in data (including events of other ports & port types) - * @param dbc DataBlockCount value for this packet - * @return true if all successfull - */ -bool MotuTransmitStreamProcessor::encodePacketPorts(quadlet_t *data, unsigned int nevents, - unsigned int dbc) { - bool ok=true; - char byte; - - // Use char here since the target address won't necessarily be - // aligned; use of an unaligned quadlet_t may cause issues on - // certain architectures. Besides, the target for MIDI data going - // directly to the MOTU isn't structured in quadlets anyway; it is a - // sequence of 3 unaligned bytes. - unsigned char *target = NULL; - - for ( PortVectorIterator it = m_PacketPorts.begin(); - it != m_PacketPorts.end(); - ++it ) { - - Port *port=static_cast(*it); - assert(port); // this should not fail!! - - // Currently the only packet type of events for MOTU - // is MIDI in mbla. However in future control data - // might also be sent via "packet" events. - // assert(pinfo->getFormat()==MotuPortInfo::E_Midi); - - // FIXME: MIDI output is completely untested at present. - switch (port->getPortType()) { - case Port::E_Midi: { - MotuMidiPort *mp=static_cast(*it); - - // Send a byte if we can. MOTU MIDI data is - // sent using a 3-byte sequence starting at - // the port's position. For now we'll - // always send in the first event of a - // packet, but this might need refinement - // later. - if (mp->canRead()) { - mp->readEvent(&byte); - target = (unsigned char *)data + mp->getPosition(); - *(target++) = 0x01; - *(target++) = 0x00; - *(target++) = byte; - } - break; - } - default: - debugOutput(DEBUG_LEVEL_VERBOSE, "Unknown packet-type port type %d\n",port->getPortType()); - return ok; - } - } - - return ok; } Index: /branches/api-cleanup/src/libstreaming/motu/MotuReceiveStreamProcessor.cpp =================================================================== --- /branches/api-cleanup/src/libstreaming/motu/MotuReceiveStreamProcessor.cpp (revision 750) +++ /branches/api-cleanup/src/libstreaming/motu/MotuReceiveStreamProcessor.cpp (revision 809) @@ -187,12 +187,4 @@ if(m_data_buffer->writeFrames(n_events, (char *)(data+8), m_last_timestamp)) { - int dbc = get_bits(ntohl(quadlet[0]), 8, 8); - // process all ports that should be handled on a per-packet base - // this is MIDI for AMDTP (due to the need of DBC) - if(isRunning()) { - if (!decodePacketPorts((quadlet_t *)(data+8), n_events, dbc)) { - debugWarning("Problem decoding Packet Ports\n"); - } - } return eCRV_OK; } else { @@ -211,11 +203,10 @@ { bool no_problem=true; - for ( PortVectorIterator it = m_PeriodPorts.begin(); - it != m_PeriodPorts.end(); + for ( PortVectorIterator it = m_Ports.begin(); + it != m_Ports.end(); ++it ) { if((*it)->isDisabled()) {continue;}; - //FIXME: make this into a static_cast when not DEBUG? - Port *port=dynamic_cast(*it); + Port *port=(*it); switch(port->getPortType()) { @@ -227,7 +218,10 @@ } break; - // midi is a packet based port, don't process - // case MotuPortInfo::E_Midi: - // break; + case Port::E_Midi: +// if(decodeMotuMidiEventsToPort(static_cast(*it), (quadlet_t *)data, offset, nevents)) { +// debugWarning("Could not decode packet midi data to port %s",(*it)->getName().c_str()); +// no_problem=false; +// } + break; default: // ignore @@ -236,71 +230,4 @@ } return no_problem; -} - -/** - * @brief decode a packet for the packet-based ports - * - * @param data Packet data - * @param nevents number of events in data (including events of other ports & port types) - * @param dbc DataBlockCount value for this packet - * @return true if all successfull - */ -bool MotuReceiveStreamProcessor::decodePacketPorts(quadlet_t *data, unsigned int nevents, - unsigned int dbc) { - bool ok=true; - - // Use char here since the source address won't necessarily be - // aligned; use of an unaligned quadlet_t may cause issues on - // certain architectures. Besides, the source for MIDI data going - // directly to the MOTU isn't structured in quadlets anyway; it is a - // sequence of 3 unaligned bytes. - unsigned char *src = NULL; - - for ( PortVectorIterator it = m_PacketPorts.begin(); - it != m_PacketPorts.end(); - ++it ) { - - Port *port=dynamic_cast(*it); - assert(port); // this should not fail!! - - // Currently the only packet type of events for MOTU - // is MIDI in mbla. However in future control data - // might also be sent via "packet" events, so allow - // for this possible expansion. - - // FIXME: MIDI input is completely untested at present. - switch (port->getPortType()) { - case Port::E_Midi: { - MotuMidiPort *mp=static_cast(*it); - signed int sample; - unsigned int j = 0; - // Get MIDI bytes if present anywhere in the - // packet. MOTU MIDI data is sent using a - // 3-byte sequence starting at the port's - // position. It's thought that there can never - // be more than one MIDI byte per packet, but - // for completeness we'll check the entire packet - // anyway. - src = (unsigned char *)data + mp->getPosition(); - while (j < nevents) { - if (*src==0x01 && *(src+1)==0x00) { - sample = *(src+2); - if (!mp->writeEvent(&sample)) { - debugWarning("MIDI packet port events lost\n"); - ok = false; - } - } - j++; - src += m_event_size; - } - break; - } - default: - debugOutput(DEBUG_LEVEL_VERBOSE, "Unknown packet-type port format %d\n",port->getPortType()); - return ok; - } - } - - return ok; } Index: /branches/api-cleanup/src/libstreaming/amdtp/AmdtpPort.h =================================================================== --- /branches/api-cleanup/src/libstreaming/amdtp/AmdtpPort.h (revision 742) +++ /branches/api-cleanup/src/libstreaming/amdtp/AmdtpPort.h (revision 809) @@ -47,17 +47,15 @@ public: - AmdtpAudioPort(std::string name, - enum E_Direction direction, + AmdtpAudioPort(PortManager &m, + std::string name, + enum E_Direction direction, int position, int location, enum E_Formats format) - : AudioPort(name, direction), + : AudioPort(m, name, direction), AmdtpPortInfo(position, location, format) {}; virtual ~AmdtpAudioPort() {}; - -protected: - }; @@ -74,18 +72,15 @@ public: - AmdtpMidiPort(std::string name, - enum E_Direction direction, - int position, - int location, - enum E_Formats format) - : MidiPort(name, direction), + AmdtpMidiPort(PortManager &m, + std::string name, + enum E_Direction direction, + int position, + int location, + enum E_Formats format) + : MidiPort(m, name, direction), AmdtpPortInfo(position, location, format) {}; - virtual ~AmdtpMidiPort() {}; - -protected: - }; Index: /branches/api-cleanup/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.cpp =================================================================== --- /branches/api-cleanup/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.cpp (revision 798) +++ /branches/api-cleanup/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.cpp (revision 809) @@ -249,13 +249,6 @@ int cycle, unsigned int dropped, unsigned int max_length ) { - struct iec61883_packet *packet = ( struct iec61883_packet * ) data; if ( m_data_buffer->readFrames ( m_syt_interval, ( char * ) ( data + 8 ) ) ) { - // process all ports that should be handled on a per-packet base - // this is MIDI for AMDTP (due to the need of DBC) - if ( !encodePacketPorts ( ( quadlet_t * ) ( data+8 ), m_syt_interval, packet->dbc ) ) - { - debugWarning ( "Problem encoding Packet Ports\n" ); - } debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "XMIT DATA (cy %04d): TSP=%011llu (%04u)\n", cycle, m_last_timestamp, ( unsigned int ) TICKS_TO_CYCLES ( m_last_timestamp ) ); @@ -395,30 +388,4 @@ m_syt_interval ); - for ( PortVectorIterator it = m_Ports.begin(); - it != m_Ports.end(); - ++it ) - { - if ( ( *it )->getPortType() == Port::E_Midi ) - { - // we use a timing unit of 10ns - // this makes sure that for the max syt interval - // we don't have rounding, and keeps the numbers low - // we have 1 slot every 8 events - // we have syt_interval events per packet - // => syt_interval/8 slots per packet - // packet rate is 8000pkt/sec => interval=125us - // so the slot interval is (1/8000)/(syt_interval/8) - // or: 1/(1000 * syt_interval) sec - // which is 1e9/(1000*syt_interval) nsec - // or 100000/syt_interval 'units' - // the event interval is fixed to 320us = 32000 'units' - if ( ! ( *it )->useRateControl ( true, ( 100000/m_syt_interval ),32000, false ) ) - { - debugFatal ( "Could not set signal type to PeriodSignalling" ); - return false; - } - break; - } - } return true; } @@ -432,6 +399,6 @@ bool no_problem = true; - for ( PortVectorIterator it = m_PeriodPorts.begin(); - it != m_PeriodPorts.end(); + for ( PortVectorIterator it = m_Ports.begin(); + it != m_Ports.end(); ++it ) { @@ -453,4 +420,11 @@ case AmdtpPortInfo::E_SPDIF: // still unimplemented break; + case AmdtpPortInfo::E_Midi: + if( encodePortToMidiEvents(static_cast(*it), (quadlet_t *)data, offset, nevents) ) + { + debugWarning ( "Could not encode port %s to Midi events", (*it)->getName().c_str() ); + no_problem = false; + } + break; default: // ignore break; @@ -465,6 +439,6 @@ { bool no_problem = true; - for(PortVectorIterator it = m_PeriodPorts.begin(); - it != m_PeriodPorts.end(); + for(PortVectorIterator it = m_Ports.begin(); + it != m_Ports.end(); ++it ) { @@ -478,5 +452,5 @@ if ( encodeSilencePortToMBLAEvents(static_cast(*it), (quadlet_t *)data, offset, nevents) ) { - debugWarning("Could not encode port %s to MBLA events", (*it)->getName().c_str()); + debugWarning("Could not encode silence for port %s to MBLA events", (*it)->getName().c_str()); no_problem = false; } @@ -484,4 +458,11 @@ case AmdtpPortInfo::E_SPDIF: // still unimplemented break; + case AmdtpPortInfo::E_Midi: + if( encodeSilencePortToMidiEvents(static_cast(*it), (quadlet_t *)data, offset, nevents) ) + { + debugWarning ( "Could not encode silence for port %s to Midi events", (*it)->getName().c_str() ); + no_problem = false; + } + break; default: // ignore break; @@ -491,83 +472,6 @@ } -/** -* @brief decode a packet for the packet-based ports -* -* @param data Packet data -* @param nevents number of events in data (including events of other ports & port types) -* @param dbc DataBlockCount value for this packet -* @return true if all successfull -*/ -bool AmdtpTransmitStreamProcessor::encodePacketPorts ( quadlet_t *data, unsigned int nevents, unsigned int dbc ) -{ - bool ok=true; - quadlet_t byte; - - quadlet_t *target_event=NULL; - unsigned int j; - - for ( PortVectorIterator it = m_PacketPorts.begin(); - it != m_PacketPorts.end(); - ++it ) - { - -#ifdef DEBUG - AmdtpPortInfo *pinfo=dynamic_cast ( *it ); - assert ( pinfo ); // this should not fail!! - - // the only packet type of events for AMDTP is MIDI in mbla - assert ( pinfo->getFormat() ==AmdtpPortInfo::E_Midi ); -#endif - - AmdtpMidiPort *mp=static_cast ( *it ); - - // we encode this directly (no function call) due to the high frequency - /* idea: - spec says: current_midi_port=(dbc+j)%8; - => if we start at (dbc+stream->location-1)%8, - we'll start at the right event for the midi port. - => if we increment j with 8, we stay at the right event. - */ - // FIXME: as we know in advance how big a packet is (syt_interval) we can - // predict how much loops will be present here - // first prefill the buffer with NO_DATA's on all time muxed channels - - for ( j = ( dbc & 0x07 ) +mp->getLocation(); j < nevents; j += 8 ) - { - - quadlet_t tmpval; - - target_event= ( quadlet_t * ) ( data + ( ( j * m_dimension ) + mp->getPosition() ) ); - - if ( mp->canRead() ) // we can send a byte - { - mp->readEvent ( &byte ); - byte &= 0xFF; - tmpval=htonl ( - IEC61883_AM824_SET_LABEL ( ( byte ) <<16, - IEC61883_AM824_LABEL_MIDI_1X ) ); - - debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "MIDI port %s, pos=%d, loc=%d, dbc=%d, nevents=%d, dim=%d\n", - mp->getName().c_str(), mp->getPosition(), mp->getLocation(), dbc, nevents, m_dimension ); - debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "base=%p, target=%p, value=%08X\n", - data, target_event, tmpval ); - - } - else - { - // can't send a byte, either because there is no byte, - // or because this would exceed the maximum rate - tmpval=htonl ( - IEC61883_AM824_SET_LABEL ( 0,IEC61883_AM824_LABEL_MIDI_NO_DATA ) ); - } - - *target_event=tmpval; - } - - } - return ok; -} - #if USE_SSE +#error Broken typedef float v4sf __attribute__ ((vector_size (16))); typedef int v4si __attribute__ ((vector_size (16))); @@ -600,4 +504,6 @@ { default: + debugError("bad type: %d\n", p->getDataType()); + return -1; case Port::E_Int24: { @@ -687,4 +593,6 @@ { default: + debugError("bad type: %d\n", p->getDataType()); + return -1; case Port::E_Int24: { @@ -729,4 +637,58 @@ return 0; } + +// note: make sure that the midi events in the port buffer are only placed on (buffer+offset+x)%8 == 0 +// i.e. 8 frame aligned +int AmdtpTransmitStreamProcessor::encodePortToMidiEvents ( AmdtpMidiPort *p, quadlet_t *data, + unsigned int offset, unsigned int nevents ) +{ + unsigned int j=0; + unsigned int position = p->getPosition(); + unsigned int location = p->getLocation(); + char byte; + + quadlet_t *target_event; + quadlet_t tmpval; + + switch ( p->getDataType() ) + { + default: + debugError("bad type: %d\n", p->getDataType()); + return -1; + case Port::E_Midi: + { + quadlet_t *buffer = (quadlet_t *)(p->getBufferAddress()); + + assert(nevents + offset <= p->getBufferSize()); + + buffer+=offset; + + for ( j = location; j < nevents; j += 8 ) + { + target_event = (quadlet_t *) (data + ((j * m_dimension) + position)); + + if ( *buffer & 0xFF000000 ) // we can send a byte + { + byte = *buffer & 0xFF; + tmpval=htonl(IEC61883_AM824_SET_LABEL((byte)<<16, IEC61883_AM824_LABEL_MIDI_1X)); + +// debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "MIDI port %s, pos=%d, loc=%d, nevents=%d, dim=%d\n", +// p->getName().c_str(), position, location, nevents, m_dimension ); +// debugOutput ( DEBUG_LEVEL_ULTRA_VERBOSE, "base=%p, target=%p, value=%08X\n", +// data, target_event, tmpval ); + } else { + // can't send a byte, either because there is no byte, + // or because this would exceed the maximum rate + tmpval=htonl(IEC61883_AM824_SET_LABEL(0, IEC61883_AM824_LABEL_MIDI_NO_DATA)); + } + *target_event=tmpval; + buffer+=8; + } + } + break; + } + return 0; +} + #endif @@ -758,3 +720,31 @@ } +int AmdtpTransmitStreamProcessor::encodeSilencePortToMidiEvents ( AmdtpMidiPort *p, quadlet_t *data, + unsigned int offset, unsigned int nevents ) +{ + unsigned int j=0; + unsigned int position = p->getPosition(); + unsigned int location = p->getLocation(); + + quadlet_t *target_event; + + switch ( p->getDataType() ) + { + default: + debugError("bad type: %d\n", p->getDataType()); + return -1; + case Port::E_Midi: + { + assert(nevents + offset <= p->getBufferSize()); + for ( j = location; j < nevents; j += 8 ) + { + target_event = (quadlet_t *) (data + ((j * m_dimension) + position)); + *target_event=htonl(IEC61883_AM824_SET_LABEL(0, IEC61883_AM824_LABEL_MIDI_NO_DATA)); + } + } + break; + } + return 0; +} + } // end of namespace Streaming Index: /branches/api-cleanup/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.cpp =================================================================== --- /branches/api-cleanup/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.cpp (revision 790) +++ /branches/api-cleanup/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.cpp (revision 809) @@ -167,11 +167,4 @@ if(m_data_buffer->writeFrames(nevents, (char *)(data+8), m_last_timestamp)) { - // process all ports that should be handled on a per-packet base - // this is MIDI for AMDTP (due to the need of DBC) - if(isRunning()) { - if (!decodePacketPorts((quadlet_t *)(data+8), nevents, packet->dbc)) { - debugWarning("Problem decoding Packet Ports\n"); - } - } return eCRV_OK; } else { @@ -193,6 +186,6 @@ bool no_problem=true; - for ( PortVectorIterator it = m_PeriodPorts.begin(); - it != m_PeriodPorts.end(); + for ( PortVectorIterator it = m_Ports.begin(); + it != m_Ports.end(); ++it ) { @@ -213,7 +206,10 @@ case AmdtpPortInfo::E_SPDIF: // still unimplemented break; - /* for this processor, midi is a packet based port case AmdtpPortInfo::E_Midi: - break;*/ + if(decodeMidiEventsToPort(static_cast(*it), (quadlet_t *)data, offset, nevents)) { + debugWarning("Could not decode packet Midi to port %s",(*it)->getName().c_str()); + no_problem=false; + } + break; default: // ignore break; @@ -223,62 +219,6 @@ } -/** - * @brief decode a packet for the packet-based ports - * - * @param data Packet data - * @param nevents number of events in data (including events of other ports & port types) - * @param dbc DataBlockCount value for this packet - * @return true if all successfull - */ -bool AmdtpReceiveStreamProcessor::decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc) -{ - bool ok=true; - - quadlet_t *target_event=NULL; - unsigned int j; - - for ( PortVectorIterator it = m_PacketPorts.begin(); - it != m_PacketPorts.end(); - ++it ) - { - -#ifdef DEBUG - AmdtpPortInfo *pinfo=dynamic_cast(*it); - assert(pinfo); // this should not fail!! - - // the only packet type of events for AMDTP is MIDI in mbla - assert(pinfo->getFormat()==AmdtpPortInfo::E_Midi); -#endif - AmdtpMidiPort *mp=static_cast(*it); - - // we decode this directly (no function call) due to the high frequency - /* idea: - spec says: current_midi_port=(dbc+j)%8; - => if we start at (dbc+stream->location-1)%8, - we'll start at the right event for the midi port. - => if we increment j with 8, we stay at the right event. - */ - // FIXME: as we know in advance how big a packet is (syt_interval) we can - // predict how much loops will be present here - for(j = (dbc & 0x07)+mp->getLocation(); j < nevents; j += 8) { - target_event=(quadlet_t *)(data + ((j * m_dimension) + mp->getPosition())); - quadlet_t sample_int=ntohl(*target_event); - // FIXME: this assumes that 2X and 3X speed isn't used, - // because only the 1X slot is put into the ringbuffer - if(IEC61883_AM824_GET_LABEL(sample_int) != IEC61883_AM824_LABEL_MIDI_NO_DATA) { - sample_int=(sample_int >> 16) & 0x000000FF; - if(!mp->writeEvent(&sample_int)) { - debugWarning("Packet port events lost\n"); - ok=false; - } - } - } - - } - - return ok; -} - #if USE_SSE +#error broken typedef float v4sf __attribute__ ((vector_size (16))); typedef int v4si __attribute__ ((vector_size (16))); @@ -306,4 +246,6 @@ switch(p->getDataType()) { default: + debugError("bad type: %d\n", p->getDataType()); + return -1; case Port::E_Int24: { @@ -374,4 +316,12 @@ } +int +AmdtpReceiveStreamProcessor::decodeMidiEventsToPort( + AmdtpMidiPort *p, quadlet_t *data, + unsigned int offset, unsigned int nevents) +{ + #warning implement +} + #else @@ -388,4 +338,6 @@ switch(p->getDataType()) { default: + debugError("bad type: %d\n", p->getDataType()); + return -1; case Port::E_Int24: { @@ -429,4 +381,55 @@ return 0; } + +int +AmdtpReceiveStreamProcessor::decodeMidiEventsToPort( + AmdtpMidiPort *p, quadlet_t *data, + unsigned int offset, unsigned int nevents) +{ + unsigned int j=0; + quadlet_t *target_event; + quadlet_t sample_int; + unsigned int position = p->getPosition(); + unsigned int location = p->getLocation(); + + switch(p->getDataType()) { + default: + debugError("bad type: %d\n", p->getDataType()); + return -1; + case Port::E_MidiEvent: + { + quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); + + assert(nevents + offset <= p->getBufferSize()); + + buffer+=offset; + + // clear + memset(buffer, 0, nevents * 4); + + // assumes that dbc%8 == 0, which is always true if data points to the + // start of a packet in blocking mode + // midi events that belong to the same time mpx-ed block should all be + // timed at the SYT timestamp of the packet. This basically means that they + // all correspond to the first audio frame in the packet. + for(j = location; j < nevents; j += 8) { + target_event=(quadlet_t *)(data + ((j * m_dimension) + position)); + sample_int=ntohl(*target_event); + // FIXME: this assumes that 2X and 3X speed isn't used, + // because only the 1X slot is put into the ringbuffer + if(IEC61883_AM824_GET_LABEL(sample_int) != IEC61883_AM824_LABEL_MIDI_NO_DATA) { + sample_int=(sample_int >> 16) & 0x000000FF; + sample_int |= 0x01000000; // flag that there is a midi event present + } + *buffer = sample_int; + buffer += 8; // skip 8 frames + } + } + break; + } + + return 0; +} + #endif } // end of namespace Streaming Index: /branches/api-cleanup/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.h =================================================================== --- /branches/api-cleanup/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.h (revision 750) +++ /branches/api-cleanup/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.h (revision 809) @@ -115,11 +115,12 @@ unsigned int offset); - bool encodePacketPorts(quadlet_t *data, unsigned int nevents, - unsigned int dbc); - int encodePortToMBLAEvents(AmdtpAudioPort *, quadlet_t *data, - unsigned int offset, unsigned int nevents); + unsigned int offset, unsigned int nevents); + int encodePortToMidiEvents(AmdtpMidiPort *p, quadlet_t *data, + unsigned int offset, unsigned int nevents); int encodeSilencePortToMBLAEvents(AmdtpAudioPort *, quadlet_t *data, - unsigned int offset, unsigned int nevents); + unsigned int offset, unsigned int nevents); + int encodeSilencePortToMidiEvents(AmdtpMidiPort *p, quadlet_t *data, + unsigned int offset, unsigned int nevents); unsigned int getFDF(); Index: /branches/api-cleanup/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.h =================================================================== --- /branches/api-cleanup/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.h (revision 750) +++ /branches/api-cleanup/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.h (revision 809) @@ -101,6 +101,6 @@ private: - bool decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc); int decodeMBLAEventsToPort(AmdtpAudioPort *, quadlet_t *data, unsigned int offset, unsigned int nevents); + int decodeMidiEventsToPort(AmdtpMidiPort *p, quadlet_t *data, unsigned int offset, unsigned int nevents); unsigned int getSytInterval(); Index: /branches/api-cleanup/src/libstreaming/generic/PortManager.cpp =================================================================== --- /branches/api-cleanup/src/libstreaming/generic/PortManager.cpp (revision 750) +++ /branches/api-cleanup/src/libstreaming/generic/PortManager.cpp (revision 809) @@ -40,24 +40,12 @@ PortManager::~PortManager() { -// deleteAllPorts(); -} - -// bool PortManager::setPortBuffersize(unsigned int newsize) { -// debugOutput( DEBUG_LEVEL_VERBOSE, "setting port buffer size to %d\n",newsize); -// -// -// for ( PortVectorIterator it = m_Ports.begin(); -// it != m_Ports.end(); -// ++it ) -// { -// if(!(*it)->setBufferSize(newsize)) { -// debugFatal("Could not set buffer size for port %s\n",(*it)->getName().c_str()); -// return false; -// } -// } -// -// return true; //not found -// -// } + // delete all ports that are still registered to the manager + for ( PortVectorIterator it = m_Ports.begin(); + it != m_Ports.end(); + ++it ) + { + delete *it; + } +} bool PortManager::makeNameUnique(Port *port) @@ -96,5 +84,5 @@ * @return */ -bool PortManager::addPort(Port *port) +bool PortManager::registerPort(Port *port) { assert(port); @@ -113,5 +101,5 @@ } -bool PortManager::deletePort(Port *port) +bool PortManager::unregisterPort(Port *port) { assert(port); @@ -124,5 +112,4 @@ if(*it == port) { m_Ports.erase(it); -// delete *it; return true; } @@ -132,20 +119,4 @@ return false; //not found - -} - -void PortManager::deleteAllPorts() -{ - debugOutput( DEBUG_LEVEL_VERBOSE, "deleting all ports\n"); - - for ( PortVectorIterator it = m_Ports.begin(); - it != m_Ports.end(); - ++it ) - { - m_Ports.erase(it); -// delete *it; - } - - return; } @@ -213,5 +184,5 @@ { if(!(*it)->init()) { - debugFatal("Could not init port %s",(*it)->getName().c_str()); + debugFatal("Could not init port %s\n", (*it)->getName().c_str()); return false; } @@ -222,8 +193,4 @@ bool PortManager::preparePorts() { debugOutput( DEBUG_LEVEL_VERBOSE, "preparing ports\n"); - - // clear the cache lists - m_PeriodPorts.clear(); - m_PacketPorts.clear(); for ( PortVectorIterator it = m_Ports.begin(); @@ -236,17 +203,4 @@ } - // now prepare the cache lists - switch((*it)->getSignalType()) { - case Port::E_PacketSignalled: - m_PacketPorts.push_back(*it); - break; - case Port::E_PeriodSignalled: - m_PeriodPorts.push_back(*it); - break; - default: - debugWarning("%s has unsupported port type\n", - (*it)->getName().c_str()); - break; - } } return true; Index: /branches/api-cleanup/src/libstreaming/generic/StreamProcessor.h =================================================================== --- /branches/api-cleanup/src/libstreaming/generic/StreamProcessor.h (revision 807) +++ /branches/api-cleanup/src/libstreaming/generic/StreamProcessor.h (revision 809) @@ -292,5 +292,5 @@ {debugWarning("call not allowed\n"); return false;}; protected: // some generic helpers - int provideSilenceToPort(AudioPort *p, unsigned int offset, unsigned int nevents); + int provideSilenceToPort(Port *p, unsigned int offset, unsigned int nevents); bool provideSilenceBlock(unsigned int nevents, unsigned int offset); Index: /branches/api-cleanup/src/libstreaming/generic/Port.cpp =================================================================== --- /branches/api-cleanup/src/libstreaming/generic/Port.cpp (revision 750) +++ /branches/api-cleanup/src/libstreaming/generic/Port.cpp (revision 809) @@ -23,4 +23,5 @@ #include "Port.h" +#include "PortManager.h" #include @@ -31,26 +32,22 @@ IMPL_DEBUG_MODULE( Port, Port, DEBUG_LEVEL_NORMAL ); -Port::Port(std::string name, enum E_PortType porttype, enum E_Direction direction) - : m_Name(name), - m_SignalType(E_PeriodSignalled), - m_BufferType(E_PointerBuffer), - m_disabled(true), - m_buffersize(0), - m_eventsize(0), - m_DataType(E_Int24), - m_PortType(porttype), - m_Direction(direction), - m_buffer(0), - m_ringbuffer(0), - m_use_external_buffer(false), - m_do_ratecontrol(false), - m_event_interval(0), - m_slot_interval(0), - m_rate_counter(0), - m_rate_counter_minimum(0), - m_average_ratecontrol(false), - m_State(E_Created) +Port::Port(PortManager& m, std::string name, + enum E_PortType porttype, enum E_Direction direction, enum E_DataType d) + : m_Name( name ) + , m_disabled( true ) + , m_buffersize( 0 ) + , m_eventsize( 0 ) + , m_DataType( d ) + , m_PortType( porttype ) + , m_Direction( direction ) + , m_buffer( NULL ) + , m_manager( m ) + , m_State( E_Created ) { - + m_manager.registerPort(this); +} + +Port::~Port() { + m_manager.unregisterPort(this); } @@ -74,31 +71,6 @@ } - switch (m_BufferType) { - case E_PointerBuffer: - if (m_use_external_buffer) { - // don't do anything - } else if (!allocateInternalBuffer()) { - debugFatal("Could not allocate internal buffer!\n"); - return false; - } - break; - - case E_RingBuffer: - if (m_use_external_buffer) { - debugFatal("Cannot use an external ringbuffer! \n"); - return false; - } else if (!allocateInternalRingBuffer()) { - debugFatal("Could not allocate internal ringbuffer!\n"); - return false; - } - break; - default: - debugFatal("Unsupported buffer type! (%d)\n",(int)m_BufferType); - return false; - break; - } - - m_eventsize=getEventSize(); // this won't change, so cache it - + m_eventsize = getEventSize(); // this won't change, so cache it + m_State = E_Initialized; return true; @@ -106,9 +78,6 @@ bool Port::reset() { - if (m_BufferType==E_RingBuffer) { - ffado_ringbuffer_reset(m_ringbuffer); - } - return true; -}; + return true; +} bool Port::setName(std::string name) { @@ -138,6 +107,8 @@ return sizeof(float); case E_Int24: // 24 bit 2's complement, packed in a 32bit integer (LSB's) + return sizeof(int32_t); + case E_MidiEvent: return sizeof(uint32_t); - case E_MidiEvent: + case E_ControlEvent: return sizeof(uint32_t); default: @@ -164,5 +135,5 @@ break; case E_Control: - if(d == E_Default) type_is_ok=true; + if(d == E_ControlEvent) type_is_ok=true; break; default: @@ -179,86 +150,11 @@ } -bool Port::setSignalType(enum E_SignalType s) { - debugOutput( DEBUG_LEVEL_VERBOSE, "Setting signaltype to %d for port %s\n",(int)s,m_Name.c_str()); - if (m_State != E_Created) { - debugFatal("Port (%s) not in E_Created state: %d\n",m_Name.c_str(),m_State); - return false; - } - - // do some sanity checks - bool type_is_ok=false; - switch (m_PortType) { - case E_Audio: - if(s == E_PeriodSignalled) type_is_ok=true; - break; - case E_Midi: - if(s == E_PacketSignalled) type_is_ok=true; - break; - case E_Control: - if(s == E_PeriodSignalled) type_is_ok=true; - break; - default: - break; - } - if(!type_is_ok) { - debugFatal("Signalling type not supported by this type of port!\n"); - return false; - } - m_SignalType=s; - return true; -} - -bool Port::setBufferType(enum E_BufferType b) { - debugOutput( DEBUG_LEVEL_VERBOSE, "Setting buffer type to %d for port %s\n",(int)b,m_Name.c_str()); - if (m_State != E_Created) { - debugFatal("Port (%s) not in E_Created state: %d\n",m_Name.c_str(),m_State); - return false; - } - // do some sanity checks - bool type_is_ok=false; - switch (m_PortType) { - case E_Audio: - if(b == E_PointerBuffer) type_is_ok=true; - break; - case E_Midi: - if(b == E_RingBuffer) type_is_ok=true; - break; - case E_Control: - break; - default: - break; - } - if(!type_is_ok) { - debugFatal("Buffer type not supported by this type of port!\n"); - return false; - } - m_BufferType=b; - return true; -} - -bool Port::useExternalBuffer(bool b) { - // If called on an initialised stream but the request isn't for a change silently - // allow it (relied on by C API as used by jack backend driver) - if (m_State==E_Initialized && m_use_external_buffer==b) - return true; - - debugOutput( DEBUG_LEVEL_VERBOSE, "Setting external buffer use to %d for port %s\n",(int)b,m_Name.c_str()); - - if (m_State != E_Created) { - debugFatal("Port (%s) not in E_Created state: %d\n",m_Name.c_str(),m_State); - return false; - } - m_use_external_buffer=b; - return true; -} - // buffer handling api's for pointer buffers /** - * Get the buffer address (being the external or the internal one). + * Get the buffer address * * @param buff */ void *Port::getBufferAddress() { - assert(m_BufferType==E_PointerBuffer); return m_buffer; }; @@ -266,213 +162,9 @@ /** * Set the external buffer address. - * only call this when you have specified that you will use - * an external buffer before doing the init() * * @param buff */ -void Port::setExternalBufferAddress(void *buff) { - assert(m_BufferType==E_PointerBuffer); - assert(m_use_external_buffer); // don't call this with an internal buffer! +void Port::setBufferAddress(void *buff) { m_buffer=buff; -}; - -// buffer handling api's for ringbuffers -bool Port::writeEvent(void *event) { - -#ifdef DEBUG - if (m_State != E_Initialized) { - debugFatal("Port (%s) not in E_Initialized state: %d\n",m_Name.c_str(),m_State); - return false; - } - - if(m_BufferType!=E_RingBuffer) { - debugError("operation not allowed on non E_RingBuffer ports\n"); - show(); - return false; - } - assert(m_ringbuffer); -#endif - - debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Writing event %08X with size %d to port %s\n",*((quadlet_t *)event),m_eventsize, m_Name.c_str()); - - return (ffado_ringbuffer_write(m_ringbuffer, (char *)event, m_eventsize)==m_eventsize); -} - -bool Port::readEvent(void *event) { - -#ifdef DEBUG - if (m_State != E_Initialized) { - debugFatal("Port (%s) not in E_Initialized state: %d\n",m_Name.c_str(),m_State); - return false; - } - - if(m_BufferType!=E_RingBuffer) { - debugError("operation not allowed on non E_RingBuffer ports\n"); - show(); - return false; - } - assert(m_ringbuffer); -#endif - - - unsigned int read=ffado_ringbuffer_read(m_ringbuffer, (char *)event, m_eventsize); - - debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Reading event %X with size %d from port %s\n",*((quadlet_t *)event),m_eventsize,m_Name.c_str()); - - - return (read==m_eventsize); -} - -int Port::writeEvents(void *event, unsigned int nevents) { - -#ifdef DEBUG - if (m_State != E_Initialized) { - debugFatal("Port (%s) not in E_Initialized state: %d\n",m_Name.c_str(),m_State); - return false; - } - - if(m_BufferType!=E_RingBuffer) { - debugError("operation not allowed on non E_RingBuffer ports\n"); - show(); - return false; - } - assert(m_ringbuffer); -#endif - - - unsigned int bytes2write=m_eventsize*nevents; - - unsigned int written=ffado_ringbuffer_write(m_ringbuffer, (char *)event,bytes2write)/m_eventsize; - -#ifdef DEBUG - if(written) { - unsigned int i=0; - quadlet_t * tmp=(quadlet_t *)event; - debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Written %d events (",written); - for (i=0;i= m_eventsize); - - if(byte_present_in_buffer) { - - if(!m_do_ratecontrol) { - return true; - } - - if(m_rate_counter <= 0) { - // update the counter - if(m_average_ratecontrol) { - m_rate_counter += m_event_interval; - assert(m_rate_counterevent_interval) { - debugWarning("Rate control not needed!\n",m_Name.c_str()); - m_do_ratecontrol=false; - return false; - } - if(slot_interval==0) { - debugFatal("Cannot have slot interval == 0!\n"); - m_do_ratecontrol=false; - return false; - } - if(event_interval==0) { - debugFatal("Cannot have event interval == 0!\n"); - m_do_ratecontrol=false; - return false; - } - m_do_ratecontrol=use; - m_event_interval=event_interval; - m_slot_interval=slot_interval; - m_rate_counter=0; - - // NOTE: pretty arbitrary, but in average mode this limits the peak stream rate - m_rate_counter_minimum=-(2*event_interval); - - m_average_ratecontrol=average; - - } else { - debugOutput(DEBUG_LEVEL_VERBOSE, "Disabling rate control for port %s...\n",m_Name.c_str()); - m_do_ratecontrol=use; - } - return true; } @@ -482,5 +174,5 @@ debugOutput(DEBUG_LEVEL_VERBOSE, "Enabling port %s...\n",m_Name.c_str()); m_disabled=false; -}; +} /// Disable the port. (this can be called anytime) @@ -489,77 +181,8 @@ debugOutput(DEBUG_LEVEL_VERBOSE, "Disabling port %s...\n",m_Name.c_str()); m_disabled=false; -}; - - -/* Private functions */ - -bool Port::allocateInternalBuffer() { - int event_size=getEventSize(); - - debugOutput(DEBUG_LEVEL_VERBOSE, - "Allocating internal buffer of %d events with size %d (%s)\n", - m_buffersize, event_size, m_Name.c_str()); - - if(m_buffer) { - debugWarning("already has an internal buffer attached, re-allocating\n"); - freeInternalBuffer(); - } - - m_buffer=calloc(m_buffersize,event_size); - if (!m_buffer) { - debugFatal("could not allocate internal buffer\n"); - m_buffersize=0; - return false; - } - - return true; -} - -void Port::freeInternalBuffer() { - debugOutput(DEBUG_LEVEL_VERBOSE, - "Freeing internal buffer (%s)\n",m_Name.c_str()); - - if(m_buffer) { - free(m_buffer); - m_buffer=0; - } -} - -bool Port::allocateInternalRingBuffer() { - int event_size=getEventSize(); - - debugOutput(DEBUG_LEVEL_VERBOSE, - "Allocating internal buffer of %d events with size %d (%s)\n", - m_buffersize, event_size, m_Name.c_str()); - - if(m_ringbuffer) { - debugWarning("already has an internal ringbuffer attached, re-allocating\n"); - freeInternalRingBuffer(); - } - - m_ringbuffer=ffado_ringbuffer_create(m_buffersize * event_size); - if (!m_ringbuffer) { - debugFatal("could not allocate internal ringbuffer\n"); - m_buffersize=0; - return false; - } - - return true; -} - -void Port::freeInternalRingBuffer() { - debugOutput(DEBUG_LEVEL_VERBOSE, - "Freeing internal ringbuffer (%s)\n",m_Name.c_str()); - - if(m_ringbuffer) { - ffado_ringbuffer_free(m_ringbuffer); - m_ringbuffer=0; - } } void Port::show() { debugOutput(DEBUG_LEVEL_VERBOSE,"Name : %s\n", m_Name.c_str()); - debugOutput(DEBUG_LEVEL_VERBOSE,"Signal Type : %d\n", m_SignalType); - debugOutput(DEBUG_LEVEL_VERBOSE,"Buffer Type : %d\n", m_BufferType); debugOutput(DEBUG_LEVEL_VERBOSE,"Enabled? : %d\n", m_disabled); debugOutput(DEBUG_LEVEL_VERBOSE,"State? : %d\n", m_State); @@ -569,5 +192,4 @@ debugOutput(DEBUG_LEVEL_VERBOSE,"Port Type : %d\n", m_PortType); debugOutput(DEBUG_LEVEL_VERBOSE,"Direction : %d\n", m_Direction); - debugOutput(DEBUG_LEVEL_VERBOSE,"Rate Control? : %d\n", m_do_ratecontrol); } Index: /branches/api-cleanup/src/libstreaming/generic/PortManager.h =================================================================== --- /branches/api-cleanup/src/libstreaming/generic/PortManager.h (revision 742) +++ /branches/api-cleanup/src/libstreaming/generic/PortManager.h (revision 809) @@ -33,5 +33,4 @@ namespace Streaming { -class Port; typedef std::vector PortVector; typedef std::vector::iterator PortVectorIterator; @@ -50,12 +49,9 @@ virtual bool makeNameUnique(Port *port); - virtual bool addPort(Port *port); - virtual bool deletePort(Port *port); - virtual void deleteAllPorts(); + virtual bool registerPort(Port *port); + virtual bool unregisterPort(Port *port); int getPortCount(enum Port::E_PortType); int getPortCount(); - -// virtual bool setPortBuffersize(unsigned int newsize); Port *getPortAtIdx(unsigned int index); @@ -69,10 +65,6 @@ protected: PortVector m_Ports; - PortVector m_PacketPorts; - PortVector m_PeriodPorts; -// PortVector m_SamplePorts; DECLARE_DEBUG_MODULE; - }; Index: /branches/api-cleanup/src/libstreaming/generic/Port.h =================================================================== --- /branches/api-cleanup/src/libstreaming/generic/Port.h (revision 742) +++ /branches/api-cleanup/src/libstreaming/generic/Port.h (revision 809) @@ -33,4 +33,5 @@ namespace Streaming { +class PortManager; /*! @@ -53,36 +54,8 @@ OK. - \todo rework the implementation into something more beautifull */ class Port { public: - friend class PortManager; - - /* - * IMPORTANT: if you add something to any of these enum's, be sure to - * check the code where they are used. - */ - - /*! - \brief Specifies the buffer type for ports - - A PointerBuffer uses the getBufferAddress() and setBufferAddres() interface - A Ringbuffer uses the read/write interface - */ - enum E_BufferType { - E_PointerBuffer, - E_RingBuffer - }; - - /*! - \brief Specifies the signalling type for ports - */ - enum E_SignalType { - E_PacketSignalled, ///< the port is to be processed for every packet - E_PeriodSignalled, ///< the port is to be processed after a period of frames -// E_SampleSignalled ///< the port is to be processed after each frame (sample) - }; - /*! \brief The datatype of the port buffer @@ -92,5 +65,5 @@ E_Int24, E_MidiEvent, - E_Default, + E_ControlEvent, }; @@ -112,8 +85,7 @@ }; - Port(std::string name, enum E_PortType porttype, enum E_Direction direction); - - virtual ~Port() - {}; + Port(PortManager&, std::string name, enum E_PortType, enum E_Direction, enum E_DataType); + + virtual ~Port(); @@ -151,22 +123,4 @@ enum E_DataType getDataType() {return m_DataType;}; - /** - * \brief sets the event type for the port buffer - * - * \note use before calling init() - */ - virtual bool setSignalType(enum E_SignalType ); - - enum E_SignalType getSignalType() {return m_SignalType;}; ///< returns the signalling type of the port - - /** - * \brief sets the buffer type for the port - * - * \note use before calling init() - */ - virtual bool setBufferType(enum E_BufferType ); - - enum E_BufferType getBufferType() {return m_BufferType;}; ///< returns the buffer type of the port - enum E_PortType getPortType() {return m_PortType;}; ///< returns the port type (is fixed) enum E_Direction getDirection() {return m_Direction;}; ///< returns the direction (is fixed) @@ -193,91 +147,14 @@ virtual bool setBufferSize(unsigned int); - /** - * \brief use an external buffer (or not) - * - * \note use before calling init() - */ - virtual bool useExternalBuffer(bool b); - - void setExternalBufferAddress(void *buff); - - - /** - * \brief enable/disable ratecontrol - * - * Rate control is nescessary for some types of ports (most notably - * midi). The StreamProcessor that handles the port should call canRead() - * everytime a 'slot' that could be filled with an event passes. The canRead - * function will return true if - * (1) there is an event ready in the buffer - * (2) we are allowed to send an event in this slot - * - * Setting the rate works is done with the slot_interval and the event_interval - * parameters. On every call to canRead(), a counter is decremented with - * slot_interval. If the counter drops below 0, canRead() returns true and resets - * the counter to event_interval. - * - * e.g. for AMDTP midi, we are only allowed to send a midi byte every 320us - * if the SYT interval is 8, there is exactly one midi slot every packet. - * therefore the slot_interval is 1/8000s (=125us), and the event_interval - * is 320us. - * - * Note that the interval parameters are unitless, so you can adapt them - * to your needs. In the AMDTP case for example, when the SYT interval is 32 - * (when the samplerate is 192kHz for example) there are 4 midi slots in - * each packet, making the slot time interval 125us/4 = 31.25us. - * The event time interval stays the same (320us). We can however set the - * slot_interval to 3125 and the event_interval to 32000, as we can choose - * the unit of the counter time step (chosen to be 10ns in this case). - * - * The average argument deserves some attention too. If average is true, we use - * average rate control. This means that on average there will be a delay of - * event_interval between two events, but that sometimes there can be a smaller - * delay. This mode fixes the average rate of the stream. - * If average is false, there will always be a minimal delay of event_interval - * between two events. This means that the maximum rate of the stream is fixed, - * and that the average rate will be lower than (or at max equal to) the rate in - * average mode. - * - * - * \note only works for the E_RingBuffer ports - * \note use before calling init() - * - * @param use set this to true to use rate control - * @param slot_interval the interval between slots - * @param event_interval the interval between events - * @param average use average rate control - * @return true if rate control was enabled/disabled successfully - */ - virtual bool useRateControl(bool use, unsigned int slot_interval, - unsigned int event_interval, bool average); - - bool usingRateControl() { return m_do_ratecontrol;}; ///< are we using rate control? - - /** - * Can we send an event in this slot. subject to rate control and - * byte availability. - * @return true if we can send an event on this slot - */ - bool canRead(); - - // FIXME: this is not really OO, but for performance??? + void setBufferAddress(void *buff); void *getBufferAddress(); - // TODO: extend this with a blocking interface - bool writeEvent(void *event); ///< write one event - bool readEvent(void *event); ///< read one event - int writeEvents(void *event, unsigned int nevents); ///< write multiple events - int readEvents(void *event, unsigned int nevents); ///< read multiple events + PortManager& getManager() { return m_manager; }; virtual void setVerboseLevel(int l); virtual void show(); - + protected: std::string m_Name; ///< Port name, [at construction] - - enum E_SignalType m_SignalType; ///< Signalling type, [at construction] - enum E_BufferType m_BufferType; ///< Buffer type, [at construction] - bool m_disabled; ///< is the port disabled?, [anytime] @@ -290,33 +167,20 @@ void *m_buffer; - ffado_ringbuffer_t *m_ringbuffer; - bool m_use_external_buffer; - - bool m_do_ratecontrol; - int m_event_interval; - int m_slot_interval; - int m_rate_counter; - int m_rate_counter_minimum; - bool m_average_ratecontrol; - - bool allocateInternalBuffer(); - void freeInternalBuffer(); - - bool allocateInternalRingBuffer(); - void freeInternalRingBuffer(); + + PortManager& m_manager; DECLARE_DEBUG_MODULE; - - // the state machine - protected: - enum EStates { - E_Created, - E_Initialized, - E_Prepared, - E_Running, - E_Error - }; - - enum EStates m_State; + +// the state machine +protected: + enum EStates { + E_Created, + E_Initialized, + E_Prepared, + E_Running, + E_Error + }; + + enum EStates m_State; }; @@ -330,13 +194,9 @@ public: - AudioPort(std::string name, enum E_Direction direction) - : Port(name, E_Audio, direction) + AudioPort(PortManager& m, std::string name, enum E_Direction direction) + : Port(m, name, E_Audio, direction, E_Int24) {}; virtual ~AudioPort() {}; - -protected: - - }; @@ -350,13 +210,8 @@ public: - MidiPort(std::string name, enum E_Direction direction) - : Port(name, E_Midi, direction) + MidiPort(PortManager& m, std::string name, enum E_Direction direction) + : Port(m, name, E_Midi, direction, E_MidiEvent) {}; virtual ~MidiPort() {}; - - -protected: - - }; @@ -370,13 +225,8 @@ public: - ControlPort(std::string name, enum E_Direction direction) - : Port(name, E_Control, direction) + ControlPort(PortManager& m, std::string name, enum E_Direction direction) + : Port(m, name, E_Control, direction, E_ControlEvent) {}; virtual ~ControlPort() {}; - - -protected: - - }; Index: /branches/api-cleanup/src/libstreaming/generic/StreamProcessor.cpp =================================================================== --- /branches/api-cleanup/src/libstreaming/generic/StreamProcessor.cpp (revision 807) +++ /branches/api-cleanup/src/libstreaming/generic/StreamProcessor.cpp (revision 809) @@ -960,26 +960,12 @@ { bool no_problem=true; - for ( PortVectorIterator it = m_PeriodPorts.begin(); - it != m_PeriodPorts.end(); + for ( PortVectorIterator it = m_Ports.begin(); + it != m_Ports.end(); ++it ) { if((*it)->isDisabled()) {continue;}; - //FIXME: make this into a static_cast when not DEBUG? - Port *port=dynamic_cast(*it); - - switch(port->getPortType()) { - - case Port::E_Audio: - if(provideSilenceToPort(static_cast(*it), offset, nevents)) { - debugWarning("Could not put silence into to port %s",(*it)->getName().c_str()); - no_problem=false; - } - break; - // midi is a packet based port, don't process - // case MotuPortInfo::E_Midi: - // break; - - default: // ignore - break; + if(provideSilenceToPort((*it), offset, nevents)) { + debugWarning("Could not put silence into to port %s",(*it)->getName().c_str()); + no_problem=false; } } @@ -988,11 +974,14 @@ int -StreamProcessor::provideSilenceToPort( - AudioPort *p, unsigned int offset, unsigned int nevents) +StreamProcessor::provideSilenceToPort(Port *p, unsigned int offset, unsigned int nevents) { unsigned int j=0; switch(p->getDataType()) { default: + debugError("Invalid port type: %d\n", p->getDataType()); + return -1; case Port::E_Int24: + case Port::E_MidiEvent: + case Port::E_ControlEvent: { quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress()); @@ -1000,5 +989,5 @@ buffer+=offset; - for(j = 0; j < nevents; j += 1) { // decode max nsamples + for(j = 0; j < nevents; j += 1) { *(buffer)=0; buffer++; @@ -1012,5 +1001,5 @@ buffer+=offset; - for(j = 0; j < nevents; j += 1) { // decode max nsamples + for(j = 0; j < nevents; j += 1) { *buffer = 0.0; buffer++; @@ -1320,47 +1309,4 @@ return false; } - switch ((*it)->getPortType()) { - case Port::E_Audio: - if(!(*it)->setSignalType(Port::E_PeriodSignalled)) { - debugFatal("Could not set signal type to PeriodSignalling"); - return false; - } - // buffertype and datatype are dependant on the API - debugWarning("---------------- ! Doing hardcoded dummy setup ! --------------\n"); - // buffertype and datatype are dependant on the API - if(!(*it)->setBufferType(Port::E_PointerBuffer)) { - debugFatal("Could not set buffer type"); - return false; - } - if(!(*it)->useExternalBuffer(true)) { - debugFatal("Could not set external buffer usage"); - return false; - } - if(!(*it)->setDataType(Port::E_Float)) { - debugFatal("Could not set data type"); - return false; - } - break; - case Port::E_Midi: - if(!(*it)->setSignalType(Port::E_PacketSignalled)) { - debugFatal("Could not set signal type to PacketSignalling"); - return false; - } - // buffertype and datatype are dependant on the API - debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n"); - // buffertype and datatype are dependant on the API - if(!(*it)->setBufferType(Port::E_RingBuffer)) { - debugFatal("Could not set buffer type"); - return false; - } - if(!(*it)->setDataType(Port::E_MidiEvent)) { - debugFatal("Could not set data type"); - return false; - } - break; - default: - debugWarning("Unsupported port type specified\n"); - break; - } } // the API specific settings of the ports should already be set, Index: /branches/api-cleanup/src/motu/motu_avdevice.cpp =================================================================== --- /branches/api-cleanup/src/motu/motu_avdevice.cpp (revision 785) +++ /branches/api-cleanup/src/motu/motu_avdevice.cpp (revision 809) @@ -554,16 +554,8 @@ // event data. asprintf(&buff,"%s_cap_MIDI0",id.c_str()); - p = new Streaming::MotuMidiPort(buff, + p = new Streaming::MotuMidiPort(*m_receiveProcessor, buff, Streaming::Port::E_Capture, 4); if (!p) { debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff); - } else { - if (!m_receiveProcessor->addPort(p)) { - debugWarning("Could not register port with stream processor\n"); - free(buff); - return false; - } else { - debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n", buff); - } } free(buff); @@ -613,16 +605,8 @@ // of the event data. asprintf(&buff,"%s_pbk_MIDI0",id.c_str()); - p = new Streaming::MotuMidiPort(buff, + p = new Streaming::MotuMidiPort(*m_transmitProcessor, buff, Streaming::Port::E_Capture, 4); if (!p) { debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff); - } else { - if (!m_receiveProcessor->addPort(p)) { - debugWarning("Could not register port with stream processor\n"); - free(buff); - return false; - } else { - debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n", buff); - } } free(buff); @@ -862,17 +846,8 @@ Streaming::Port *p=NULL; - p = new Streaming::MotuAudioPort(name, direction, position, size); + p = new Streaming::MotuAudioPort(*s_processor, name, direction, position, size); if (!p) { debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",name); - } else { - if (!s_processor->addPort(p)) { - debugWarning("Could not register port with stream processor\n"); - free(name); - return false; - } else { - debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",name); - } - p->enable(); } free(name); Index: /branches/api-cleanup/src/ffado.cpp =================================================================== --- /branches/api-cleanup/src/ffado.cpp (revision 807) +++ /branches/api-cleanup/src/ffado.cpp (revision 809) @@ -263,23 +263,4 @@ } - -int ffado_streaming_write(ffado_device_t *dev, int i, ffado_sample_t *buffer, int nsamples) { - Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Playback); - // use an assert here performancewise, - // it should already have failed before, if not correct - assert(p); - - return p->writeEvents((void *)buffer, nsamples); -} - -int ffado_streaming_read(ffado_device_t *dev, int i, ffado_sample_t *buffer, int nsamples) { - Streaming::Port *p=dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Capture); - // use an assert here performancewise, - // it should already have failed before, if not correct - assert(p); - - return p->readEvents((void *)buffer, nsamples); -} - int ffado_streaming_get_nb_capture_streams(ffado_device_t *dev) { return dev->m_deviceManager->getStreamProcessorManager().getPortCount(Streaming::Port::E_Capture); @@ -370,16 +351,8 @@ return -1; } - if (!p->setBufferType(Streaming::Port::E_PointerBuffer)) { - debugWarning("%s: Could not set buffer type to Pointerbuffer\n",p->getName().c_str()); - return -1; - } break; case ffado_buffer_type_float: if (!p->setDataType(Streaming::Port::E_Float)) { debugWarning("%s: Could not set data type to Float\n",p->getName().c_str()); - return -1; - } - if (!p->setBufferType(Streaming::Port::E_PointerBuffer)) { - debugWarning("%s: Could not set buffer type to Pointerbuffer\n",p->getName().c_str()); return -1; } @@ -390,11 +363,7 @@ return -1; } - if (!p->setBufferType(Streaming::Port::E_RingBuffer)) { - debugWarning("%s: Could not set buffer type to Ringbuffer\n",p->getName().c_str()); - return -1; - } break; default: - debugWarning("%s: Unsupported buffer type\n",p->getName().c_str()); + debugWarning("%s: Unsupported buffer type (%d)\n", p->getName().c_str(), t); return -1; } @@ -435,17 +404,11 @@ } -// TODO: the way port buffers are set in the C api doesn't satisfy me int ffado_streaming_set_capture_stream_buffer(ffado_device_t *dev, int i, char *buff) { Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Capture); - // use an assert here performancewise, // it should already have failed before, if not correct assert(p); - - p->useExternalBuffer(true); - p->setExternalBufferAddress((void *)buff); - - return 0; - + p->setBufferAddress((void *)buff); + return 0; } @@ -455,8 +418,5 @@ // it should already have failed before, if not correct assert(p); - - p->useExternalBuffer(true); - p->setExternalBufferAddress((void *)buff); - - return 0; -} + p->setBufferAddress((void *)buff); + return 0; +} Index: /branches/api-cleanup/src/dice/dice_avdevice.cpp =================================================================== --- /branches/api-cleanup/src/dice/dice_avdevice.cpp (revision 785) +++ /branches/api-cleanup/src/dice/dice_avdevice.cpp (revision 809) @@ -839,4 +839,5 @@ case ePT_Analog: p=new Streaming::AmdtpAudioPort( + *processor, portname.str(), direction, @@ -849,4 +850,5 @@ case ePT_MIDI: p=new Streaming::AmdtpMidiPort( + *processor, portname.str(), direction, @@ -864,10 +866,4 @@ if (!p) { debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",channelInfo->name.c_str()); - } else { - - if (!processor->addPort(p)) { - debugWarning("Could not register port with stream processor\n"); - return false; - } } Index: /branches/api-cleanup/src/genericavc/avc_avdevice.cpp =================================================================== --- /branches/api-cleanup/src/genericavc/avc_avdevice.cpp (revision 784) +++ /branches/api-cleanup/src/genericavc/avc_avdevice.cpp (revision 809) @@ -443,5 +443,5 @@ } - if (!addPlugToProcessor(*outputPlug,p, + if (!addPlugToProcessor(*outputPlug, p, Streaming::Port::E_Capture)) { debugFatal("Could not add plug to processor!\n"); @@ -472,5 +472,5 @@ if (snoopMode) { - if (!addPlugToProcessor(*inputPlug,p, + if (!addPlugToProcessor(*inputPlug, p, Streaming::Port::E_Capture)) { debugFatal("Could not add plug to processor!\n"); @@ -478,5 +478,5 @@ } } else { - if (!addPlugToProcessor(*inputPlug,p, + if (!addPlugToProcessor(*inputPlug, p, Streaming::Port::E_Playback)) { debugFatal("Could not add plug to processor!\n"); @@ -532,4 +532,5 @@ channelInfo->m_name.c_str(), channelInfo->m_streamPosition, channelInfo->m_location); p=new Streaming::AmdtpAudioPort( + *processor, portname.str(), direction, @@ -544,4 +545,5 @@ channelInfo->m_name.c_str(), channelInfo->m_streamPosition, processor->getPortCount(Streaming::Port::E_Midi)); p=new Streaming::AmdtpMidiPort( + *processor, portname.str(), direction, @@ -565,4 +567,5 @@ channelInfo->m_name.c_str(), channelInfo->m_streamPosition, channelInfo->m_location); p=new Streaming::AmdtpAudioPort( + *processor, portname.str(), direction, @@ -581,10 +584,4 @@ if (!p) { debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",channelInfo->m_name.c_str()); - } else { - - if (!processor->addPort(p)) { - debugWarning("Could not register port with stream processor\n"); - return false; - } } } Index: /branches/api-cleanup/src/bounce/bounce_avdevice.cpp =================================================================== --- /branches/api-cleanup/src/bounce/bounce_avdevice.cpp (revision 742) +++ /branches/api-cleanup/src/bounce/bounce_avdevice.cpp (revision 809) @@ -212,4 +212,5 @@ Streaming::Port *p=NULL; p=new Streaming::AmdtpAudioPort( + *processor, buff, direction, @@ -224,13 +225,4 @@ if (!p) { debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff); - } else { - - if (!processor->addPort(p)) { - debugWarning("Could not register port with stream processor\n"); - free(buff); - return false; - } else { - debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff); - } } free(buff); @@ -243,4 +235,5 @@ Streaming::Port *p=NULL; p=new Streaming::AmdtpMidiPort( + *processor, buff, direction, @@ -255,13 +248,4 @@ if (!p) { debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff); - } else { - - if (!processor->addPort(p)) { - debugWarning("Could not register port with stream processor\n"); - free(buff); - return false; - } else { - debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff); - } } free(buff); Index: /branches/api-cleanup/tests/streaming/SConscript =================================================================== --- /branches/api-cleanup/tests/streaming/SConscript (revision 792) +++ /branches/api-cleanup/tests/streaming/SConscript (revision 809) @@ -30,11 +30,4 @@ env.PrependUnique( LIBS=["ffado"] ) -apps = "teststreaming teststreaming2" -if env.GetOption('clean') or env['ALSA_SEQ_OUTPUT']: - apps += " testmidistreaming1" - -for app in env.Split( apps ): - env.Program( target=app, source = [ app+".c", "debugtools.c" ] ) - cppapps = "teststreaming3" Index: /branches/api-cleanup/tests/streaming/teststreaming3.cpp =================================================================== --- /branches/api-cleanup/tests/streaming/teststreaming3.cpp (revision 807) +++ /branches/api-cleanup/tests/streaming/teststreaming3.cpp (revision 809) @@ -321,5 +321,5 @@ for (i=0; i < nb_in_channels; i++) { audiobuffers_in[i] = (float *)calloc(arguments.period+1, sizeof(float)); - + switch (ffado_streaming_get_capture_stream_type(dev,i)) { case ffado_stream_type_audio: @@ -331,13 +331,17 @@ // this is done with read/write routines because the nb of bytes can differ. case ffado_stream_type_midi: + // note that using a float * buffer for midievents is a HACK + ffado_streaming_set_capture_stream_buffer(dev, i, (char *)(audiobuffers_in[i])); + ffado_streaming_set_capture_buffer_type(dev, i, ffado_buffer_type_midi); + ffado_streaming_capture_stream_onoff(dev, i, 1); default: break; } } - + audiobuffers_out = (float **)calloc(nb_out_channels, sizeof(float)); for (i=0; i < nb_out_channels; i++) { audiobuffers_out[i] = (float *)calloc(arguments.period+1, sizeof(float)); - + switch (ffado_streaming_get_playback_stream_type(dev,i)) { case ffado_stream_type_audio: @@ -349,4 +353,6 @@ // this is done with read/write routines because the nb of bytes can differ. case ffado_stream_type_midi: + ffado_streaming_set_playback_buffer_type(dev, i, ffado_buffer_type_midi); + ffado_streaming_playback_stream_onoff(dev, i, 0); default: break; @@ -413,4 +419,6 @@ } } else { + uint32_t *midibuffer; + int idx; for (i=0; i < min_ch_count; i++) { switch (ffado_streaming_get_capture_stream_type(dev,i)) { @@ -423,4 +431,12 @@ // this is done with read/write routines because the nb of bytes can differ. case ffado_stream_type_midi: + midibuffer=(uint32_t *)audiobuffers_in[i]; + for(idx=0; idx < arguments.period; idx++) { + uint32_t midievent = *(midibuffer + idx); + if(midievent & 0xFF000000) { + debugOutput(DEBUG_LEVEL_NORMAL, " Received midi event %08X on idx %d of period %d\n", + midievent, idx, nb_periods); + } + } default: break; Index: /anches/api-cleanup/tests/streaming/debugtools.c =================================================================== --- /branches/api-cleanup/tests/streaming/debugtools.c (revision 742) +++ (revision ) @@ -1,199 +1,0 @@ -/* - * Copyright (C) 2005-2007 by Daniel Wagner - * Copyright (C) 2005-2007 by Pieter Palmers - * - * This file is part of FFADO - * FFADO = Free Firewire (pro-)audio drivers for linux - * - * FFADO is based upon FreeBoB. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#include -#include -#include "debugtools.h" -#include -#include - -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// - -unsigned char -toAscii( unsigned char c ) -{ - if ( ( c > 31 ) && ( c < 126) ) { - return c; - } else { - return '.'; - } -} - -/* converts a quadlet to a uchar * buffer - * not implemented optimally, but clear - */ -void -quadlet2char( quadlet_t quadlet, unsigned char* buff ) -{ - *(buff) = (quadlet>>24)&0xFF; - *(buff+1) = (quadlet>>16)&0xFF; - *(buff+2) = (quadlet>> 8)&0xFF; - *(buff+3) = (quadlet) &0xFF; -} - -void -hexDump( unsigned char *data_start, unsigned int length ) -{ - unsigned int i=0; - unsigned int byte_pos; - unsigned int bytes_left; - //printf("hexdump: %p %d\n",data_start,length); - - if ( length <= 0 ) { - return; - } - if ( length >= 7 ) { - for ( i = 0; i < (length-7); i += 8 ) { - printf( "%04X: %02X %02X %02X %02X %02X %02X %02X %02X " - "- [%c%c%c%c%c%c%c%c] - %2.5F %2.5F\n", - - i, - - *(data_start+i+0), - *(data_start+i+1), - *(data_start+i+2), - *(data_start+i+3), - *(data_start+i+4), - *(data_start+i+5), - *(data_start+i+6), - *(data_start+i+7), - - toAscii( *(data_start+i+0) ), - toAscii( *(data_start+i+1) ), - toAscii( *(data_start+i+2) ), - toAscii( *(data_start+i+3) ), - toAscii( *(data_start+i+4) ), - toAscii( *(data_start+i+5) ), - toAscii( *(data_start+i+6) ), - toAscii( *(data_start+i+7) ), - - (*((float *)(data_start+i+0))), - (*((float *)(data_start+i+4))) - ); - } - } - byte_pos = i; - bytes_left = length - byte_pos; - - printf( "%04X:" ,i ); - for ( i = byte_pos; i < length; i += 1 ) { - printf( " %02X", *(data_start+i) ); - } - for ( i=0; i < 8-bytes_left; i+=1 ) { - printf( " " ); - } - - printf( " - [" ); - for ( i = byte_pos; i < length; i += 1) { - printf( "%c", toAscii(*(data_start+i))); - } - for ( i = 0; i < 8-bytes_left; i += 1) { - printf( " " ); - } - - printf( "]" ); - printf( "\n" ); -} - -void -hexDumpToFile( FILE* fid, unsigned char *data_start, unsigned int length ) -{ - unsigned int i=0; - unsigned int byte_pos; - unsigned int bytes_left; - //printf("hexdump: %p %d\n",data_start,length); - - if ( length <= 0 ) { - return; - } - if ( length >= 7 ) { - for ( i = 0; i < (length-7); i += 8 ) { - float *f1=(float *)(data_start+i+0); - - fprintf(fid, "%04X: %02X %02X %02X %02X %02X %02X %02X %02X " - "- [%c%c%c%c%c%c%c%c] - %2.5e %2.5e\n", - - i, - - *(data_start+i+0), - *(data_start+i+1), - *(data_start+i+2), - *(data_start+i+3), - *(data_start+i+4), - *(data_start+i+5), - *(data_start+i+6), - *(data_start+i+7), - - toAscii( *(data_start+i+0) ), - toAscii( *(data_start+i+1) ), - toAscii( *(data_start+i+2) ), - toAscii( *(data_start+i+3) ), - toAscii( *(data_start+i+4) ), - toAscii( *(data_start+i+5) ), - toAscii( *(data_start+i+6) ), - toAscii( *(data_start+i+7) ), - - (*(f1)), - (*(f1+1)) - ); - } - } - byte_pos = i; - bytes_left = length - byte_pos; - - fprintf(fid, "%04X:" ,i ); - for ( i = byte_pos; i < length; i += 1 ) { - fprintf(fid, " %02X", *(data_start+i) ); - } - for ( i=0; i < 8-bytes_left; i+=1 ) { - fprintf(fid, " " ); - } - - fprintf(fid, " - [" ); - for ( i = byte_pos; i < length; i += 1) { - fprintf(fid, "%c", toAscii(*(data_start+i))); - } - for ( i = 0; i < 8-bytes_left; i += 1) { - fprintf(fid, " " ); - } - - fprintf(fid, "]" ); - fprintf(fid, "\n" ); -} - - -void -hexDumpQuadlets( quadlet_t *data, unsigned int length ) -{ - unsigned int i=0; - - if ( length <= 0 ) { - return; - } - for (i=0;i. - * - */ - -/** - * Test application for the per-stream decode API - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include - -#include "libffado/ffado.h" - -#include "debugtools.h" - -int run; - -static void sighandler (int sig) -{ - run = 0; -} - -int main(int argc, char *argv[]) -{ - - #define PERIOD_SIZE 1024 - - int samplesread=0, sampleswritten=0; - int nb_in_channels=0, nb_out_channels=0; - int retval=0; - int i=0; - int start_flag = 0; - - int nb_periods=0; - - ffado_sample_t **audiobuffer; - ffado_sample_t *nullbuffer; - - run=1; - - printf("Ffado streaming test application\n"); - - signal (SIGINT, sighandler); - signal (SIGPIPE, sighandler); - - ffado_device_info_t device_info; - - ffado_options_t dev_options; - - dev_options.sample_rate=44100; - dev_options.period_size=PERIOD_SIZE; - - dev_options.nb_buffers=3; - - dev_options.realtime=1; - dev_options.packetizer_priority=60; - - dev_options.verbose=5; - - dev_options.slave_mode=0; - dev_options.snoop_mode=0; - - ffado_device_t *dev=ffado_streaming_init(device_info, dev_options); - - if (!dev) { - fprintf(stderr,"Could not init FFADO Streaming layer\n"); - exit(-1); - } - - nb_in_channels=ffado_streaming_get_nb_capture_streams(dev); - nb_out_channels=ffado_streaming_get_nb_playback_streams(dev); - - /* allocate intermediate buffers */ - audiobuffer=calloc(nb_in_channels,sizeof(ffado_sample_t *)); - for (i=0;i. - * - */ - - -/** - * Test application for the direct decode stream API - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include - -#include "libffado/ffado.h" - -#include "debugtools.h" - -int run; - -static void sighandler (int sig) -{ - run = 0; -} - -int main(int argc, char *argv[]) -{ - - #define PERIOD_SIZE 1024 - - int samplesread=0, sampleswritten=0; - int nb_in_channels=0, nb_out_channels=0; - int retval=0; - int i=0; - int start_flag=0; - - int nb_periods=0; - - ffado_sample_t **audiobuffer; - ffado_sample_t *nullbuffer; - - run=1; - - printf("Ffado streaming test application (2)\n"); - - signal (SIGINT, sighandler); - signal (SIGPIPE, sighandler); - - ffado_device_info_t device_info; - - ffado_options_t dev_options; - - dev_options.sample_rate=44100; - dev_options.period_size=PERIOD_SIZE; - - dev_options.nb_buffers=3; - - dev_options.realtime=0; - dev_options.packetizer_priority=60; - - dev_options.verbose=5; - - dev_options.slave_mode=0; - dev_options.snoop_mode=0; - - ffado_device_t *dev=ffado_streaming_init(device_info, dev_options); - if (!dev) { - fprintf(stderr,"Could not init Ffado Streaming layer\n"); - exit(-1); - } - - nb_in_channels=ffado_streaming_get_nb_capture_streams(dev); - nb_out_channels=ffado_streaming_get_nb_playback_streams(dev); - - /* allocate intermediate buffers */ - audiobuffer=calloc(nb_in_channels,sizeof(ffado_sample_t *)); - for (i=0;i. - * - */ - -#ifndef DEBUG_TOOLS_H -#define DEBUG_TOOLS_H -#include -#include -#include -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// - -unsigned char toAscii( unsigned char c ); - -void quadlet2char( quadlet_t quadlet, unsigned char* buff ); - -void hexDump( unsigned char *data_start, unsigned int length ); -void hexDumpToFile( FILE* fid, unsigned char *data_start, unsigned int length ); -void hexDumpQuadlets( quadlet_t *data, unsigned int length ); - -#endif Index: /anches/api-cleanup/tests/streaming/testmidistreaming1.c =================================================================== --- /branches/api-cleanup/tests/streaming/testmidistreaming1.c (revision 742) +++ (revision ) @@ -1,494 +1,0 @@ -/* - * Copyright (C) 2005-2007 by Pieter Palmers - * - * This file is part of FFADO - * FFADO = Free Firewire (pro-)audio drivers for linux - * - * FFADO is based upon FreeBoB. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - - -/** - * Test application for the direct decode stream API - * for floating point use - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libffado/ffado.h" - -#include "debugtools.h" -#define IEC61883_AM824_LABEL_MIDI_NO_DATA 0x80 -#define IEC61883_AM824_LABEL_MIDI_1X 0x81 -#define IEC61883_AM824_LABEL_MIDI_2X 0x82 -#define IEC61883_AM824_LABEL_MIDI_3X 0x83 - -#define ALSA_SEQ_BUFF_SIZE 1024 -#define MAX_MIDI_PORTS 20 -#define MIDI_TRANSMIT_BUFFER_SIZE 1024 - -int run; - -static void sighandler (int sig) -{ - run = 0; -} - -typedef struct { - int seq_port_nr; - snd_midi_event_t *parser; - snd_seq_t *seq_handle; -} ffado_midi_port_t; - -typedef struct { - snd_seq_t *seq_handle; - int nb_seq_ports; - ffado_midi_port_t *ports[MAX_MIDI_PORTS]; -} ffado_midi_ports_t; - -int open_seq(snd_seq_t **seq_handle, int in_ports[], int out_ports[], int num_in, int num_out); - -/* Open ALSA sequencer with num_in writeable ports and num_out readable ports. */ -/* The sequencer handle and the port IDs are returned. */ -int open_seq(snd_seq_t **seq_handle, int in_ports[], int out_ports[], int num_in, int num_out) { - - int l1; - char portname[64]; - - if (snd_seq_open(seq_handle, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK) < 0) { - fprintf(stderr, "Error opening ALSA sequencer.\n"); - return(-1); - } - - snd_seq_set_client_name(*seq_handle, "FreeBob MIDI I/O test"); - - for (l1 = 0; l1 < num_in; l1++) { - sprintf(portname, "MIDI OUT %d", l1); - if ((in_ports[l1] = snd_seq_create_simple_port(*seq_handle, portname, - SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, - SND_SEQ_PORT_TYPE_MIDI_GENERIC)) < 0) { - fprintf(stderr, "Error creating sequencer port.\n"); - return(-1); - } - } - for (l1 = 0; l1 < num_out; l1++) { - sprintf(portname, "MIDI IN %d", l1); - if ((out_ports[l1] = snd_seq_create_simple_port(*seq_handle, portname, - SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, - SND_SEQ_PORT_TYPE_MIDI_GENERIC)) < 0) { - fprintf(stderr, "Error creating sequencer port.\n"); - return(-1); - } - } - return(0); -} - -void decode_midi_byte (ffado_midi_port_t *port, int byte) { - snd_seq_event_t ev; - if ((snd_midi_event_encode_byte(port->parser,byte, &ev)) > 0) { -// printf("message ok, sending it to %d\n", port->seq_port_nr); - // a midi message is complete, send it out to ALSA - snd_seq_ev_set_subs(&ev); - snd_seq_ev_set_direct(&ev); - snd_seq_ev_set_source(&ev, port->seq_port_nr); - snd_seq_event_output_direct(port->seq_handle, &ev); - } else { - - } -} - -int encode_midi_bytes(ffado_midi_port_t *port, unsigned char *byte_buff, int len) { - static int cnt=0; - cnt++; - if (cnt>64) { - *byte_buff=0xFF; - return 1; - } - return 0; -} - -int main(int argc, char *argv[]) -{ - - #define PERIOD_SIZE 1024 - - int samplesread=0, sampleswritten=0; - int nb_in_channels=0, nb_out_channels=0; - int retval=0; - int i=0; - int start_flag = 0; - - int nb_periods=0; - - ffado_sample_t **audiobuffers_in; - ffado_sample_t **audiobuffers_out; - ffado_sample_t *nullbuffer; - - run=1; - - printf("Ffado MIDI streaming test application (1)\n"); - - signal (SIGINT, sighandler); - signal (SIGPIPE, sighandler); - - ffado_device_info_t device_info; - - ffado_options_t dev_options; - - dev_options.sample_rate=48000; // -1 = detect from discovery - dev_options.period_size=PERIOD_SIZE; - - dev_options.nb_buffers=3; - - dev_options.realtime=0; - dev_options.packetizer_priority=60; - - dev_options.verbose=5; - - dev_options.slave_mode=0; - dev_options.snoop_mode=0; - - ffado_device_t *dev=ffado_streaming_init(device_info, dev_options); - if (!dev) { - fprintf(stderr,"Could not init Ffado Streaming layer\n"); - exit(-1); - } - - nb_in_channels=ffado_streaming_get_nb_capture_streams(dev); - nb_out_channels=ffado_streaming_get_nb_playback_streams(dev); - - int midi_in_nbchannels=0; - int midi_out_nbchannels=0; - - /* allocate intermediate buffers */ - audiobuffers_in=calloc(nb_in_channels,sizeof(ffado_sample_t *)); - audiobuffers_out=calloc(nb_in_channels,sizeof(ffado_sample_t)); - for (i=0;iseq_port_nr=in_ports[cnt++]; - midi_out_port->seq_handle=seq_handle; - if (snd_midi_event_new ( ALSA_SEQ_BUFF_SIZE, &(midi_out_port->parser)) < 0) { - fprintf(stderr, "ALSA Error: could not init parser for MIDI OUT port %d\n",i); - exit(1); // this too - } - midi_out_portmap[i]=midi_out_port; - } - break; - default: break; - } - } - - cnt=0; - for (i=0;iseq_port_nr=out_ports[cnt++]; - midi_in_port->seq_handle=seq_handle; - - if (snd_midi_event_new ( ALSA_SEQ_BUFF_SIZE, &(midi_in_port->parser)) < 0) { - fprintf(stderr, "ALSA Error: could not init parser for MIDI IN port %d\n",i); - exit(1); // this too - } - midi_in_portmap[i]=midi_in_port; - } - break; - default: break; - } - } - - // start the streaming layer - ffado_streaming_prepare(dev); - start_flag = ffado_streaming_start(dev); - - fprintf(stderr,"Entering receive loop (%d,%d)\n",nb_in_channels,nb_out_channels); - while(run && start_flag==0) { - retval = ffado_streaming_wait(dev); - if (retval < 0) { - fprintf(stderr,"Xrun\n"); - ffado_streaming_reset(dev); - continue; - } - -// ffado_streaming_transfer_buffers(dev); - ffado_streaming_transfer_capture_buffers(dev); - ffado_streaming_transfer_playback_buffers(dev); - - nb_periods++; - - if((nb_periods % 32)==0) { -// fprintf(stderr,"\r%05d periods",nb_periods); - } - - for(i=0;i0) { - fprintf(fid_in[i], "---- Period read (%d samples) ----\n",samplesread); - hexDumpToFile(fid_in[i],(unsigned char*)audiobuffers_in[i],samplesread*sizeof(ffado_sample_t)); - } - break; - default: break; - } -// fprintf(fid_in[i], "---- Period read (%d samples) ----\n",samplesread); -// hexDumpToFile(fid_in[i],(unsigned char*)buff,samplesread*sizeof(ffado_sample_t)); - - } - - for(i=0;iparser ); - free(midi_in_port); - } - } - // free the MIDI to seq parsers and port structures - for(i=0;iparser ); - free(midi_out_port); - } - } - - return EXIT_SUCCESS; -} Index: /branches/api-cleanup/libffado/ffado.h =================================================================== --- /branches/api-cleanup/libffado/ffado.h (revision 742) +++ /branches/api-cleanup/libffado/ffado.h (revision 809) @@ -206,10 +206,9 @@ /** - * + * * Buffer types known to the API - * + * */ typedef enum { - ffado_buffer_type_per_stream = -1, // use this to use the per-stream read functions ffado_buffer_type_int24 = 0, ffado_buffer_type_float = 1, @@ -412,28 +411,4 @@ /** - * Reads from a specific channel to a supplied buffer. - * - * @param dev the ffado device - * @param number the stream number - * @param buffer the buffer to copy the samples into - * @param nsamples the number of samples to be read. the buffer has to be big enough for this amount of samples. - * - * @return the amount of samples actually read. -1 on error (xrun). - */ -int ffado_streaming_read(ffado_device_t *dev, int number, ffado_sample_t *buffer, int nsamples); - -/** - * Write to a specific channel from a supplied buffer. - * - * @param dev the ffado device - * @param number the stream number - * @param buffer the buffer to copy the samples from - * @param nsamples the number of samples to be written. - * - * @return the amount of samples actually written. -1 on error. - */ -int ffado_streaming_write(ffado_device_t *dev, int number, ffado_sample_t *buffer, int nsamples); - -/** * Transfer & decode the events from the packet buffer to the sample buffers * Index: /branches/api-cleanup/SConstruct =================================================================== --- /branches/api-cleanup/SConstruct (revision 806) +++ /branches/api-cleanup/SConstruct (revision 809) @@ -331,8 +331,8 @@ env['REVISION'] = '' -env['FFADO_API_VERSION']="5" +env['FFADO_API_VERSION']="6" env['PACKAGE'] = "libffado" -env['VERSION'] = "1.999.11" +env['VERSION'] = "1.999.12" env['LIBVERSION'] = "1.0.0"