Changeset 312

Show
Ignore:
Timestamp:
10/02/06 16:41:21 (17 years ago)
Author:
jwoithe
Message:

MOTU: fix xrun recovery glitches inadvertantly introduced in r309.
MOTU: preliminary MIDI port support. Rate control still needs to be added so it probably won't work in its current form yet. MIDI has not yet been tested.
MOTU: tweaks to receive/transmit missed cycle detection.
jack driver: during driver shutdown don't try to free NULL ports created for non-audio ports during initialisation to preserve device port index locations.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/libfreebob-2.0/src/libstreaming/MotuPort.h

    r267 r312  
    7979                           int position) 
    8080                : MidiPort(name, direction), 
    81                   MotuPortInfo(name, position, 2)  // TODO: add more port information parameters here if nescessary 
     81                  MotuPortInfo(name, position, 0)  // TODO: add more port information parameters here if nescessary 
    8282        {}; 
    8383 
  • branches/libfreebob-2.0/src/libstreaming/MotuStreamProcessor.cpp

    r310 r312  
    7171                return false; 
    7272        } 
    73         m_next_cycle = -1; 
    74         m_closedown_count = -1; 
    75         m_streaming_active = 0; 
    76         m_cycle_count = -1; 
    77         m_cycle_ofs = 0.0; 
    7873 
    7974        return true; 
     
    115110        // Similarly, initialise the "next cycle".  This can be done 
    116111        // whenever iso data is seen - it doesn't have to wait until 
    117         // the stream is initialised. 
     112        // the stream is enabled. 
    118113        if (m_next_cycle < 0) 
    119114                m_next_cycle = cycle; 
     
    138133 
    139134        // Detect a missed cycle and attempt to "catch up". 
    140         if (!m_disabled && m_next_cycle>=0 && cycle!=m_next_cycle) { 
     135        if (cycle != m_next_cycle) { 
     136                debugOutput(DEBUG_LEVEL_VERBOSE, "tx cycle miss: %d requested, %d expected\n",cycle,m_next_cycle); 
     137        } 
     138        // Attempt to catch up any missed cycles but only if we're enabled. 
     139        if (!m_disabled && cycle!=m_next_cycle) { 
    141140                float ftmp; 
    142141                signed int ccount = m_next_cycle; 
    143                 debugOutput(DEBUG_LEVEL_VERBOSE, "tx cycle miss: %d requested, %d expected\n",cycle,m_next_cycle); 
    144142 
    145143                while (ccount!=cycle) { 
     
    175173        } 
    176174 
    177         if  (!m_disabled) { 
    178                 if (++m_next_cycle >= 8000) 
    179                         m_next_cycle -= 8000; 
    180         } else 
    181                 m_next_cycle = -1; 
     175        if ((m_next_cycle=cycle+1) >= 8000) 
     176                m_next_cycle -= 8000; 
    182177 
    183178        // Deal cleanly with potential wrap-around cycle counter conditions 
     
    250245 
    251246        } else { 
     247 
    252248                retval=RAW1394_ISO_OK; 
    253249                *length += read_size; 
     
    387383        } 
    388384 
    389         m_next_cycle = -1; 
    390         m_closedown_count = -1; 
    391         m_streaming_active = 0; 
    392         m_cycle_count = -1; 
    393         m_cycle_ofs = 0.0; 
    394  
    395385        return true; 
    396386} 
     
    455445                                return false; 
    456446                        } 
     447                        if (!(*it)->setBufferType(Port::E_RingBuffer)) { 
     448                                debugFatal("Could not set buffer type"); 
     449                                return false; 
     450                        } 
     451                        if (!(*it)->setDataType(Port::E_MidiEvent)) { 
     452                                debugFatal("Could not set data type"); 
     453                                return false; 
     454                        } 
     455                        // FIXME: probably need rate control too.  See 
     456                        // Port::useRateControl() and AmdtpStreamProcessor. 
    457457                        break; 
    458458                 
     
    696696 * @return true if all successfull 
    697697 */ 
    698 bool MotuTransmitStreamProcessor::encodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc) 
    699 
    700     bool ok=true; 
    701     char byte; 
    702      
    703     quadlet_t *target_event=NULL; 
    704     int j; 
    705  
    706     for ( PortVectorIterator it = m_PacketPorts.begin(); 
    707           it != m_PacketPorts.end(); 
    708           ++it ) 
    709     { 
     698bool MotuTransmitStreamProcessor::encodePacketPorts(quadlet_t *data, unsigned int nevents,  
     699                unsigned int dbc) { 
     700        bool ok=true; 
     701        char byte; 
     702 
     703        // Use char here since the target address won't necessarily be 
     704        // aligned; use of an unaligned quadlet_t may cause issues on 
     705        // certain architectures.  Besides, the target for MIDI data going 
     706        // directly to the MOTU isn't structured in quadlets anyway; it is a 
     707        // sequence of 3 unaligned bytes. 
     708        unsigned char *target = NULL; 
     709 
     710        for ( PortVectorIterator it = m_PacketPorts.begin(); 
     711                it != m_PacketPorts.end(); 
     712                ++it ) { 
    710713 
    711714#ifdef DEBUG 
    712         MotuPortInfo *pinfo=dynamic_cast<MotuPortInfo *>(*it); 
    713         assert(pinfo); // this should not fail!! 
    714  
    715         // the only packet type of events for AMDTP is MIDI in mbla 
    716 //         assert(pinfo->getFormat()==MotuPortInfo::E_Midi); 
     715                //FIXME: make this into a static_cast when not DEBUG? 
     716                Port *port=dynamic_cast<Port *>(*it); 
     717                assert(port); // this should not fail!! 
     718 
     719                // Currently the only packet type of events for MOTU  
     720                // is MIDI in mbla.  However in future control data 
     721                // might also be sent via "packet" events. 
     722                // assert(pinfo->getFormat()==MotuPortInfo::E_Midi); 
    717723#endif 
    718          
    719         MotuMidiPort *mp=static_cast<MotuMidiPort *>(*it); 
    720          
    721         // TODO: decode the midi (or other type) stuff here 
    722  
    723     } 
    724          
    725     return ok; 
     724                // FIXME: MIDI output is completely untested at present. 
     725                switch (port->getPortType()) { 
     726                        case Port::E_Midi: { 
     727                                MotuMidiPort *mp=static_cast<MotuMidiPort *>(*it); 
     728 
     729                                // Send a byte if we can. MOTU MIDI data is 
     730                                // sent using a 3-byte sequence starting at 
     731                                // the port's position.  For now we'll 
     732                                // always send in the first event of a 
     733                                // packet, but this might need refinement 
     734                                // later. 
     735                                if (mp->canRead()) { 
     736                                        mp->readEvent(&byte); 
     737                                        target = (unsigned char *)data + mp->getPosition(); 
     738                                        *(target++) = 0x01; 
     739                                        *(target++) = 0x00; 
     740                                        *(target++) = byte; 
     741                                } 
     742                                break; 
     743                        } 
     744                        default: 
     745                                debugOutput(DEBUG_LEVEL_VERBOSE, "Unknown packet-type port type %d\n",port->getPortType()); 
     746                                return ok;         
     747                } 
     748        } 
     749 
     750        return ok; 
    726751} 
    727752 
     
    871896} 
    872897 
     898bool MotuTransmitStreamProcessor::preparedForStart() { 
     899// Reset some critical variables required so the stream starts cleanly. This 
     900// method is called once on every stream restart, including those during 
     901// xrun recovery.  Initialisations which should be done once should be 
     902// placed in the init() method instead. 
     903        m_running = 0; 
     904        m_next_cycle = -1; 
     905        m_closedown_count = -1; 
     906        m_streaming_active = 0; 
     907        m_cycle_count = -1; 
     908        m_cycle_ofs = 0.0; 
     909 
     910        // At this point we'll also disable the stream processor here. 
     911        // At this stage stream processors are always explicitly re-enabled 
     912        // after being started, so by starting in the disabled state we  
     913        // ensure that every start will be exactly the same. 
     914        disable(); 
     915 
     916        return true; 
     917} 
     918 
    873919/* --------------------- RECEIVE ----------------------- */ 
    874920 
     
    890936bool MotuReceiveStreamProcessor::init() { 
    891937 
    892     // call the parent init 
    893     // this has to be done before allocating the buffers,  
    894     // because this sets the buffersizes from the processormanager 
    895     if(!ReceiveStreamProcessor::init()) { 
    896         debugFatal("Could not do base class init (%d)\n",this); 
    897         return false; 
    898    
    899  
    900     return true; 
     938       // call the parent init 
     939       // this has to be done before allocating the buffers,  
     940       // because this sets the buffersizes from the processormanager 
     941       if(!ReceiveStreamProcessor::init()) { 
     942               debugFatal("Could not do base class init (%d)\n",this); 
     943               return false; 
     944       
     945 
     946       return true; 
    901947} 
    902948 
     
    906952                  unsigned int cycle, unsigned int dropped) { 
    907953     
    908     enum raw1394_iso_disposition retval=RAW1394_ISO_OK; 
    909     signed int have_lost_cycles = 0; 
    910  
    911     // Detect missed receive cycles 
    912     // FIXME: it would be nice to advance the rx buffer by the amount of 
    913     // frames missed.  However, since the MOTU transmits more frames per 
    914     // cycle than the average and "catches up" with periodic empty cycles 
    915     // it's not trivial to work out precisely how many frames were missed.  
    916     // Ultimately I think we need to do so if sync is to be maintained 
    917     // across a transient receive failure. 
    918     if (m_next_cycle < 0) 
    919         m_next_cycle = cycle; 
    920     if ((signed)cycle != m_next_cycle) { 
    921         debugOutput(DEBUG_LEVEL_VERBOSE, "lost rx cycles; received %d, expected %d\n", 
    922             cycle, m_next_cycle); 
    923         m_next_cycle = cycle; 
    924         have_lost_cycles = 1; 
    925     } 
    926     if (!m_disabled) { 
    927         if (++m_next_cycle >= 8000) 
    928             m_next_cycle -= 8000; 
    929     } else 
    930         m_next_cycle = -1; 
    931  
    932     // If the packet length is 8 bytes (ie: just a CIP-like header) there is 
    933     // no isodata. 
    934     if (length > 8) { 
    935         // The iso data blocks from the MOTUs comprise a CIP-like header 
    936         // followed by a number of events (8 for 1x rates, 16 for 2x rates, 
    937         // 32 for 4x rates). 
    938         quadlet_t *quadlet = (quadlet_t *)data; 
    939         unsigned int dbs = get_bits(ntohl(quadlet[0]), 23, 8);  // Size of one event in terms of fdf_size 
    940         unsigned int fdf_size = get_bits(ntohl(quadlet[1]), 23, 8) == 0x22 ? 32:0; // Event unit size in bits 
    941         unsigned int event_length = (fdf_size * dbs) / 8;       // Event size in bytes 
    942         unsigned int n_events = (length-8) / event_length; 
    943  
    944         // Don't even attempt to process a packet if it isn't what we expect 
    945         // from a MOTU 
    946         if (tag!=1 || fdf_size!=32) { 
    947                 return RAW1394_ISO_OK; 
    948         } 
    949  
    950         // Signal that we're running 
    951         if (n_events) m_running=true; 
    952  
    953         /* Send actual ticks-per-frame values (as deduced by the incoming  
    954          * SPHs) to the DLL for averaging.  Doing this here means the DLL 
    955          * should acquire a reasonable estimation of the ticks per frame 
    956          * even while the stream is formally disabled.  This in turn means 
    957          * the transmit stream should have access to a very realistic  
    958          * estimate by the time it is enabled.  The major disadvantage 
    959          * is a small increase in the overheads of this function compared 
    960          * to what would be the case if this was delayed by pushing it into 
    961          * the decode functions. 
    962          */ 
    963         unsigned int ev; 
    964         signed int sph_ofs; 
    965  
    966         /* If this is the first block received or we have lost cycles, 
    967          * initialise the m_last_cycle_ofs to a value which won't cause the 
    968          * DLL to become polluted with an inappropriate ticks-per-frame 
    969          * estimate. 
    970          */ 
    971         if (m_last_cycle_ofs<0 || have_lost_cycles) { 
    972                 sph_ofs = ntohl(*(quadlet_t *)(data+8)) & 0xfff; 
    973                 m_last_cycle_ofs = sph_ofs-(int)(m_ticks_per_frame); 
    974         } 
    975         for (ev=0; ev<n_events; ev++) { 
    976                 sph_ofs = ntohl(*(quadlet_t *)(data+8+ev*m_event_size)) & 0xfff; 
    977                 signed int sph_diff = (sph_ofs - m_last_cycle_ofs); 
    978                 // Handle wraparound of the cycle offset 
    979                 if (sph_diff < 0) 
    980                         sph_diff += 3072; 
    981                 float err = sph_diff - m_ticks_per_frame; 
    982                 // FIXME: originally we used a value of 0.0005 for the coefficient 
    983                 // which mirrored the value used in 
    984                 // AmdtpReceiveStreamProcessor::putPacket() for a similar purpose. 
    985                 // However, tests showed that this introduced discontinuities in 
    986                 // the output audio signal, so an alternative value was sought. 
    987                 // Further tests are needed, but a value of 0.015 seems to work 
    988                 // well, at least at a sample rate of 48 kHz. 
    989                 m_ticks_per_frame += 0.015*err; 
    990                 m_last_cycle_ofs = sph_ofs; 
    991         } 
    992  
    993         // Don't process the stream when it is not enabled 
    994         if (m_disabled) { 
    995                 return RAW1394_ISO_OK; 
    996         } 
    997          
    998         // If closedown is active we also just throw data way, but in this case 
    999         // we keep the frame counter going to prevent a false xrun detection 
    1000         if (m_closedown_active) { 
     954        enum raw1394_iso_disposition retval=RAW1394_ISO_OK; 
     955        signed int have_lost_cycles = 0; 
     956 
     957        // Detect missed receive cycles 
     958        // FIXME: it would be nice to advance the rx buffer by the amount of 
     959        // frames missed.  However, since the MOTU transmits more frames per 
     960        // cycle than the average and "catches up" with periodic empty 
     961        // cycles it's not trivial to work out precisely how many frames 
     962        // were missed.  Ultimately I think we need to do so if sync is to 
     963        // be maintained across a transient receive failure. 
     964        if (m_next_cycle < 0) 
     965                m_next_cycle = cycle; 
     966        if ((signed)cycle != m_next_cycle) { 
     967                debugOutput(DEBUG_LEVEL_VERBOSE, "lost rx cycles; received %d, expected %d\n", 
     968                        cycle, m_next_cycle); 
     969                m_next_cycle = cycle; 
     970                have_lost_cycles = 1; 
     971        } 
     972        if (++m_next_cycle >= 8000) 
     973                m_next_cycle -= 8000; 
     974 
     975        // If the packet length is 8 bytes (ie: just a CIP-like header) 
     976        // there is no isodata. 
     977        if (length > 8) { 
     978                // The iso data blocks from the MOTUs comprise a CIP-like 
     979                // header followed by a number of events (8 for 1x rates, 16 
     980                // for 2x rates, 32 for 4x rates). 
     981                quadlet_t *quadlet = (quadlet_t *)data; 
     982                unsigned int dbs = get_bits(ntohl(quadlet[0]), 23, 8);  // Size of one event in terms of fdf_size 
     983                unsigned int fdf_size = get_bits(ntohl(quadlet[1]), 23, 8) == 0x22 ? 32:0; // Event unit size in bits 
     984                unsigned int event_length = (fdf_size * dbs) / 8;       // Event size in bytes 
     985                unsigned int n_events = (length-8) / event_length; 
     986 
     987                // Don't even attempt to process a packet if it isn't what 
     988                // we expect from a MOTU.  Yes, an FDF value of 32 bears 
     989                // little relationship to the actual data (24 bit integer) 
     990                // sent by the MOTU - it's one of those areas where MOTU 
     991                // have taken a curious detour around the standards. 
     992                if (tag!=1 || fdf_size!=32) { 
     993                        return RAW1394_ISO_OK; 
     994                } 
     995 
     996                // Signal that we're running 
     997                if (n_events) m_running=true; 
     998 
     999                /* Send actual ticks-per-frame values (as deduced by the 
     1000                 * incoming SPHs) to the DLL for averaging.  Doing this here 
     1001                 * means the DLL should acquire a reasonable estimation of 
     1002                 * the ticks per frame even while the stream is formally 
     1003                 * disabled.  This in turn means the transmit stream should 
     1004                 * have access to a very realistic estimate by the time it 
     1005                 * is enabled.  The major disadvantage is a small increase 
     1006                 * in the overheads of this function compared to what would 
     1007                 * be the case if this was delayed by pushing it into the 
     1008                 * decode functions. 
     1009                 */ 
     1010                unsigned int ev; 
     1011                signed int sph_ofs; 
     1012 
     1013                /* If this is the first block received or we have lost 
     1014                 * cycles, initialise the m_last_cycle_ofs to a value which 
     1015                 * won't cause the DLL to become polluted with an 
     1016                 * inappropriate ticks-per-frame estimate. 
     1017                 */ 
     1018                if (m_last_cycle_ofs<0 || have_lost_cycles) { 
     1019                        sph_ofs = ntohl(*(quadlet_t *)(data+8)) & 0xfff; 
     1020                        m_last_cycle_ofs = sph_ofs-(int)(m_ticks_per_frame); 
     1021                } 
     1022                for (ev=0; ev<n_events; ev++) { 
     1023                        sph_ofs = ntohl(*(quadlet_t *)(data+8+ev*m_event_size)) & 0xfff; 
     1024                        signed int sph_diff = (sph_ofs - m_last_cycle_ofs); 
     1025                        // Handle wraparound of the cycle offset 
     1026                        if (sph_diff < 0) 
     1027                                sph_diff += 3072; 
     1028                        float err = sph_diff - m_ticks_per_frame; 
     1029                        // FIXME: originally we used a value of 0.0005 for 
     1030                        // the coefficient which mirrored the value used in 
     1031                        // AmdtpReceiveStreamProcessor::putPacket() for a 
     1032                        // similar purpose.  However, tests showed that this 
     1033                        // introduced discontinuities in the output audio 
     1034                        // signal, so an alternative value was sought.  
     1035                        // Further tests are needed, but a value of 0.015 
     1036                        // seems to work well, at least at a sample rate of 
     1037                        // 48 kHz. 
     1038                        m_ticks_per_frame += 0.015*err; 
     1039                        m_last_cycle_ofs = sph_ofs; 
     1040                } 
     1041 
     1042                // Don't process the stream when it is not enabled 
     1043                if (m_disabled) { 
     1044                        return RAW1394_ISO_OK; 
     1045                } 
     1046 
     1047                // If closedown is active we also just throw data way, but 
     1048                // in this case we keep the frame counter going to prevent a 
     1049                // false xrun detection 
     1050                if (m_closedown_active) { 
     1051                        incrementFrameCounter(n_events); 
     1052                        if (m_framecounter > (signed int)m_period) 
     1053                                return RAW1394_ISO_DEFER; 
     1054                        return RAW1394_ISO_OK; 
     1055                } 
     1056 
     1057                debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "put packet...\n"); 
     1058 
     1059                // Add the data payload (events) to the ringbuffer.  We'll 
     1060                // just copy everything including the 4 byte timestamp at 
     1061                // the start of each event (that is, everything except the 
     1062                // CIP-like header).  The demultiplexer can deal with the 
     1063                // complexities such as the channel 24-bit data. 
     1064                unsigned int write_size = length-8; 
     1065                if (freebob_ringbuffer_write(m_event_buffer,(char *)(data+8),write_size) < write_size) { 
     1066                        debugWarning("Receive buffer overrun (cycle %d, FC=%d, PC=%d)\n",  
     1067                                cycle, m_framecounter, m_handler->getPacketCount()); 
     1068                        m_xruns++; 
     1069 
     1070                        retval=RAW1394_ISO_DEFER; 
     1071                } else { 
     1072                        retval=RAW1394_ISO_OK; 
     1073                        // Process all ports that should be handled on a 
     1074                        // per-packet basis.  This is MIDI for AMDTP (due to 
     1075                        // the need of DBC) 
     1076                        int dbc = get_bits(ntohl(quadlet[0]), 8, 8);  // Low byte of CIP quadlet 0 
     1077                        if (!decodePacketPorts((quadlet_t *)(data+8), n_events, dbc)) { 
     1078                                debugWarning("Problem decoding Packet Ports\n"); 
     1079                                retval=RAW1394_ISO_DEFER; 
     1080                        } 
     1081                        // time stamp processing can be done here 
     1082                } 
     1083 
     1084                // update the frame counter 
    10011085                incrementFrameCounter(n_events); 
    1002                 if (m_framecounter > (signed int)m_period) 
    1003                         return RAW1394_ISO_DEFER; 
    1004                 return RAW1394_ISO_OK; 
    1005         } 
    1006  
    1007         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "put packet...\n"); 
    1008  
    1009         // Add the data payload (events) to the ringbuffer.  We'll just copy 
    1010         // everything including the 4 byte timestamp at the start of each 
    1011         // event (that is, everything except the CIP-like header).  The 
    1012         // demultiplexer can deal with the complexities such as the channel 
    1013         // 24-bit data. 
    1014         unsigned int write_size = length-8; 
    1015         if (freebob_ringbuffer_write(m_event_buffer,(char *)(data+8),write_size) < write_size) { 
    1016                 debugWarning("Receive buffer overrun (cycle %d, FC=%d, PC=%d)\n",  
    1017                         cycle, m_framecounter, m_handler->getPacketCount()); 
    1018                 m_xruns++; 
    1019  
    1020                 retval=RAW1394_ISO_DEFER; 
    1021         } else { 
    1022                 retval=RAW1394_ISO_OK; 
    1023                 // Process all ports that should be handled on a per-packet basis 
    1024                 // This is MIDI for AMDTP (due to the need of DBC) 
    1025                 int dbc = get_bits(ntohl(quadlet[0]), 8, 8);  // Low byte of CIP quadlet 0 
    1026                 if (!decodePacketPorts((quadlet_t *)(data+8), n_events, dbc)) { 
    1027                         debugWarning("Problem decoding Packet Ports\n"); 
     1086                // keep this at the end, because otherwise the 
     1087                // raw1394_loop_iterate functions inner loop keeps 
     1088                // requesting packets without going to the xmit handler, 
     1089                // leading to xmit starvation 
     1090                if(m_framecounter>(signed int)m_period) { 
    10281091                        retval=RAW1394_ISO_DEFER; 
    10291092                } 
    1030                 // time stamp processing can be done here 
    1031         } 
    1032  
    1033         // update the frame counter 
    1034         incrementFrameCounter(n_events); 
    1035         // keep this at the end, because otherwise the raw1394_loop_iterate functions inner loop 
    1036         // keeps requesting packets without going to the xmit handler, leading to xmit starvation 
    1037         if(m_framecounter>(signed int)m_period) { 
    1038                 retval=RAW1394_ISO_DEFER; 
    1039         } 
    1040          
    1041     } else { // no events in packet 
    1042         // discard packet 
    1043         // can be important for sync though 
    1044     } 
     1093 
     1094        } else { // no events in packet 
     1095                // discard packet 
     1096                // can be important for sync though 
     1097        } 
    10451098     
    1046     return retval; 
     1099       return retval; 
    10471100} 
    10481101 
     
    11491202                                        return false; 
    11501203                                } 
     1204                                if (!(*it)->setBufferType(Port::E_RingBuffer)) { 
     1205                                        debugFatal("Could not set buffer type"); 
     1206                                        return false; 
     1207                                } 
     1208                                if (!(*it)->setDataType(Port::E_MidiEvent)) { 
     1209                                        debugFatal("Could not set data type"); 
     1210                                        return false; 
     1211                                } 
     1212                                // FIXME: probably need rate control too.  See 
     1213                                // Port::useRateControl() and AmdtpStreamProcessor. 
    11511214                                break; 
    11521215                        case Port::E_Control: 
     
    13201383 * @return true if all successfull 
    13211384 */ 
    1322 bool MotuReceiveStreamProcessor::decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc) 
    1323 
     1385bool MotuReceiveStreamProcessor::decodePacketPorts(quadlet_t *data, unsigned int nevents,  
     1386               unsigned int dbc)
    13241387        bool ok=true; 
    1325          
    1326         quadlet_t *target_event=NULL; 
    1327         int j; 
    1328          
     1388 
     1389        // Use char here since the source address won't necessarily be 
     1390        // aligned; use of an unaligned quadlet_t may cause issues on 
     1391        // certain architectures.  Besides, the source for MIDI data going 
     1392        // directly to the MOTU isn't structured in quadlets anyway; it is a 
     1393        // sequence of 3 unaligned bytes. 
     1394        unsigned char *src = NULL; 
     1395 
    13291396        for ( PortVectorIterator it = m_PacketPorts.begin(); 
    1330           it != m_PacketPorts.end(); 
    1331           ++it ) { 
     1397               it != m_PacketPorts.end(); 
     1398               ++it ) { 
    13321399 
    13331400#ifdef DEBUG 
    1334                 MotuPortInfo *pinfo=dynamic_cast<MotuPortInfo *>(*it); 
    1335                 assert(pinfo); // this should not fail!! 
    1336  
    1337                 // the only packet type of events for AMDTP is MIDI in mbla 
    1338 //              assert(pinfo->getFormat()==MotuPortInfo::E_Midi); 
     1401                //FIXME: make these into a static_casts when not DEBUG? 
     1402                Port *port=dynamic_cast<Port *>(*it); 
     1403                assert(port); // this should not fail!! 
     1404 
     1405                // Currently the only packet type of events for MOTU  
     1406                // is MIDI in mbla.  However in future control data 
     1407                // might also be sent via "packet" events, so allow  
     1408                // for this possible expansion. 
    13391409#endif 
    1340                 MotuMidiPort *mp=static_cast<MotuMidiPort *>(*it); 
    1341                  
    1342  
    1343         // do decoding here 
    1344  
    1345         } 
    1346          
     1410                // FIXME: MIDI input is completely untested at present. 
     1411                switch (port->getPortType()) { 
     1412                        case Port::E_Midi: { 
     1413                                MotuMidiPort *mp=static_cast<MotuMidiPort *>(*it); 
     1414                                signed int sample; 
     1415                                unsigned int j = 0; 
     1416                                // Get MIDI bytes if present anywhere in the 
     1417                                // packet.  MOTU MIDI data is sent using a 
     1418                                // 3-byte sequence starting at the port's 
     1419                                // position.  It's thought that there can never 
     1420                                // be more than one MIDI byte per packet, but 
     1421                                // for completeness we'll check the entire packet 
     1422                                // anyway. 
     1423                                src = (unsigned char *)data + mp->getPosition(); 
     1424                                while (j < nevents) { 
     1425                                        if (*src==0x01 && *(src+1)==0x00) { 
     1426                                                sample = *(src+2); 
     1427                                                if (!mp->writeEvent(&sample)) { 
     1428                                                        debugWarning("MIDI packet port events lost\n"); 
     1429                                                        ok = false; 
     1430                                                } 
     1431                                        } 
     1432                                        j++; 
     1433                                        src += m_event_size; 
     1434                                } 
     1435                                break; 
     1436                        } 
     1437                        default: 
     1438                                debugOutput(DEBUG_LEVEL_VERBOSE, "Unknown packet-type port format %d\n",port->getPortType()); 
     1439                                return ok;         
     1440                } 
     1441        } 
     1442 
    13471443        return ok; 
    13481444} 
     
    14421538        return true; 
    14431539} 
     1540 
     1541bool MotuReceiveStreamProcessor::preparedForStart() { 
     1542// Reset some critical variables required so the stream starts cleanly. This 
     1543// method is called once on every stream restart, including those during 
     1544// xrun recovery.  Initialisations which should be done once should be 
     1545// placed in the init() method instead. 
     1546        m_running = 0; 
     1547        m_next_cycle = -1; 
     1548        m_closedown_active = 0; 
     1549        m_last_cycle_ofs = -1; 
     1550 
     1551        // At this point we'll also disable the stream processor here. 
     1552        // At this stage stream processors are always explicitly re-enabled 
     1553        // after being started, so by starting in the disabled state we  
     1554        // ensure that every start will be exactly the same. 
     1555        disable(); 
     1556 
     1557        return true; 
     1558} 
     1559 
    14441560                 
    14451561} // end of namespace FreebobStreaming 
  • branches/libfreebob-2.0/src/libstreaming/MotuStreamProcessor.h

    r309 r312  
    7676 
    7777        virtual bool preparedForStop(); 
     78        virtual bool preparedForStart(); 
    7879 
    7980protected: 
     
    165166 
    166167        virtual bool preparedForStop(); 
     168        virtual bool preparedForStart(); 
    167169 
    168170protected: 
  • branches/libfreebob-2.0/src/libstreaming/StreamProcessor.h

    r287 r312  
    112112 
    113113        virtual bool preparedForStop() {return true;}; 
     114        virtual bool preparedForStart() {return true;}; 
    114115 
    115116protected: 
  • branches/libfreebob-2.0/src/libstreaming/StreamProcessorManager.cpp

    r309 r312  
    320320                it != m_ReceiveProcessors.end(); 
    321321                ++it ) { 
     322                        if (!(*it)->preparedForStart()) { 
     323                                debugOutput(DEBUG_LEVEL_VERBOSE,"Receive stream processor (%p) failed to prepare for start\n", *it); 
     324                                return false; 
     325                        } 
    322326                        if (!m_isoManager->registerStream(*it)) { 
    323327                                debugOutput(DEBUG_LEVEL_VERBOSE,"Could not register receive stream processor (%p) with the Iso manager\n",*it); 
     
    332336                it != m_TransmitProcessors.end(); 
    333337                ++it ) { 
     338                        if (!(*it)->preparedForStart()) { 
     339                                debugOutput(DEBUG_LEVEL_VERBOSE,"Transmit stream processor (%p) failed to prepare for start\n", *it); 
     340                                return false; 
     341                        } 
    334342                        if (!m_isoManager->registerStream(*it)) { 
    335343                                debugOutput(DEBUG_LEVEL_VERBOSE,"Could not register transmit stream processor (%p) with the Iso manager\n",*it); 
  • branches/libfreebob-2.0/src/motu/motu_avdevice.cpp

    r311 r312  
    404404         
    405405        char *buff; 
    406         unsigned int i; 
    407406        FreebobStreaming::Port *p=NULL; 
    408407 
     
    412411        } 
    413412 
    414         // example of adding an midi port: 
    415 //    asprintf(&buff,"dev%d_cap_%s",m_id,"myportnamehere"); 
    416 //    p=new FreebobStreaming::MotuMidiPort( 
    417 //            buff, 
    418 //            FreebobStreaming::Port::E_Capture,  
    419 //            0 // you can add all other port specific stuff you  
    420 //              // need to pass by extending MotuXXXPort and MotuPortInfo 
    421 //    ); 
    422 //    free(buff); 
    423 // 
    424 //    if (!p) { 
    425 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff); 
    426 //    } else { 
    427 //        if (!m_receiveProcessor->addPort(p)) { 
    428 //            debugWarning("Could not register port with stream processor\n"); 
    429 //            return false; 
    430 //        } else { 
    431 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff); 
    432 //        } 
    433 //    } 
    434      
     413        // Add MIDI port.  The MOTU only has one MIDI input port, with each 
     414        // MIDI byte sent using a 3 byte sequence starting at byte 4 of the 
     415        // event data. 
     416        asprintf(&buff,"dev%d_cap_MIDI0",m_id); 
     417        p = new FreebobStreaming::MotuMidiPort(buff, 
     418                FreebobStreaming::Port::E_Capture, 4); 
     419        if (!p) { 
     420                debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff); 
     421        } else { 
     422                if (!m_receiveProcessor->addPort(p)) { 
     423                        debugWarning("Could not register port with stream processor\n"); 
     424                        free(buff); 
     425                        return false; 
     426                } else { 
     427                        debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n", buff); 
     428                } 
     429        } 
     430        free(buff); 
     431 
    435432        // example of adding an control port: 
    436433//    asprintf(&buff,"dev%d_cap_%s",m_id,"myportnamehere"); 
     
    478475        } 
    479476 
    480 //      // example of adding an midi port: 
    481 //    asprintf(&buff,"dev%d_pbk_%s",m_id,"myportnamehere"); 
    482 //     
    483 //    p=new FreebobStreaming::MotuMidiPort( 
    484 //            buff, 
    485 //            FreebobStreaming::Port::E_Playback,  
    486 //            0 // you can add all other port specific stuff you  
    487 //              // need to pass by extending MotuXXXPort and MotuPortInfo 
    488 //    ); 
    489 //    free(buff); 
    490 // 
    491 //    if (!p) { 
    492 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff); 
    493 //    } else { 
    494 //        if (!m_transmitProcessor->addPort(p)) { 
    495 //            debugWarning("Could not register port with stream processor\n"); 
    496 //            return false; 
    497 //        } else { 
    498 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff); 
    499 //        } 
    500 //    } 
    501      
     477        // Add MIDI port.  The MOTU only has one output MIDI port, with each 
     478        // MIDI byte transmitted using a 3 byte sequence starting at byte 4 
     479        // of the event data. 
     480        asprintf(&buff,"dev%d_pbk_MIDI0",m_id); 
     481        p = new FreebobStreaming::MotuMidiPort(buff, 
     482                FreebobStreaming::Port::E_Capture, 4); 
     483        if (!p) { 
     484                debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff); 
     485        } else { 
     486                if (!m_receiveProcessor->addPort(p)) { 
     487                        debugWarning("Could not register port with stream processor\n"); 
     488                        free(buff); 
     489                        return false; 
     490                } else { 
     491                        debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n", buff); 
     492                } 
     493        } 
     494        free(buff); 
     495 
    502496        // example of adding an control port: 
    503497//    asprintf(&buff,"dev%d_pbk_%s",m_id,"myportnamehere"); 
  • branches/libfreebob-2.0/support/jack/freebob_driver.c

    r302 r312  
    207207        for (node = driver->capture_ports; node; 
    208208             node = jack_slist_next (node)) { 
    209                 jack_port_unregister (driver->client, 
    210                                       ((jack_port_t *) node->data)); 
     209                // Don't try to unregister NULL entries added for non-audio 
     210                // freebob ports by freebob_driver_attach(). 
     211                if (node->data != NULL) { 
     212                        jack_port_unregister (driver->client, 
     213                                              ((jack_port_t *) node->data)); 
     214                } 
    211215        } 
    212216