fix all manner of things relating to io connections, setting capture alignment, and...
authorPaul Davis <paul@linuxaudiosystems.com>
Tue, 15 Mar 2011 19:32:21 +0000 (19:32 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Tue, 15 Mar 2011 19:32:21 +0000 (19:32 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@9155 d708f5d6-7413-0410-9779-e7cbd77b26cf

12 files changed:
libs/ardour/ardour/audio_diskstream.h
libs/ardour/ardour/audioengine.h
libs/ardour/ardour/session.h
libs/ardour/audio_diskstream.cc
libs/ardour/audioengine.cc
libs/ardour/diskstream.cc
libs/ardour/io.cc
libs/ardour/midi_diskstream.cc
libs/ardour/port.cc
libs/ardour/route.cc
libs/ardour/session.cc
libs/ardour/session_transport.cc

index 53dbe5bd9b0245b98dcda085a59e6a9b91daedbc..12ad418a75901e7b9ab2dc65403a6e5186509a11 100644 (file)
@@ -66,17 +66,12 @@ class AudioDiskstream : public Diskstream
        std::string input_source (uint32_t n=0) const {
                boost::shared_ptr<ChannelList> c = channels.reader();
                if (n < c->size()) {
-                       return (*c)[n]->source ? (*c)[n]->source->name() : "";
+                       return (*c)[n]->source.name;
                } else {
                        return "";
                }
        }
 
-       Port *input_source_port (uint32_t n=0) const {
-               boost::shared_ptr<ChannelList> c = channels.reader();
-               if (n < c->size()) return (*c)[n]->source; return 0;
-       }
-
        void set_record_enabled (bool yn);
        int set_destructive (bool yn);
        int set_non_layered (bool yn);
@@ -179,6 +174,12 @@ class AudioDiskstream : public Diskstream
        bool commit  (framecnt_t nframes);
 
   private:
+        struct ChannelSource { 
+            std::string name;
+
+            bool is_physical () const;
+            void ensure_monitor_input (bool) const;
+        };
 
        struct ChannelInfo : public boost::noncopyable {
 
@@ -197,8 +198,10 @@ class AudioDiskstream : public Diskstream
                boost::shared_ptr<AudioFileSource> fades_source;
                boost::shared_ptr<AudioFileSource> write_source;
 
-               /// the Port that our audio data comes from
-               Port         *source;
+               /// information the Port that our audio data comes from
+               
+                ChannelSource source;
+
                Sample       *current_capture_buffer;
                Sample       *current_playback_buffer;
 
index e025169f0ac3b432fcbe022822f3df570abc7256..8e68581e122db4d1e37fab79c1492bd331e66371 100644 (file)
@@ -170,6 +170,9 @@ class AudioEngine : public SessionHandlePtr
        Port *register_output_port (DataType, const std::string& portname);
        int   unregister_port (Port &);
 
+        bool port_is_physical (const std::string&) const;
+        void ensure_monitor_input (const std::string&, bool) const;
+
        void split_cycle (pframes_t offset);
 
        int connect (const std::string& source, const std::string& destination);
index c67e3d10fe6c63de739332893159752230d1d8d3..29aae1fbd42b8ef8a7cd65139688b8bfcfe9e0ff 100644 (file)
@@ -1221,7 +1221,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
        void route_processors_changed (RouteProcessorChange);
 
        bool find_route_name (std::string const &, uint32_t& id, char* name, size_t name_len, bool);
-       void count_existing_route_channels (ChanCount& in, ChanCount& out);
+       void count_existing_track_channels (ChanCount& in, ChanCount& out);
        void auto_connect_route (Route*,
                                  ChanCount& existing_inputs,
                                  ChanCount& existing_outputs,
index 36d72ce124bc599c21cd3d3fa5bda3008e3050ff..abe75b6ea274750940b2c65e39370f2070b288e5 100644 (file)
@@ -162,7 +162,7 @@ AudioDiskstream::non_realtime_input_change ()
                        return;
                }
 
-               {
+                if (input_change_pending.type == IOChange::ConfigurationChanged) {
                        RCUWriter<ChannelList> writer (channels);
                        boost::shared_ptr<ChannelList> c = writer.get_copy();
 
@@ -175,9 +175,11 @@ AudioDiskstream::non_realtime_input_change ()
                        }
                }
 
-               get_input_sources ();
-               set_capture_offset ();
-               set_align_style_from_io ();
+                if (input_change_pending.type & IOChange::ConnectionsChanged) {
+                        get_input_sources ();
+                        set_capture_offset ();
+                        set_align_style_from_io ();
+                }
 
                input_change_pending = IOChange::NoChange;
 
@@ -223,20 +225,13 @@ AudioDiskstream::get_input_sources ()
 
                connections.clear ();
 
-               cerr << "Getting Nth connection from io " << n << " = " << _io->nth(n) << endl;
-
                if (_io->nth (n)->get_connections (connections) == 0) {
-
-                       cerr << "\tThere were NO connections, apparently ...\n";
-                       if ((*chan)->source) {
+                       if (!(*chan)->source.name.empty()) {
                                // _source->disable_metering ();
                        }
-
-                       (*chan)->source = 0;
-
+                       (*chan)->source.name = string();
                } else {
-                       cerr << "\tThere were some connections, apparently ... to " << connections[0] << endl;
-                       (*chan)->source = dynamic_cast<AudioPort*>(_session.engine().get_port_by_name (connections[0]) );
+                       (*chan)->source.name = connections[0];
                }
        }
 }
@@ -1681,9 +1676,7 @@ AudioDiskstream::engage_record_enable ()
        if (Config->get_monitoring_model() == HardwareMonitoring) {
 
                for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
-                       if ((*chan)->source) {
-                               (*chan)->source->ensure_monitor_input (!(_session.config.get_auto_input() && rolling));
-                       }
+                        (*chan)->source.ensure_monitor_input (!(_session.config.get_auto_input() && rolling));
                        capturing_sources.push_back ((*chan)->write_source);
                        (*chan)->write_source->mark_streaming_write_started ();
                }
@@ -1705,9 +1698,7 @@ AudioDiskstream::disengage_record_enable ()
        boost::shared_ptr<ChannelList> c = channels.reader();
        if (Config->get_monitoring_model() == HardwareMonitoring) {
                for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
-                       if ((*chan)->source) {
-                               (*chan)->source->ensure_monitor_input (false);
-                       }
+                        (*chan)->source.ensure_monitor_input (false);
                }
        }
        capturing_sources.clear ();
@@ -1992,10 +1983,7 @@ AudioDiskstream::monitor_input (bool yn)
        boost::shared_ptr<ChannelList> c = channels.reader();
 
        for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
-
-               if ((*chan)->source) {
-                       (*chan)->source->ensure_monitor_input (yn);
-               }
+                (*chan)->source.ensure_monitor_input (yn);
        }
 }
 
@@ -2016,17 +2004,12 @@ AudioDiskstream::set_align_style_from_io ()
 
        boost::shared_ptr<ChannelList> c = channels.reader();
 
-       cerr << "Checking " << c->size() << " for physical connections\n";
-
        for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
-               cerr << "Channel connected via " << (*chan)->source << endl;
-               if ((*chan)->source && (*chan)->source->flags() & JackPortIsPhysical) {
-                       cerr << "\tchannel has physical connection to " << (*chan)->source->name() << endl;
+               if ((*chan)->source.is_physical ()) {
                        have_physical = true;
                        break;
                }
        }
-       cerr << "\tphysical? " << have_physical << endl;
 
        if (have_physical) {
                set_align_style (ExistingMaterial);
@@ -2312,10 +2295,29 @@ AudioDiskstream::adjust_capture_buffering ()
        }
 }
 
+bool
+AudioDiskstream::ChannelSource::is_physical () const
+{
+        if (name.empty()) {
+                return false;
+        }
+
+        return AudioEngine::instance()->port_is_physical (name);
+}
+
+void
+AudioDiskstream::ChannelSource::ensure_monitor_input (bool yn) const
+{
+        if (name.empty()) {
+                return;
+        }
+
+        return AudioEngine::instance()->ensure_monitor_input (name, yn);
+}
+
 AudioDiskstream::ChannelInfo::ChannelInfo (framecnt_t playback_bufsize, framecnt_t capture_bufsize, framecnt_t speed_size, framecnt_t wrap_size)
 {
        peak_power = 0.0f;
-       source = 0;
        current_capture_buffer = 0;
        current_playback_buffer = 0;
        curr_capture_cnt = 0;
index ffa55e453dce87365b1c6ef2b7e2b0ff3d6b274e..6067da55b7a53b76dfbfe04d7db3053ed785c5ef 100644 (file)
@@ -1010,7 +1010,7 @@ AudioEngine::get_port_by_name (const string& portname)
                }
        }
 
-       return 0;
+        return 0;
 }
 
 const char **
@@ -1484,3 +1484,31 @@ AudioEngine::_start_process_thread (void* arg)
 
         return 0;
 }
+
+bool 
+AudioEngine::port_is_physical (const std::string& portname) const
+{
+        GET_PRIVATE_JACK_POINTER_RET(_jack, false);
+
+        jack_port_t *port = jack_port_by_name (_priv_jack, portname.c_str());
+
+        if (!port) {
+                return false;
+        }
+        
+        return jack_port_flags (port) & JackPortIsPhysical;
+}
+
+void 
+AudioEngine::ensure_monitor_input (const std::string& portname, bool yn) const
+{
+        GET_PRIVATE_JACK_POINTER(_jack);
+
+        jack_port_t *port = jack_port_by_name (_priv_jack, portname.c_str());
+
+        if (!port) {
+                return;
+        }
+
+        jack_port_request_monitor (port, yn);
+}
index ae4a8ada3edb57872864e1024a93bfc90f55add9..affda7b56af41aad06e21ccbcb25a6ef04562ede 100644 (file)
@@ -180,9 +180,8 @@ Diskstream::set_track (Track* t)
        ic_connection.disconnect();
        _io->changed.connect_same_thread (ic_connection, boost::bind (&Diskstream::handle_input_change, this, _1, _2));
 
-       input_change_pending = IOChange::ConfigurationChanged;
+       input_change_pending.type = IOChange::Type (IOChange::ConfigurationChanged|IOChange::ConnectionsChanged);
        non_realtime_input_change ();
-       set_align_style_from_io ();
 
        _track->Destroyed.connect_same_thread (*this, boost::bind (&Diskstream::route_going_away, this));
 }
@@ -192,7 +191,14 @@ Diskstream::handle_input_change (IOChange change, void * /*src*/)
 {
        Glib::Mutex::Lock lm (state_lock);
 
-        if (change.type & IOChange::ConfigurationChanged) {
+        if (change.type & (IOChange::ConfigurationChanged|IOChange::ConnectionsChanged)) {
+
+                /* rather than handle this here on a DS-by-DS basis we defer to the
+                   session transport/butler thread, and let it tackle
+                   as many diskstreams as need it in one shot. this avoids many repeated
+                   takings of the audioengine process lock.
+                */
+
                 if (!(input_change_pending.type & change.type)) {
                         input_change_pending.type = IOChange::Type (input_change_pending.type | change.type);
                         _session.request_input_change_handling ();
index 875fca7fa0f7d7a23a0c2c70f4131fd2f0811789..27f8ca819dcdca6889dc87082c364681545ad3c4 100644 (file)
@@ -224,7 +224,6 @@ IO::connect (Port* our_port, string other_port, void* src)
                        return -1;
                }
        }
-
        changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */
        _session.set_dirty ();
        return 0;
@@ -912,7 +911,7 @@ IO::make_connections (const XMLNode& node, int version, bool in)
                                        }
                                         
                                        if (prop) {
-                                               p->connect (prop->value());
+                                                connect (p, prop->value(), this);
                                        }
                                }
                        } 
index 3d2336da3abb7642722729d23f44d8577476c56a..3889d79dfb4049ec11ed2d61c8fbd7b83dedd174 100644 (file)
@@ -164,14 +164,17 @@ MidiDiskstream::non_realtime_input_change ()
 
                if (input_change_pending.type & IOChange::ConfigurationChanged) {
                        if (_io->n_ports().n_midi() != _n_channels.n_midi()) {
-                               error << "Can not feed IO " << _io->n_ports()
-                                       << " with diskstream " << _n_channels << endl;
+                               error << "Can not feed " << _io->n_ports() 
+                                      << " ports to " << _n_channels << " channels" 
+                                      << endmsg;
                        }
                }
 
-               get_input_sources ();
-               set_capture_offset ();
-               set_align_style_from_io ();
+                if (input_change_pending.type & IOChange::ConnectionsChanged) {
+                        get_input_sources ();
+                        set_capture_offset ();
+                        set_align_style_from_io ();
+                }
 
                input_change_pending.type = IOChange::NoChange;
 
index bd3004ba02f0c70262dbc15b77f9c2f682c5195b..c66995bb3c927a60b5594a974500d9d0fb2e301b 100644 (file)
@@ -341,11 +341,11 @@ Port::get_connected_latency_range (jack_latency_range_t& range, bool playback) c
                range.min = ~((jack_nframes_t) 0);
                range.max = 0;
 
+                DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: %2 connections to check for latency range\n", name(), connections.size()));
+
                for (vector<string>::const_iterator c = connections.begin();
                     c != connections.end(); ++c) {
 
-                       cerr << "Connection between " << name() << " and " << *c << endl;
-
                        jack_port_t* remote_port = jack_port_by_name (_engine->jack(), (*c).c_str());
                        jack_latency_range_t lr;
 
@@ -359,15 +359,16 @@ Port::get_connected_latency_range (jack_latency_range_t& range, bool playback) c
                                                     name(), *c, lr.min, lr.max));
                                range.min = min (range.min, lr.min);
                                range.max = max (range.max, lr.max);
-                       } else {
-                               cerr << "\t NO PORT BY NAME!\n";
                        }
                }
 
        } else {
+                DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: not connected to anything\n", name()));
                range.min = 0;
                range.max = 0;
        }
+
+        DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: final connected latency range [ %2 .. %3 ] \n", name(), range.min, range.max));
 }
 
 int
index d368198e22879bb55c9f5181213539efefefbd69..f5fd4a682cf17185e8d66d1d313eea1d774c3332 100644 (file)
@@ -137,8 +137,6 @@ Route::init ()
        _output.reset (new IO (_session, _name, IO::Output, _default_type));
 
        _input->changed.connect_same_thread (*this, boost::bind (&Route::input_change_handler, this, _1, _2));
-       _output->changed.connect_same_thread (*this, boost::bind (&Route::output_change_handler, this, _1, _2));
-
        _input->PortCountChanging.connect_same_thread (*this, boost::bind (&Route::input_port_count_changing, this, _1));
 
        /* add amp processor  */
@@ -2742,47 +2740,6 @@ Route::input_change_handler (IOChange change, void * /*src*/)
        }
 }
 
-/** Called with the process lock held if change contains ConfigurationChanged */
-void
-Route::output_change_handler (IOChange change, void * /*src*/)
-{
-       if ((change.type & IOChange::ConfigurationChanged)) {
-
-               /* XXX resize all listeners to match _main_outs? */
-
-               /* Auto-connect newly-created outputs, unless we're auto-connecting to master
-                  and we are master (as an auto-connect in this situation would cause a
-                  feedback loop)
-               */
-
-               AutoConnectOption ac = Config->get_output_auto_connect ();
-
-               if (ac == AutoConnectPhysical || (ac == AutoConnectMaster && !is_master ())) {
-
-                       ChanCount start = change.before;
-                       
-                       for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) {
-                               if (change.before.get(*i) < change.after.get(*i)) {
-                                       /* the existing ChanCounts don't matter for this call as they are only
-                                          to do with matching input and output indices, and we are only changing
-                                          outputs here.
-                                       */
-                                       ChanCount dummy;
-
-                                       /* only auto-connect the newly-created outputs, not the ones that were
-                                          already there
-                                       */
-                                       start.set (*i, start.get (*i) + 1);
-
-                                       _session.auto_connect_route (this, dummy, dummy, false, false, ChanCount(), change.before);
-                               }
-                       }
-               }
-
-               // configure_processors (0);
-       }
-}
-
 uint32_t
 Route::pans_required () const
 {
index f08f0589d3e04d3d0288dfc64020f1c01851eb7c..35aebf7effa08314c616438507fc53a4213eb919 100644 (file)
@@ -1399,9 +1399,9 @@ Session::find_route_name (string const & base, uint32_t& id, char* name, size_t
        return false;
 }
 
-/** Count the total ins and outs of all non-hidden routes in the session and return them in in and out */
+/** Count the total ins and outs of all non-hidden tracks in the session and return them in in and out */
 void
-Session::count_existing_route_channels (ChanCount& in, ChanCount& out)
+Session::count_existing_track_channels (ChanCount& in, ChanCount& out)
 {
        in  = ChanCount::ZERO;
        out = ChanCount::ZERO;
@@ -1409,9 +1409,11 @@ Session::count_existing_route_channels (ChanCount& in, ChanCount& out)
        boost::shared_ptr<RouteList> r = routes.reader ();
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               if (!(*i)->is_hidden()) {
-                       in  += (*i)->n_inputs();
-                       out += (*i)->n_outputs();
+                boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
+               if (tr && !tr->is_hidden()) {
+                        cerr << "Using track i/o counts for " << tr->name() << endl;
+                       in  += tr->n_inputs();
+                       out += tr->n_outputs();
                }
        }
 }
@@ -1511,6 +1513,7 @@ Session::auto_connect_route (Route* route, ChanCount& existing_inputs, ChanCount
                              bool with_lock, bool connect_inputs, ChanCount input_start, ChanCount output_start)
 {
        if (!IO::connecting_legal) {
+                cerr << "Auto-connect ignored because connecting it not legal\n";
                return;
        }
 
@@ -1528,14 +1531,16 @@ Session::auto_connect_route (Route* route, ChanCount& existing_inputs, ChanCount
           offset possible.
        */
 
-       cerr << "ACR: existing in = " << existing_inputs << " out = " << existing_outputs << endl;
+       cerr << "Auto-connect: existing in = " << existing_inputs << " out = " << existing_outputs << endl;
 
        const bool in_out_physical =
                (Config->get_input_auto_connect() & AutoConnectPhysical)
                && (Config->get_output_auto_connect() & AutoConnectPhysical)
                && connect_inputs;
 
-       const ChanCount in_offset = existing_inputs;
+       const ChanCount in_offset = in_out_physical
+               ? ChanCount::max(existing_inputs, existing_outputs)
+                : existing_inputs;
 
        const ChanCount out_offset = in_out_physical
                ? ChanCount::max(existing_inputs, existing_outputs)
@@ -1896,6 +1901,11 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
 void
 Session::add_routes (RouteList& new_routes, bool auto_connect, bool save)
 {
+        ChanCount existing_inputs;
+        ChanCount existing_outputs;
+        
+        count_existing_track_channels (existing_inputs, existing_outputs);
+
        {
                RCUWriter<RouteList> writer (routes);
                boost::shared_ptr<RouteList> r = writer.get_copy ();
@@ -1948,11 +1958,6 @@ Session::add_routes (RouteList& new_routes, bool auto_connect, bool save)
         
                if (auto_connect) {
 
-                       ChanCount existing_inputs;
-                       ChanCount existing_outputs;
-
-                       count_existing_route_channels (existing_inputs, existing_outputs);
-
                        auto_connect_route (r, existing_inputs, existing_outputs, true);
                }
        }
@@ -4160,25 +4165,23 @@ Session::update_latency (bool playback)
                max_latency = max (max_latency, (*i)->set_private_port_latencies (playback));
        }
 
+        /* because we latency compensate playback, our published playback latencies should
+           be the same for all output ports - all material played back by ardour has
+           the same latency, whether its caused by plugins or by latency compensation. since
+           these may differ from the values computed above, reset all playback port latencies
+           to the same value.
+        */
+
+        DEBUG_TRACE (DEBUG::Latency, string_compose ("Set public port latencies to %1\n", max_latency));
+        
+        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+                (*i)->set_public_port_latencies (max_latency, playback);
+        }
+                
        if (playback) {
 
                post_playback_latency ();
  
-               /* because we latency compensate playback, our published playback latencies should
-                  be the same for all output ports - all material played back by ardour has
-                  the same latency, whether its caused by plugins or by latency compensation. since
-                  these may differ from the values computed above, reset all playback port latencies
-                  to the same value.
-               */
-
-               DEBUG_TRACE (DEBUG::Latency, string_compose ("Set public port latencies to %1\n", max_latency));
-
-               for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-                       (*i)->set_public_port_latencies (max_latency, playback);
-               }
-                
-
-
        } else {
 
                post_capture_latency ();
@@ -4275,9 +4278,9 @@ Session::set_worst_capture_latency ()
 void
 Session::update_latency_compensation (bool force_whole_graph)
 {
-       bool update_jack = false;
+       bool some_track_latency_changed = false;
 
-       if (_state_of_the_state & Deletion) {
+       if (_state_of_the_state & (InitialConnecting|Deletion)) {
                return;
        }
 
@@ -4286,21 +4289,21 @@ Session::update_latency_compensation (bool force_whole_graph)
        _worst_track_latency = 0;
 
        boost::shared_ptr<RouteList> r = routes.reader ();
-
+        
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                if (!(*i)->is_hidden() && ((*i)->active())) {
                        framecnt_t tl;
                        if ((*i)->signal_latency () != (tl = (*i)->update_signal_latency ())) {
-                               update_jack = true;
+                               some_track_latency_changed = true;
                        }
                        _worst_track_latency = max (tl, _worst_track_latency); 
                }
        }
 
        DEBUG_TRACE (DEBUG::Latency, string_compose ("worst signal processing latency: %1 (changed ? %2)\n", _worst_track_latency,
-                                                    (update_jack ? "yes" : "no")));
+                                                    (some_track_latency_changed ? "yes" : "no")));
 
-       if (force_whole_graph || update_jack) {
+       if (force_whole_graph || some_track_latency_changed) {
                /* trigger a full recompute of latency numbers for the graph.
                   everything else that we need to do will be done in the latency
                   callback.
@@ -4309,8 +4312,6 @@ Session::update_latency_compensation (bool force_whole_graph)
                return; // everything else will be done in the latency callback
        } 
 
-        
-
        DEBUG_TRACE(DEBUG::Latency, "---------------------------- DONE update latency compensation\n\n")
 }
 
index 248172fcd9b71806c18213f3c05367dd4e903de9..3dc1f9e7b3393588e0ec010c9f1ee16481794b61 100644 (file)
@@ -226,7 +226,7 @@ Session::realtime_stop (bool abort, bool clear_state)
                        /* we rolled past the stop point to pick up data that had
                           not yet arrived. move back to where the stop occured.
                        */
-                       decrement_transport_position (current_block_size + (worst_playback_latency() - current_block_size));
+                       decrement_transport_position (current_block_size + (worst_input_latency() - current_block_size));
                } else {
                        decrement_transport_position (current_block_size);
                }
@@ -1047,7 +1047,7 @@ Session::stop_transport (bool abort, bool clear_state)
                return;
        }
 
-       if (actively_recording() && !(transport_sub_state & StopPendingCapture) && worst_playback_latency() > current_block_size) {
+       if (actively_recording() && !(transport_sub_state & StopPendingCapture) && worst_input_latency() > current_block_size) {
 
                boost::shared_ptr<RouteList> rl = routes.reader();
                for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
@@ -1075,7 +1075,6 @@ Session::stop_transport (bool abort, bool clear_state)
                return;
        }
 
-
        if ((transport_sub_state & PendingDeclickOut) == 0) {
 
                if (!(transport_sub_state & StopPendingCapture)) {