full compilation and linking (coding not finished, will not run)
[ardour.git] / libs / ardour / session.cc
index e98b1b687768a93a7c389cefa2e51dbdd20b08d9..e1634db536ed980a8ea424e16f80ff3a415c27f0 100644 (file)
@@ -119,6 +119,7 @@ PBD::Signal1<int,boost::shared_ptr<Playlist> > Session::AskAboutPlaylistDeletion
 PBD::Signal0<void> Session::Quit;
 PBD::Signal0<void> Session::FeedbackDetected;
 PBD::Signal0<void> Session::SuccessfulGraphSort;
+PBD::Signal2<void,std::string,std::string> Session::VersionMismatch;
 
 static void clean_up_session_event (SessionEvent* ev) { delete ev; }
 const SessionEvent::RTeventCallback Session::rt_cleanup (clean_up_session_event);
@@ -132,12 +133,14 @@ Session::Session (AudioEngine &eng,
        : _engine (eng)
        , _target_transport_speed (0.0)
        , _requested_return_frame (-1)
+       , _under_nsm_control (false)
        , _session_dir (new SessionDirectory(fullpath))
        , state_tree (0)
        , _state_of_the_state (Clean)
        , _butler (new Butler (*this))
        , _post_transport_work (0)
        , _send_timecode_update (false)
+       , ltc_enc_buf(0)
        , _all_route_group (new RouteGroup (*this, "all"))
        , routes (new RouteList)
        , _total_free_4k_blocks (0)
@@ -152,9 +155,7 @@ Session::Session (AudioEngine &eng,
        , _suspend_timecode_transmission (0)
 {
        _locations = new Locations (*this);
-#ifdef HAVE_LTC
        ltc_encoder = NULL;
-#endif
 
        if (how_many_dsp_threads () > 1) {
                /* For now, only create the graph if we are using >1 DSP threads, as
@@ -232,6 +233,10 @@ Session::destroy ()
 
        _state_of_the_state = StateOfTheState (CannotSave|Deletion);
 
+       /* disconnect from any and all signals that we are connected to */
+
+       drop_connections ();
+
        _engine.remove_session ();
 
        /* deregister all ports - there will be no process or any other
@@ -240,9 +245,7 @@ Session::destroy ()
 
        Port::PortDrop (); /* EMIT SIGNAL */
 
-#ifdef HAVE_LTC
        ltc_tx_cleanup();
-#endif
 
        /* clear history so that no references to objects are held any more */
 
@@ -343,8 +346,8 @@ Session::when_engine_running ()
 
        BootMessage (_("Set block size and sample rate"));
 
-       set_block_size (_engine.frames_per_cycle());
-       set_frame_rate (_engine.frame_rate());
+       set_block_size (_engine.samples_per_cycle());
+       set_frame_rate (_engine.sample_rate());
 
        BootMessage (_("Using configuration"));
 
@@ -1077,7 +1080,7 @@ Session::set_auto_loop_location (Location* location)
        }
 
        if (location->end() <= location->start()) {
-               error << _("Session: you can't use a mark for auto loop") << endmsg;
+               error << _("You cannot use this location for auto-loop because it has zero or negative length") << endmsg;
                return;
        }
 
@@ -1596,7 +1599,7 @@ Session::find_route_name (string const & base, uint32_t& id, char* name, size_t
                }
 
                ++id;
-
+               
        } while (id < (UINT_MAX-1));
 
        return false;
@@ -1613,7 +1616,7 @@ Session::count_existing_track_channels (ChanCount& in, ChanCount& out)
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
-               if (tr && !tr->is_hidden()) {
+               if (tr && !tr->is_auditioner()) {
                        in  += tr->n_inputs();
                        out += tr->n_outputs();
                }
@@ -1634,8 +1637,6 @@ Session::new_midi_track (const ChanCount& input, const ChanCount& output, boost:
        RouteList new_routes;
        list<boost::shared_ptr<MidiTrack> > ret;
 
-       cerr << "Adding MIDI track with in = " << input << " out = " << output << endl;
-
        bool const use_number = (how_many != 1) || name_template.empty () || name_template == _("MIDI");
 
        while (how_many) {
@@ -1694,7 +1695,7 @@ Session::new_midi_track (const ChanCount& input, const ChanCount& output, boost:
 
                catch (AudioEngine::PortRegistrationFailure& pfe) {
 
-                       error << string_compose (_("No more JACK ports are available. You will need to stop %1 and restart JACK with ports if you need this many tracks."), PROGRAM_NAME) << endmsg;
+                       error << string_compose (_("No more JACK ports are available. You will need to stop %1 and restart JACK with more ports if you need this many tracks."), PROGRAM_NAME) << endmsg;
                        goto failed;
                }
 
@@ -2008,6 +2009,8 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
                        bus->add_internal_return ();
 
                        ret.push_back (bus);
+                       
+                       ARDOUR::GUIIdle ();
                }
 
 
@@ -2035,12 +2038,13 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
 }
 
 RouteList
-Session::new_route_from_template (uint32_t how_many, const std::string& template_path)
+Session::new_route_from_template (uint32_t how_many, const std::string& template_path, const std::string& name_base)
 {
        RouteList ret;
        uint32_t control_id;
        XMLTree tree;
        uint32_t number = 0;
+       const uint32_t being_added = how_many;
 
        if (!tree.read (template_path.c_str())) {
                return ret;
@@ -2060,13 +2064,29 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
                node_copy.remove_property_recursively (X_("id"));
 
                try {
-                       string const route_name = node_copy.property(X_("name"))->value ();
-                       
-                       /* generate a new name by adding a number to the end of the template name */
                        char name[32];
-                       if (!find_route_name (route_name.c_str(), ++number, name, sizeof(name), true)) {
-                               fatal << _("Session: UINT_MAX routes? impossible!") << endmsg;
-                               /*NOTREACHED*/
+
+                       if (!name_base.empty()) {
+
+                               /* if we're adding more than one routes, force
+                                * all the names of the new routes to be
+                                * numbered, via the final parameter.
+                                */
+
+                               if (!find_route_name (name_base.c_str(), ++number, name, sizeof(name), (being_added > 1))) {
+                                       fatal << _("Session: UINT_MAX routes? impossible!") << endmsg;
+                                       /*NOTREACHDE*/
+                               }
+
+                       } else {
+
+                               string const route_name  = node_copy.property(X_("name"))->value ();
+                       
+                               /* generate a new name by adding a number to the end of the template name */
+                               if (!find_route_name (route_name.c_str(), ++number, name, sizeof(name), true)) {
+                                       fatal << _("Session: UINT_MAX routes? impossible!") << endmsg;
+                                       /*NOTREACHED*/
+                               }
                        }
 
                        /* set this name in the XML description that we are about to use */
@@ -2135,6 +2155,31 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
 
 void
 Session::add_routes (RouteList& new_routes, bool input_auto_connect, bool output_auto_connect, bool save)
+{
+       try {
+               PBD::Unwinder<bool> aip (_adding_routes_in_progress, true);
+               add_routes_inner (new_routes, input_auto_connect, output_auto_connect);
+
+       } catch (...) {
+               error << _("Adding new tracks/busses failed") << endmsg;
+       }
+
+       graph_reordered ();
+
+       update_latency (true);
+       update_latency (false);
+               
+       set_dirty();
+       
+       if (save) {
+               save_state (_current_snapshot_name);
+       }
+       
+       RouteAdded (new_routes); /* EMIT SIGNAL */
+}
+
+void
+Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool output_auto_connect)
 {
         ChanCount existing_inputs;
         ChanCount existing_outputs;
@@ -2191,6 +2236,7 @@ Session::add_routes (RouteList& new_routes, bool input_auto_connect, bool output
                        }
                }
 
+
                if (input_auto_connect || output_auto_connect) {
                        auto_connect_route (r, existing_inputs, existing_outputs, true, input_auto_connect);
                }
@@ -2199,9 +2245,9 @@ Session::add_routes (RouteList& new_routes, bool input_auto_connect, bool output
                   reasonable defaults because they also affect the remote control
                   ID in most situations.
                */
-               
+
                if (!r->has_order_key (EditorSort)) {
-                       if (r->is_hidden()) {
+                       if (r->is_auditioner()) {
                                /* use an arbitrarily high value */
                                r->set_order_key (EditorSort, UINT_MAX);
                                r->set_order_key (MixerSort, UINT_MAX);
@@ -2212,34 +2258,23 @@ Session::add_routes (RouteList& new_routes, bool input_auto_connect, bool output
                                order++;
                        }
                }
+
+               ARDOUR::GUIIdle ();
        }
 
        if (_monitor_out && IO::connecting_legal) {
-
-               {
-                       Glib::Threads::Mutex::Lock lm (_engine.process_lock());         
-                       
-                       for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
-                               if ((*x)->is_monitor()) {
-                                       /* relax */
-                               } else if ((*x)->is_master()) {
+               Glib::Threads::Mutex::Lock lm (_engine.process_lock());         
+               
+               for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
+                       if ((*x)->is_monitor()) {
+                               /* relax */
+                       } else if ((*x)->is_master()) {
                                        /* relax */
-                               } else {
-                                       (*x)->enable_monitor_send ();
-                               }
+                       } else {
+                               (*x)->enable_monitor_send ();
                        }
                }
-
-               resort_routes ();
-       }
-
-       set_dirty();
-
-       if (save) {
-               save_state (_current_snapshot_name);
        }
-
-       RouteAdded (new_routes); /* EMIT SIGNAL */
 }
 
 void
@@ -2437,7 +2472,7 @@ Session::route_listen_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
                        /* new listen: disable all other listen */
                        boost::shared_ptr<RouteList> r = routes.reader ();
                        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-                               if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_hidden()) {
+                               if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner()) {
                                        continue;
                                }
                                (*i)->set_listen (false, this);
@@ -2519,7 +2554,7 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
                /* new solo: disable all other solos, but not the group if its solo-enabled */
 
                for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-                       if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_hidden() ||
+                       if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner() ||
                            (leave_group_alone && ((*i)->route_group() == rg))) {
                                continue;
                        }
@@ -2539,7 +2574,7 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
                bool via_sends_only;
                bool in_signal_flow;
 
-               if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_hidden() ||
+               if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner() ||
                    (leave_group_alone && ((*i)->route_group() == rg))) {
                        continue;
                }
@@ -2549,14 +2584,17 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
                DEBUG_TRACE (DEBUG::Solo, string_compose ("check feed from %1\n", (*i)->name()));
                
                if ((*i)->feeds (route, &via_sends_only)) {
+                       DEBUG_TRACE (DEBUG::Solo, string_compose ("\tthere is a feed from %1\n", (*i)->name()));
                        if (!via_sends_only) {
                                if (!route->soloed_by_others_upstream()) {
                                        (*i)->mod_solo_by_others_downstream (delta);
                                }
+                       } else {
+                               DEBUG_TRACE (DEBUG::Solo, string_compose ("\tthere is a send-only feed from %1\n", (*i)->name()));
                        }
                        in_signal_flow = true;
                } else {
-                       DEBUG_TRACE (DEBUG::Solo, "\tno feed from\n");
+                       DEBUG_TRACE (DEBUG::Solo, string_compose ("\tno feed from %1\n", (*i)->name()));
                }
                
                DEBUG_TRACE (DEBUG::Solo, string_compose ("check feed to %1\n", (*i)->name()));
@@ -2577,7 +2615,11 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
                                if (!route->soloed_by_others_downstream()) {
                                        DEBUG_TRACE (DEBUG::Solo, string_compose ("\tmod %1 by %2\n", (*i)->name(), delta));
                                        (*i)->mod_solo_by_others_upstream (delta);
+                               } else {
+                                       DEBUG_TRACE (DEBUG::Solo, "\talready soloed by others downstream\n");
                                }
+                       } else {
+                               DEBUG_TRACE (DEBUG::Solo, string_compose ("\tfeed to %1 ignored, sends-only\n", (*i)->name()));
                        }
                        in_signal_flow = true;
                } else {
@@ -2599,7 +2641,7 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
        */
 
        for (RouteList::iterator i = uninvolved.begin(); i != uninvolved.end(); ++i) {
-               DEBUG_TRACE (DEBUG::Solo, string_compose ("mute change for %1\n", (*i)->name()));
+               DEBUG_TRACE (DEBUG::Solo, string_compose ("mute change for %1, which neither feeds or is fed by %2\n", (*i)->name(), route->name()));
                (*i)->mute_changed (this);
        }
 
@@ -2621,11 +2663,11 @@ Session::update_route_solo_state (boost::shared_ptr<RouteList> r)
        }
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               if (!(*i)->is_master() && !(*i)->is_monitor() && !(*i)->is_hidden() && (*i)->self_soloed()) {
+               if (!(*i)->is_master() && !(*i)->is_monitor() && !(*i)->is_auditioner() && (*i)->self_soloed()) {
                        something_soloed = true;
                }
 
-               if (!(*i)->is_hidden() && (*i)->listening_via_monitor()) {
+               if (!(*i)->is_auditioner() && (*i)->listening_via_monitor()) {
                        if (Config->get_solo_control_is_listen_control()) {
                                listeners++;
                        } else {
@@ -2649,6 +2691,9 @@ Session::update_route_solo_state (boost::shared_ptr<RouteList> r)
                _solo_isolated_cnt = isolated;
                IsolatedChanged (); /* EMIT SIGNAL */
        }
+
+       DEBUG_TRACE (DEBUG::Solo, string_compose ("solo state updated by session, soloed? %1 listeners %2 isolated %3\n",
+                                                 something_soloed, listeners, isolated));
 }
 
 boost::shared_ptr<RouteList>
@@ -3355,7 +3400,7 @@ Session::create_audio_source_for_session (size_t n_chans, string const & n, uint
        const string path    = new_source_path_from_name(DataType::AUDIO, name);
 
        return boost::dynamic_pointer_cast<AudioFileSource> (
-               SourceFactory::createWritable (DataType::AUDIO, *this, path, string(), destructive, frame_rate()));
+               SourceFactory::createWritable (DataType::AUDIO, *this, path, destructive, frame_rate()));
 }
 
 /** Return a unique name based on \a base for a new internal MIDI source */
@@ -3431,7 +3476,7 @@ Session::create_midi_source_for_session (Track* track, string const & n)
 
        return boost::dynamic_pointer_cast<SMFSource> (
                SourceFactory::createWritable (
-                       DataType::MIDI, *this, path, string(), false, frame_rate()));
+                       DataType::MIDI, *this, path, false, frame_rate()));
 }
 
 
@@ -3541,7 +3586,7 @@ Session::graph_reordered ()
           from a set_state() call or creating new tracks. Ditto for deletion.
        */
 
-       if (_state_of_the_state & (InitialConnecting|Deletion)) {
+       if ((_state_of_the_state & (InitialConnecting|Deletion)) || _adding_routes_in_progress) {
                return;
        }
 
@@ -3983,7 +4028,7 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
 
                try {
                        fsource = boost::dynamic_pointer_cast<AudioFileSource> (
-                               SourceFactory::createWritable (DataType::AUDIO, *this, buf, string(), false, frame_rate()));
+                               SourceFactory::createWritable (DataType::AUDIO, *this, buf, false, frame_rate()));
                }
 
                catch (failed_constructor& err) {
@@ -4176,7 +4221,7 @@ Session::add_automation_list(AutomationList *al)
 bool
 Session::have_rec_enabled_track () const
 {
-       return g_atomic_int_get (&_have_rec_enabled_track) == 1;
+       return g_atomic_int_get (const_cast<gint*>(&_have_rec_enabled_track)) == 1;
 }
 
 /** Update the state of our rec-enabled tracks flag */
@@ -4521,7 +4566,7 @@ Session::update_latency (bool playback)
 {
        DEBUG_TRACE (DEBUG::Latency, string_compose ("JACK latency callback: %1\n", (playback ? "PLAYBACK" : "CAPTURE")));
 
-       if (_state_of_the_state & (InitialConnecting|Deletion)) {
+       if ((_state_of_the_state & (InitialConnecting|Deletion)) || _adding_routes_in_progress) {
                return;
        }
 
@@ -4577,7 +4622,7 @@ Session::post_playback_latency ()
        boost::shared_ptr<RouteList> r = routes.reader ();
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               if (!(*i)->is_hidden() && ((*i)->active())) {
+               if (!(*i)->is_auditioner() && ((*i)->active())) {
                        _worst_track_latency = max (_worst_track_latency, (*i)->update_signal_latency ());
                }
        }
@@ -4683,7 +4728,7 @@ Session::update_latency_compensation (bool force_whole_graph)
        boost::shared_ptr<RouteList> r = routes.reader ();
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               if (!(*i)->is_hidden() && ((*i)->active())) {
+               if (!(*i)->is_auditioner() && ((*i)->active())) {
                        framecnt_t tl;
                        if ((*i)->signal_latency () != (tl = (*i)->update_signal_latency ())) {
                                some_track_latency_changed = true;