Merged with trunk R1393.
[ardour.git] / libs / ardour / session.cc
1 /*
2     Copyright (C) 1999-2004 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18     $Id$
19 */
20
21 #include <algorithm>
22 #include <string>
23 #include <vector>
24 #include <sstream>
25 #include <fstream>
26 #include <cstdio> /* sprintf(3) ... grrr */
27 #include <cmath>
28 #include <cerrno>
29 #include <unistd.h>
30 #include <limits.h>
31
32 #include <sigc++/bind.h>
33 #include <sigc++/retype.h>
34
35 #include <glibmm/thread.h>
36 #include <glibmm/miscutils.h>
37
38 #include <pbd/error.h>
39 #include <glibmm/thread.h>
40 #include <pbd/pathscanner.h>
41 #include <pbd/stl_delete.h>
42 #include <pbd/basename.h>
43 #include <pbd/stacktrace.h>
44
45 #include <ardour/audioengine.h>
46 #include <ardour/configuration.h>
47 #include <ardour/session.h>
48 #include <ardour/utils.h>
49 #include <ardour/audio_diskstream.h>
50 #include <ardour/audioplaylist.h>
51 #include <ardour/audioregion.h>
52 #include <ardour/audiofilesource.h>
53 #include <ardour/midi_diskstream.h>
54 #include <ardour/midi_playlist.h>
55 #include <ardour/midi_region.h>
56 #include <ardour/smf_source.h>
57 #include <ardour/destructive_filesource.h>
58 #include <ardour/auditioner.h>
59 #include <ardour/recent_sessions.h>
60 #include <ardour/redirect.h>
61 #include <ardour/send.h>
62 #include <ardour/insert.h>
63 #include <ardour/connection.h>
64 #include <ardour/slave.h>
65 #include <ardour/tempo.h>
66 #include <ardour/audio_track.h>
67 #include <ardour/midi_track.h>
68 #include <ardour/cycle_timer.h>
69 #include <ardour/named_selection.h>
70 #include <ardour/crossfade.h>
71 #include <ardour/playlist.h>
72 #include <ardour/click.h>
73 #include <ardour/data_type.h>
74 #include <ardour/buffer_set.h>
75 #include <ardour/source_factory.h>
76 #include <ardour/region_factory.h>
77
78 #ifdef HAVE_LIBLO
79 #include <ardour/osc.h>
80 #endif
81
82 #include "i18n.h"
83
84 using namespace std;
85 using namespace ARDOUR;
86 using namespace PBD;
87 using boost::shared_ptr;
88
89 const char* Session::_template_suffix = X_(".template");
90 const char* Session::_statefile_suffix = X_(".ardour");
91 const char* Session::_pending_suffix = X_(".pending");
92 const char* Session::old_sound_dir_name = X_("sounds");
93 const char* Session::sound_dir_name = X_("audiofiles");
94 const char* Session::peak_dir_name = X_("peaks");
95 const char* Session::dead_sound_dir_name = X_("dead_sounds");
96 const char* Session::interchange_dir_name = X_("interchange");
97
98 Session::compute_peak_t                         Session::compute_peak                   = 0;
99 Session::apply_gain_to_buffer_t         Session::apply_gain_to_buffer   = 0;
100 Session::mix_buffers_with_gain_t        Session::mix_buffers_with_gain  = 0;
101 Session::mix_buffers_no_gain_t          Session::mix_buffers_no_gain    = 0;
102
103 sigc::signal<int> Session::AskAboutPendingState;
104 sigc::signal<void> Session::SendFeedback;
105
106 sigc::signal<void> Session::SMPTEOffsetChanged;
107 sigc::signal<void> Session::StartTimeChanged;
108 sigc::signal<void> Session::EndTimeChanged;
109
110 int
111 Session::find_session (string str, string& path, string& snapshot, bool& isnew)
112 {
113         struct stat statbuf;
114         char buf[PATH_MAX+1];
115
116         isnew = false;
117
118         if (!realpath (str.c_str(), buf) && (errno != ENOENT && errno != ENOTDIR)) {
119                 error << string_compose (_("Could not resolve path: %1 (%2)"), buf, strerror(errno)) << endmsg;
120                 return -1;
121         }
122
123         str = buf;
124         
125         /* check to see if it exists, and what it is */
126
127         if (stat (str.c_str(), &statbuf)) {
128                 if (errno == ENOENT) {
129                         isnew = true;
130                 } else {
131                         error << string_compose (_("cannot check session path %1 (%2)"), str, strerror (errno))
132                               << endmsg;
133                         return -1;
134                 }
135         }
136
137         if (!isnew) {
138
139                 /* it exists, so it must either be the name
140                    of the directory, or the name of the statefile
141                    within it.
142                 */
143
144                 if (S_ISDIR (statbuf.st_mode)) {
145
146                         string::size_type slash = str.find_last_of ('/');
147                 
148                         if (slash == string::npos) {
149                                 
150                                 /* a subdirectory of cwd, so statefile should be ... */
151
152                                 string tmp;
153                                 tmp = str;
154                                 tmp += '/';
155                                 tmp += str;
156                                 tmp += _statefile_suffix;
157
158                                 /* is it there ? */
159                                 
160                                 if (stat (tmp.c_str(), &statbuf)) {
161                                         error << string_compose (_("cannot check statefile %1 (%2)"), tmp, strerror (errno))
162                                               << endmsg;
163                                         return -1;
164                                 }
165
166                                 path = str;
167                                 snapshot = str;
168
169                         } else {
170
171                                 /* some directory someplace in the filesystem.
172                                    the snapshot name is the directory name
173                                    itself.
174                                 */
175
176                                 path = str;
177                                 snapshot = str.substr (slash+1);
178                                         
179                         }
180
181                 } else if (S_ISREG (statbuf.st_mode)) {
182                         
183                         string::size_type slash = str.find_last_of ('/');
184                         string::size_type suffix;
185
186                         /* remove the suffix */
187                         
188                         if (slash != string::npos) {
189                                 snapshot = str.substr (slash+1);
190                         } else {
191                                 snapshot = str;
192                         }
193
194                         suffix = snapshot.find (_statefile_suffix);
195                         
196                         if (suffix == string::npos) {
197                                 error << string_compose (_("%1 is not an Ardour snapshot file"), str) << endmsg;
198                                 return -1;
199                         }
200
201                         /* remove suffix */
202
203                         snapshot = snapshot.substr (0, suffix);
204                         
205                         if (slash == string::npos) {
206                                 
207                                 /* we must be in the directory where the 
208                                    statefile lives. get it using cwd().
209                                 */
210
211                                 char cwd[PATH_MAX+1];
212
213                                 if (getcwd (cwd, sizeof (cwd)) == 0) {
214                                         error << string_compose (_("cannot determine current working directory (%1)"), strerror (errno))
215                                               << endmsg;
216                                         return -1;
217                                 }
218
219                                 path = cwd;
220
221                         } else {
222
223                                 /* full path to the statefile */
224
225                                 path = str.substr (0, slash);
226                         }
227                                 
228                 } else {
229
230                         /* what type of file is it? */
231                         error << string_compose (_("unknown file type for session %1"), str) << endmsg;
232                         return -1;
233                 }
234
235         } else {
236
237                 /* its the name of a new directory. get the name
238                    as "dirname" does.
239                 */
240
241                 string::size_type slash = str.find_last_of ('/');
242
243                 if (slash == string::npos) {
244                         
245                         /* no slash, just use the name, but clean it up */
246                         
247                         path = legalize_for_path (str);
248                         snapshot = path;
249                         
250                 } else {
251                         
252                         path = str;
253                         snapshot = str.substr (slash+1);
254                 }
255         }
256
257         return 0;
258 }
259
260 Session::Session (AudioEngine &eng,
261                   string fullpath,
262                   string snapshot_name,
263                   string* mix_template)
264
265         : _engine (eng),
266           _scratch_buffers(new BufferSet()),
267           _silent_buffers(new BufferSet()),
268           _send_buffers(new BufferSet()),
269           _mmc_port (default_mmc_port),
270           _mtc_port (default_mtc_port),
271           _midi_port (default_midi_port),
272           pending_events (2048),
273           //midi_requests (128), // the size of this should match the midi request pool size
274           _send_smpte_update (false),
275           diskstreams (new DiskstreamList),
276           routes (new RouteList),
277           auditioner ((Auditioner*) 0),
278           _click_io ((IO*) 0),
279           main_outs (0)
280 {
281         bool new_session;
282
283         cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << " (1)" << endl;
284
285         n_physical_outputs = _engine.n_physical_outputs();
286         n_physical_inputs =  _engine.n_physical_inputs();
287
288         first_stage_init (fullpath, snapshot_name);
289         
290         new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
291         if (new_session) {
292                 if (create (new_session, mix_template, compute_initial_length())) {
293                         cerr << "create failed\n";
294                         destroy ();
295                         throw failed_constructor ();
296                 }
297         }
298         
299         if (second_stage_init (new_session)) {
300                 destroy ();
301                 throw failed_constructor ();
302         }
303         
304         store_recent_sessions(_name, _path);
305         
306         bool was_dirty = dirty();
307
308         _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
309
310         Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed));
311
312         if (was_dirty) {
313                 DirtyChanged (); /* EMIT SIGNAL */
314         }
315 }
316
317 Session::Session (AudioEngine &eng,
318                   string fullpath,
319                   string snapshot_name,
320                   AutoConnectOption input_ac,
321                   AutoConnectOption output_ac,
322                   uint32_t control_out_channels,
323                   uint32_t master_out_channels,
324                   uint32_t requested_physical_in,
325                   uint32_t requested_physical_out,
326                   nframes_t initial_length)
327
328         : _engine (eng),
329           _scratch_buffers(new BufferSet()),
330           _silent_buffers(new BufferSet()),
331           _send_buffers(new BufferSet()),
332           _mmc_port (default_mmc_port),
333           _mtc_port (default_mtc_port),
334           _midi_port (default_midi_port),
335           pending_events (2048),
336           //midi_requests (16),
337           _send_smpte_update (false),
338           diskstreams (new DiskstreamList),
339           routes (new RouteList),
340           main_outs (0)
341
342 {
343         bool new_session;
344
345         cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << " (2)" << endl;
346
347         n_physical_outputs = _engine.n_physical_outputs();
348         n_physical_inputs = _engine.n_physical_inputs();
349
350         if (n_physical_inputs) {
351                 n_physical_inputs = max (requested_physical_in, n_physical_inputs);
352         }
353
354         if (n_physical_outputs) {
355                 n_physical_outputs = max (requested_physical_out, n_physical_outputs);
356         }
357
358         first_stage_init (fullpath, snapshot_name);
359
360         new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
361
362         if (new_session) {
363                 if (create (new_session, 0, initial_length)) {
364                         destroy ();
365                         throw failed_constructor ();
366                 }
367         }
368
369         {
370                 /* set up Master Out and Control Out if necessary */
371                 
372                 RouteList rl;
373                 int control_id = 1;
374                 
375                 if (control_out_channels) {
376                         shared_ptr<Route> r (new Route (*this, _("monitor"), -1, control_out_channels, -1, control_out_channels, Route::ControlOut));
377                         r->set_remote_control_id (control_id++);
378                         
379                         rl.push_back (r);
380                 }
381                 
382                 if (master_out_channels) {
383                         shared_ptr<Route> r (new Route (*this, _("master"), -1, master_out_channels, -1, master_out_channels, Route::MasterOut));
384                         r->set_remote_control_id (control_id);
385                          
386                         rl.push_back (r);
387                 } else {
388                         /* prohibit auto-connect to master, because there isn't one */
389                         output_ac = AutoConnectOption (output_ac & ~AutoConnectMaster);
390                 }
391                 
392                 if (!rl.empty()) {
393                         add_routes (rl);
394                 }
395                 
396         }
397
398         Config->set_input_auto_connect (input_ac);
399         Config->set_output_auto_connect (output_ac);
400
401         if (second_stage_init (new_session)) {
402                 destroy ();
403                 throw failed_constructor ();
404         }
405         
406         store_recent_sessions(_name, _path);
407         
408         bool was_dirty = dirty ();
409
410         _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
411
412         Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed));
413
414         if (was_dirty) {
415                 DirtyChanged (); /* EMIT SIGNAL */
416         }
417 }
418
419 Session::~Session ()
420 {
421         destroy ();
422 }
423
424 void
425 Session::destroy ()
426 {
427         /* if we got to here, leaving pending capture state around
428            is a mistake.
429         */
430
431         remove_pending_capture_state ();
432
433         _state_of_the_state = StateOfTheState (CannotSave|Deletion);
434         _engine.remove_session ();
435
436         GoingAway (); /* EMIT SIGNAL */
437         
438         /* do this */
439
440         notify_callbacks ();
441
442         /* clear history so that no references to objects are held any more */
443
444         _history.clear ();
445
446         /* clear state tree so that no references to objects are held any more */
447         
448         if (state_tree) {
449                 delete state_tree;
450         }
451
452         terminate_butler_thread ();
453         //terminate_midi_thread ();
454         
455         if (click_data && click_data != default_click) {
456                 delete [] click_data;
457         }
458
459         if (click_emphasis_data && click_emphasis_data != default_click_emphasis) {
460                 delete [] click_emphasis_data;
461         }
462
463         clear_clicks ();
464
465         delete _scratch_buffers;
466         delete _silent_buffers;
467         delete _send_buffers;
468
469         AudioDiskstream::free_working_buffers();
470         
471 #undef TRACK_DESTRUCTION
472 #ifdef TRACK_DESTRUCTION
473         cerr << "delete named selections\n";
474 #endif /* TRACK_DESTRUCTION */
475         for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ) {
476                 NamedSelectionList::iterator tmp;
477
478                 tmp = i;
479                 ++tmp;
480
481                 delete *i;
482                 i = tmp;
483         }
484
485 #ifdef TRACK_DESTRUCTION
486         cerr << "delete playlists\n";
487 #endif /* TRACK_DESTRUCTION */
488         for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ) {
489                 PlaylistList::iterator tmp;
490
491                 tmp = i;
492                 ++tmp;
493
494                 (*i)->drop_references ();
495                 
496                 i = tmp;
497         }
498         
499         for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ) {
500                 PlaylistList::iterator tmp;
501
502                 tmp = i;
503                 ++tmp;
504
505                 (*i)->drop_references ();
506                 
507                 i = tmp;
508         }
509         
510         playlists.clear ();
511         unused_playlists.clear ();
512
513 #ifdef TRACK_DESTRUCTION
514         cerr << "delete regions\n";
515 #endif /* TRACK_DESTRUCTION */
516         
517         for (RegionList::iterator i = regions.begin(); i != regions.end(); ) {
518                 RegionList::iterator tmp;
519
520                 tmp = i;
521                 ++tmp;
522
523                 cerr << "dropping refs on a region (" << i->second->name() << " @ " << i->second << ") with UC = " << i->second.use_count() << endl;
524                 i->second->drop_references ();
525                 cerr << "AFTER: UC = " << i->second.use_count() << endl;
526
527                 i = tmp;
528         }
529
530         regions.clear ();
531
532 #ifdef TRACK_DESTRUCTION
533         cerr << "delete routes\n";
534 #endif /* TRACK_DESTRUCTION */
535         {
536                 RCUWriter<RouteList> writer (routes);
537                 boost::shared_ptr<RouteList> r = writer.get_copy ();
538                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
539                         (*i)->drop_references ();
540                 }
541                 r->clear ();
542                 /* writer goes out of scope and updates master */
543         }
544
545         routes.flush ();
546
547 #ifdef TRACK_DESTRUCTION
548         cerr << "delete diskstreams\n";
549 #endif /* TRACK_DESTRUCTION */
550        {
551                RCUWriter<DiskstreamList> dwriter (diskstreams);
552                boost::shared_ptr<DiskstreamList> dsl = dwriter.get_copy();
553                for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
554                        (*i)->drop_references ();
555                }
556                dsl->clear ();
557        }
558        diskstreams.flush ();
559
560 #ifdef TRACK_DESTRUCTION
561         cerr << "delete audio sources\n";
562 #endif /* TRACK_DESTRUCTION */
563         for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
564                 SourceMap::iterator tmp;
565
566                 tmp = i;
567                 ++tmp;
568
569                 i->second->drop_references ();
570
571                 i = tmp;
572         }
573
574         sources.clear ();
575
576 #ifdef TRACK_DESTRUCTION
577         cerr << "delete mix groups\n";
578 #endif /* TRACK_DESTRUCTION */
579         for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ) {
580                 list<RouteGroup*>::iterator tmp;
581
582                 tmp = i;
583                 ++tmp;
584
585                 delete *i;
586
587                 i = tmp;
588         }
589
590 #ifdef TRACK_DESTRUCTION
591         cerr << "delete edit groups\n";
592 #endif /* TRACK_DESTRUCTION */
593         for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ) {
594                 list<RouteGroup*>::iterator tmp;
595                 
596                 tmp = i;
597                 ++tmp;
598
599                 delete *i;
600
601                 i = tmp;
602         }
603         
604 #ifdef TRACK_DESTRUCTION
605         cerr << "delete connections\n";
606 #endif /* TRACK_DESTRUCTION */
607         for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ) {
608                 ConnectionList::iterator tmp;
609
610                 tmp = i;
611                 ++tmp;
612
613                 delete *i;
614
615                 i = tmp;
616         }
617
618         if (butler_mixdown_buffer) {
619                 delete [] butler_mixdown_buffer;
620         }
621
622         if (butler_gain_buffer) {
623                 delete [] butler_gain_buffer;
624         }
625
626         Crossfade::set_buffer_size (0);
627
628         if (mmc) {
629                 delete mmc;
630         }
631 }
632
633 void
634 Session::set_worst_io_latencies ()
635 {
636         _worst_output_latency = 0;
637         _worst_input_latency = 0;
638
639         if (!_engine.connected()) {
640                 return;
641         }
642
643         boost::shared_ptr<RouteList> r = routes.reader ();
644         
645         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
646                 _worst_output_latency = max (_worst_output_latency, (*i)->output_latency());
647                 _worst_input_latency = max (_worst_input_latency, (*i)->input_latency());
648         }
649 }
650
651 void
652 Session::when_engine_running ()
653 {
654         string first_physical_output;
655
656         /* we don't want to run execute this again */
657
658         set_block_size (_engine.frames_per_cycle());
659         set_frame_rate (_engine.frame_rate());
660
661         Config->map_parameters (mem_fun (*this, &Session::config_changed));
662
663         /* every time we reconnect, recompute worst case output latencies */
664
665         _engine.Running.connect (mem_fun (*this, &Session::set_worst_io_latencies));
666
667         if (synced_to_jack()) {
668                 _engine.transport_stop ();
669         }
670
671         if (Config->get_jack_time_master()) {
672                 _engine.transport_locate (_transport_frame);
673         }
674
675         _clicking = false;
676
677         try {
678                 XMLNode* child = 0;
679                 
680                 _click_io.reset (new ClickIO (*this, "click", 0, 0, -1, -1));
681
682                 if (state_tree && (child = find_named_node (*state_tree->root(), "Click")) != 0) {
683
684                         /* existing state for Click */
685                         
686                         if (_click_io->set_state (*child->children().front()) == 0) {
687                                 
688                                 _clicking = Config->get_clicking ();
689
690                         } else {
691
692                                 error << _("could not setup Click I/O") << endmsg;
693                                 _clicking = false;
694                         }
695
696                 } else {
697                         
698                         /* default state for Click */
699
700                         first_physical_output = _engine.get_nth_physical_output (DataType::AUDIO, 0);
701
702                         if (first_physical_output.length()) {
703                                 if (_click_io->add_output_port (first_physical_output, this)) {
704                                         // relax, even though its an error
705                                 } else {
706                                         _clicking = Config->get_clicking ();
707                                 }
708                         }
709                 }
710         }
711
712         catch (failed_constructor& err) {
713                 error << _("cannot setup Click I/O") << endmsg;
714         }
715
716         set_worst_io_latencies ();
717
718         if (_clicking) {
719                 // XXX HOW TO ALERT UI TO THIS ? DO WE NEED TO?
720         }
721
722         /* Create a set of Connection objects that map
723            to the physical outputs currently available
724         */
725
726         /* ONE: MONO */
727
728         for (uint32_t np = 0; np < n_physical_outputs; ++np) {
729                 char buf[32];
730                 snprintf (buf, sizeof (buf), _("out %" PRIu32), np+1);
731
732                 Connection* c = new OutputConnection (buf, true);
733
734                 c->add_port ();
735                 c->add_connection (0, _engine.get_nth_physical_output (DataType::AUDIO, np));
736
737                 add_connection (c);
738         }
739
740         for (uint32_t np = 0; np < n_physical_inputs; ++np) {
741                 char buf[32];
742                 snprintf (buf, sizeof (buf), _("in %" PRIu32), np+1);
743
744                 Connection* c = new InputConnection (buf, true);
745
746                 c->add_port ();
747                 c->add_connection (0, _engine.get_nth_physical_input (DataType::AUDIO, np));
748
749                 add_connection (c);
750         }
751
752         /* TWO: STEREO */
753
754         for (uint32_t np = 0; np < n_physical_outputs; np +=2) {
755                 char buf[32];
756                 snprintf (buf, sizeof (buf), _("out %" PRIu32 "+%" PRIu32), np+1, np+2);
757
758                 Connection* c = new OutputConnection (buf, true);
759
760                 c->add_port ();
761                 c->add_port ();
762                 c->add_connection (0, _engine.get_nth_physical_output (DataType::AUDIO, np));
763                 c->add_connection (1, _engine.get_nth_physical_output (DataType::AUDIO, np+1));
764
765                 add_connection (c);
766         }
767
768         for (uint32_t np = 0; np < n_physical_inputs; np +=2) {
769                 char buf[32];
770                 snprintf (buf, sizeof (buf), _("in %" PRIu32 "+%" PRIu32), np+1, np+2);
771
772                 Connection* c = new InputConnection (buf, true);
773
774                 c->add_port ();
775                 c->add_port ();
776                 c->add_connection (0, _engine.get_nth_physical_input (DataType::AUDIO, np));
777                 c->add_connection (1, _engine.get_nth_physical_input (DataType::AUDIO, np+1));
778
779                 add_connection (c);
780         }
781
782         /* THREE MASTER */
783
784         if (_master_out) {
785
786                 /* create master/control ports */
787                 
788                 if (_master_out) {
789                         uint32_t n;
790
791                         /* force the master to ignore any later call to this */
792                         
793                         if (_master_out->pending_state_node) {
794                                 _master_out->ports_became_legal();
795                         }
796
797                         /* no panner resets till we are through */
798                         
799                         _master_out->defer_pan_reset ();
800                         
801                         while (_master_out->n_inputs().get(DataType::AUDIO)
802                                         < _master_out->input_maximum().get(DataType::AUDIO)) {
803                                 if (_master_out->add_input_port ("", this, DataType::AUDIO)) {
804                                         error << _("cannot setup master inputs") 
805                                               << endmsg;
806                                         break;
807                                 }
808                         }
809                         n = 0;
810                         while (_master_out->n_outputs().get(DataType::AUDIO)
811                                         < _master_out->output_maximum().get(DataType::AUDIO)) {
812                                 if (_master_out->add_output_port (_engine.get_nth_physical_output (DataType::AUDIO, n), this, DataType::AUDIO)) {
813                                         error << _("cannot setup master outputs")
814                                               << endmsg;
815                                         break;
816                                 }
817                                 n++;
818                         }
819
820                         _master_out->allow_pan_reset ();
821                         
822                 }
823
824                 Connection* c = new OutputConnection (_("Master Out"), true);
825
826                 for (uint32_t n = 0; n < _master_out->n_inputs ().get_total(); ++n) {
827                         c->add_port ();
828                         c->add_connection ((int) n, _master_out->input(n)->name());
829                 }
830                 add_connection (c);
831         } 
832
833         hookup_io ();
834
835         /* catch up on send+insert cnts */
836
837         insert_cnt = 0;
838         
839         for (list<PortInsert*>::iterator i = _port_inserts.begin(); i != _port_inserts.end(); ++i) {
840                 uint32_t id;
841
842                 if (sscanf ((*i)->name().c_str(), "%*s %u", &id) == 1) {
843                         if (id > insert_cnt) {
844                                 insert_cnt = id;
845                         }
846                 }
847         }
848
849         send_cnt = 0;
850
851         for (list<Send*>::iterator i = _sends.begin(); i != _sends.end(); ++i) {
852                 uint32_t id;
853                 
854                 if (sscanf ((*i)->name().c_str(), "%*s %u", &id) == 1) {
855                         if (id > send_cnt) {
856                                 send_cnt = id;
857                         }
858                 }
859         }
860
861         
862         _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
863
864         /* hook us up to the engine */
865
866         _engine.set_session (this);
867
868 #ifdef HAVE_LIBLO
869         /* and to OSC */
870
871         osc->set_session (*this);
872 #endif
873
874         _state_of_the_state = Clean;
875
876         DirtyChanged (); /* EMIT SIGNAL */
877 }
878
879 void
880 Session::hookup_io ()
881 {
882         /* stop graph reordering notifications from
883            causing resorts, etc.
884         */
885
886         _state_of_the_state = StateOfTheState (_state_of_the_state | InitialConnecting);
887
888         if (auditioner == 0) {
889                 
890                 /* we delay creating the auditioner till now because
891                    it makes its own connections to ports.
892                    the engine has to be running for this to work.
893                 */
894                 
895                 try {
896                         auditioner.reset (new Auditioner (*this));
897                 }
898                 
899                 catch (failed_constructor& err) {
900                         warning << _("cannot create Auditioner: no auditioning of regions possible") << endmsg;
901                 }
902         }
903
904         /* Tell all IO objects to create their ports */
905
906         IO::enable_ports ();
907
908         if (_control_out) {
909                 uint32_t n;
910
911                 while (_control_out->n_inputs().get(DataType::AUDIO) < _control_out->input_maximum().get(DataType::AUDIO)) {
912                         if (_control_out->add_input_port ("", this)) {
913                                 error << _("cannot setup control inputs")
914                                       << endmsg;
915                                 break;
916                         }
917                 }
918                 n = 0;
919                 while (_control_out->n_outputs().get(DataType::AUDIO) < _control_out->output_maximum().get(DataType::AUDIO)) {
920                         if (_control_out->add_output_port (_engine.get_nth_physical_output (DataType::AUDIO, n), this)) {
921                                 error << _("cannot set up master outputs")
922                                       << endmsg;
923                                 break;
924                         }
925                         n++;
926                 }
927         }
928
929         /* Tell all IO objects to connect themselves together */
930
931         IO::enable_connecting ();
932
933         /* Now reset all panners */
934
935         IO::reset_panners ();
936
937         /* Anyone who cares about input state, wake up and do something */
938
939         IOConnectionsComplete (); /* EMIT SIGNAL */
940
941         _state_of_the_state = StateOfTheState (_state_of_the_state & ~InitialConnecting);
942
943         /* now handle the whole enchilada as if it was one
944            graph reorder event.
945         */
946
947         graph_reordered ();
948
949         /* update mixer solo state */
950
951         catch_up_on_solo();
952 }
953
954 void
955 Session::playlist_length_changed ()
956 {
957         /* we can't just increase end_location->end() if pl->get_maximum_extent() 
958            if larger. if the playlist used to be the longest playlist,
959            and its now shorter, we have to decrease end_location->end(). hence,
960            we have to iterate over all diskstreams and check the 
961            playlists currently in use.
962         */
963         find_current_end ();
964 }
965
966 void
967 Session::diskstream_playlist_changed (boost::shared_ptr<Diskstream> dstream)
968 {
969         boost::shared_ptr<Playlist> playlist;
970
971         if ((playlist = dstream->playlist()) != 0) {
972                 playlist->LengthChanged.connect (mem_fun (this, &Session::playlist_length_changed));
973         }
974         
975         /* see comment in playlist_length_changed () */
976         find_current_end ();
977 }
978
979 bool
980 Session::record_enabling_legal () const
981 {
982         /* this used to be in here, but survey says.... we don't need to restrict it */
983         // if (record_status() == Recording) {
984         //      return false;
985         // }
986
987         if (Config->get_all_safe()) {
988                 return false;
989         }
990         return true;
991 }
992
993 void
994 Session::reset_input_monitor_state ()
995 {
996         if (transport_rolling()) {
997
998                 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
999
1000                 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1001                         if ((*i)->record_enabled ()) {
1002                                 //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
1003                                 (*i)->monitor_input (Config->get_monitoring_model() == HardwareMonitoring && !Config->get_auto_input());
1004                         }
1005                 }
1006         } else {
1007                 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1008
1009                 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1010                         if ((*i)->record_enabled ()) {
1011                                 //cerr << "switching to input = " << !Config->get_auto_input() << __FILE__ << __LINE__ << endl << endl;
1012                                 (*i)->monitor_input (Config->get_monitoring_model() == HardwareMonitoring);
1013                         }
1014                 }
1015         }
1016 }
1017
1018 void
1019 Session::auto_punch_start_changed (Location* location)
1020 {
1021         replace_event (Event::PunchIn, location->start());
1022
1023         if (get_record_enabled() && Config->get_punch_in()) {
1024                 /* capture start has been changed, so save new pending state */
1025                 save_state ("", true);
1026         }
1027 }       
1028
1029 void
1030 Session::auto_punch_end_changed (Location* location)
1031 {
1032         nframes_t when_to_stop = location->end();
1033         // when_to_stop += _worst_output_latency + _worst_input_latency;
1034         replace_event (Event::PunchOut, when_to_stop);
1035 }       
1036
1037 void
1038 Session::auto_punch_changed (Location* location)
1039 {
1040         nframes_t when_to_stop = location->end();
1041
1042         replace_event (Event::PunchIn, location->start());
1043         //when_to_stop += _worst_output_latency + _worst_input_latency;
1044         replace_event (Event::PunchOut, when_to_stop);
1045 }       
1046
1047 void
1048 Session::auto_loop_changed (Location* location)
1049 {
1050         replace_event (Event::AutoLoop, location->end(), location->start());
1051
1052         if (transport_rolling() && play_loop) {
1053
1054                 //if (_transport_frame < location->start() || _transport_frame > location->end()) {
1055
1056                 if (_transport_frame > location->end()) {
1057                         // relocate to beginning of loop
1058                         clear_events (Event::LocateRoll);
1059                         
1060                         request_locate (location->start(), true);
1061
1062                 }
1063                 else if (Config->get_seamless_loop() && !loop_changing) {
1064                         
1065                         // schedule a locate-roll to refill the diskstreams at the
1066                         // previous loop end
1067                         loop_changing = true;
1068
1069                         if (location->end() > last_loopend) {
1070                                 clear_events (Event::LocateRoll);
1071                                 Event *ev = new Event (Event::LocateRoll, Event::Add, last_loopend, last_loopend, 0, true);
1072                                 queue_event (ev);
1073                         }
1074
1075                 }
1076         }       
1077
1078         last_loopend = location->end();
1079         
1080 }
1081
1082 void
1083 Session::set_auto_punch_location (Location* location)
1084 {
1085         Location* existing;
1086
1087         if ((existing = _locations.auto_punch_location()) != 0 && existing != location) {
1088                 auto_punch_start_changed_connection.disconnect();
1089                 auto_punch_end_changed_connection.disconnect();
1090                 auto_punch_changed_connection.disconnect();
1091                 existing->set_auto_punch (false, this);
1092                 remove_event (existing->start(), Event::PunchIn);
1093                 clear_events (Event::PunchOut);
1094                 auto_punch_location_changed (0);
1095         }
1096
1097         set_dirty();
1098
1099         if (location == 0) {
1100                 return;
1101         }
1102         
1103         if (location->end() <= location->start()) {
1104                 error << _("Session: you can't use that location for auto punch (start <= end)") << endmsg;
1105                 return;
1106         }
1107
1108         auto_punch_start_changed_connection.disconnect();
1109         auto_punch_end_changed_connection.disconnect();
1110         auto_punch_changed_connection.disconnect();
1111                 
1112         auto_punch_start_changed_connection = location->start_changed.connect (mem_fun (this, &Session::auto_punch_start_changed));
1113         auto_punch_end_changed_connection = location->end_changed.connect (mem_fun (this, &Session::auto_punch_end_changed));
1114         auto_punch_changed_connection = location->changed.connect (mem_fun (this, &Session::auto_punch_changed));
1115
1116         location->set_auto_punch (true, this);
1117         auto_punch_location_changed (location);
1118 }
1119
1120 void
1121 Session::set_auto_loop_location (Location* location)
1122 {
1123         Location* existing;
1124
1125         if ((existing = _locations.auto_loop_location()) != 0 && existing != location) {
1126                 auto_loop_start_changed_connection.disconnect();
1127                 auto_loop_end_changed_connection.disconnect();
1128                 auto_loop_changed_connection.disconnect();
1129                 existing->set_auto_loop (false, this);
1130                 remove_event (existing->end(), Event::AutoLoop);
1131                 auto_loop_location_changed (0);
1132         }
1133         
1134         set_dirty();
1135
1136         if (location == 0) {
1137                 return;
1138         }
1139
1140         if (location->end() <= location->start()) {
1141                 error << _("Session: you can't use a mark for auto loop") << endmsg;
1142                 return;
1143         }
1144
1145         last_loopend = location->end();
1146         
1147         auto_loop_start_changed_connection.disconnect();
1148         auto_loop_end_changed_connection.disconnect();
1149         auto_loop_changed_connection.disconnect();
1150         
1151         auto_loop_start_changed_connection = location->start_changed.connect (mem_fun (this, &Session::auto_loop_changed));
1152         auto_loop_end_changed_connection = location->end_changed.connect (mem_fun (this, &Session::auto_loop_changed));
1153         auto_loop_changed_connection = location->changed.connect (mem_fun (this, &Session::auto_loop_changed));
1154
1155         location->set_auto_loop (true, this);
1156         auto_loop_location_changed (location);
1157 }
1158
1159 void
1160 Session::locations_added (Location* ignored)
1161 {
1162         set_dirty ();
1163 }
1164
1165 void
1166 Session::locations_changed ()
1167 {
1168         _locations.apply (*this, &Session::handle_locations_changed);
1169 }
1170
1171 void
1172 Session::handle_locations_changed (Locations::LocationList& locations)
1173 {
1174         Locations::LocationList::iterator i;
1175         Location* location;
1176         bool set_loop = false;
1177         bool set_punch = false;
1178
1179         for (i = locations.begin(); i != locations.end(); ++i) {
1180
1181                 location =* i;
1182
1183                 if (location->is_auto_punch()) {
1184                         set_auto_punch_location (location);
1185                         set_punch = true;
1186                 }
1187                 if (location->is_auto_loop()) {
1188                         set_auto_loop_location (location);
1189                         set_loop = true;
1190                 }
1191                 
1192         }
1193
1194         if (!set_loop) {
1195                 set_auto_loop_location (0);
1196         }
1197         if (!set_punch) {
1198                 set_auto_punch_location (0);
1199         }
1200
1201         set_dirty();
1202 }                                                    
1203
1204 void
1205 Session::enable_record ()
1206 {
1207         /* XXX really atomic compare+swap here */
1208         if (g_atomic_int_get (&_record_status) != Recording) {
1209                 g_atomic_int_set (&_record_status, Recording);
1210                 _last_record_location = _transport_frame;
1211                 deliver_mmc(MIDI::MachineControl::cmdRecordStrobe, _last_record_location);
1212
1213                 if (Config->get_monitoring_model() == HardwareMonitoring && Config->get_auto_input()) {
1214                         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1215                         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1216                                 if ((*i)->record_enabled ()) {
1217                                         (*i)->monitor_input (true);   
1218                                 }
1219                         }
1220                 }
1221
1222                 RecordStateChanged ();
1223         }
1224 }
1225
1226 void
1227 Session::disable_record (bool rt_context, bool force)
1228 {
1229         RecordState rs;
1230
1231         if ((rs = (RecordState) g_atomic_int_get (&_record_status)) != Disabled) {
1232
1233                 if (!Config->get_latched_record_enable () || force) {
1234                         g_atomic_int_set (&_record_status, Disabled);
1235                 } else {
1236                         if (rs == Recording) {
1237                                 g_atomic_int_set (&_record_status, Enabled);
1238                         }
1239                 }
1240
1241                 // FIXME: timestamp correct? [DR]
1242                 // FIXME FIXME FIXME: rt_context?  this must be called in the process thread.
1243                 // does this /need/ to be sent in all cases?
1244                 if (rt_context)
1245                         deliver_mmc (MIDI::MachineControl::cmdRecordExit, _transport_frame);
1246
1247                 if (Config->get_monitoring_model() == HardwareMonitoring && Config->get_auto_input()) {
1248                         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1249                         
1250                         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1251                                 if ((*i)->record_enabled ()) {
1252                                         (*i)->monitor_input (false);   
1253                                 }
1254                         }
1255                 }
1256                 
1257                 RecordStateChanged (); /* emit signal */
1258
1259                 if (!rt_context) {
1260                         remove_pending_capture_state ();
1261                 }
1262         }
1263 }
1264
1265 void
1266 Session::step_back_from_record ()
1267 {
1268         g_atomic_int_set (&_record_status, Enabled);
1269
1270         if (Config->get_monitoring_model() == HardwareMonitoring) {
1271                 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1272                 
1273                 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1274                         if (Config->get_auto_input() && (*i)->record_enabled ()) {
1275                                 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
1276                                 (*i)->monitor_input (false);   
1277                         }
1278                 }
1279         }
1280 }
1281
1282 void
1283 Session::maybe_enable_record ()
1284 {
1285         g_atomic_int_set (&_record_status, Enabled);
1286
1287         /* this function is currently called from somewhere other than an RT thread.
1288            this save_state() call therefore doesn't impact anything.
1289         */
1290
1291         save_state ("", true);
1292
1293         if (_transport_speed) {
1294                 if (!Config->get_punch_in()) {
1295                         enable_record ();
1296                 } 
1297         } else {
1298                 deliver_mmc (MIDI::MachineControl::cmdRecordPause, _transport_frame);
1299                 RecordStateChanged (); /* EMIT SIGNAL */
1300         }
1301
1302         set_dirty();
1303 }
1304
1305 nframes_t
1306 Session::audible_frame () const
1307 {
1308         nframes_t ret;
1309         nframes_t offset;
1310         nframes_t tf;
1311
1312         /* the first of these two possible settings for "offset"
1313            mean that the audible frame is stationary until 
1314            audio emerges from the latency compensation
1315            "pseudo-pipeline".
1316
1317            the second means that the audible frame is stationary
1318            until audio would emerge from a physical port
1319            in the absence of any plugin latency compensation
1320         */
1321
1322         offset = _worst_output_latency;
1323
1324         if (offset > current_block_size) {
1325                 offset -= current_block_size;
1326         } else { 
1327                 /* XXX is this correct? if we have no external
1328                    physical connections and everything is internal
1329                    then surely this is zero? still, how
1330                    likely is that anyway?
1331                 */
1332                 offset = current_block_size;
1333         }
1334
1335         if (synced_to_jack()) {
1336                 tf = _engine.transport_frame();
1337         } else {
1338                 tf = _transport_frame;
1339         }
1340
1341         if (_transport_speed == 0) {
1342                 return tf;
1343         }
1344
1345         if (tf < offset) {
1346                 return 0;
1347         }
1348
1349         ret = tf;
1350
1351         if (!non_realtime_work_pending()) {
1352
1353                 /* MOVING */
1354
1355                 /* take latency into account */
1356                 
1357                 ret -= offset;
1358         }
1359
1360         return ret;
1361 }
1362
1363 void
1364 Session::set_frame_rate (nframes_t frames_per_second)
1365 {
1366         /** \fn void Session::set_frame_size(nframes_t)
1367                 the AudioEngine object that calls this guarantees 
1368                 that it will not be called while we are also in
1369                 ::process(). Its fine to do things that block
1370                 here.
1371         */
1372
1373         _base_frame_rate = frames_per_second;
1374
1375         sync_time_vars();
1376
1377         Route::set_automation_interval ((jack_nframes_t) ceil ((double) frames_per_second * 0.25));
1378
1379         // XXX we need some equivalent to this, somehow
1380         // SndFileSource::setup_standard_crossfades (frames_per_second);
1381
1382         set_dirty();
1383
1384         /* XXX need to reset/reinstantiate all LADSPA plugins */
1385 }
1386
1387 void
1388 Session::set_block_size (nframes_t nframes)
1389 {
1390         /* the AudioEngine guarantees 
1391            that it will not be called while we are also in
1392            ::process(). It is therefore fine to do things that block
1393            here.
1394         */
1395
1396         { 
1397                         
1398                 current_block_size = nframes;
1399                 
1400                 ensure_buffers(_scratch_buffers->available());
1401
1402                 if (_gain_automation_buffer) {
1403                         delete [] _gain_automation_buffer;
1404                 }
1405                 _gain_automation_buffer = new gain_t[nframes];
1406
1407                 allocate_pan_automation_buffers (nframes, _npan_buffers, true);
1408
1409                 boost::shared_ptr<RouteList> r = routes.reader ();
1410
1411                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1412                         (*i)->set_block_size (nframes);
1413                 }
1414                 
1415                 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1416                 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1417                         (*i)->set_block_size (nframes);
1418                 }
1419
1420                 set_worst_io_latencies ();
1421         }
1422 }
1423
1424 void
1425 Session::set_default_fade (float steepness, float fade_msecs)
1426 {
1427 #if 0
1428         nframes_t fade_frames;
1429         
1430         /* Don't allow fade of less 1 frame */
1431         
1432         if (fade_msecs < (1000.0 * (1.0/_current_frame_rate))) {
1433
1434                 fade_msecs = 0;
1435                 fade_frames = 0;
1436
1437         } else {
1438                 
1439                 fade_frames = (nframes_t) floor (fade_msecs * _current_frame_rate * 0.001);
1440                 
1441         }
1442
1443         default_fade_msecs = fade_msecs;
1444         default_fade_steepness = steepness;
1445
1446         {
1447                 // jlc, WTF is this!
1448                 Glib::RWLock::ReaderLock lm (route_lock);
1449                 AudioRegion::set_default_fade (steepness, fade_frames);
1450         }
1451
1452         set_dirty();
1453
1454         /* XXX have to do this at some point */
1455         /* foreach region using default fade, reset, then 
1456            refill_all_diskstream_buffers ();
1457         */
1458 #endif
1459 }
1460
1461 struct RouteSorter {
1462     bool operator() (boost::shared_ptr<Route> r1, boost::shared_ptr<Route> r2) {
1463             if (r1->fed_by.find (r2) != r1->fed_by.end()) {
1464                     return false;
1465             } else if (r2->fed_by.find (r1) != r2->fed_by.end()) {
1466                     return true;
1467             } else {
1468                     if (r1->fed_by.empty()) {
1469                             if (r2->fed_by.empty()) {
1470                                     /* no ardour-based connections inbound to either route. just use signal order */
1471                                     return r1->order_key(N_("signal")) < r2->order_key(N_("signal"));
1472                             } else {
1473                                     /* r2 has connections, r1 does not; run r1 early */
1474                                     return true;
1475                             }
1476                     } else {
1477                             return r1->order_key(N_("signal")) < r2->order_key(N_("signal"));
1478                     }
1479             }
1480     }
1481 };
1482
1483 static void
1484 trace_terminal (shared_ptr<Route> r1, shared_ptr<Route> rbase)
1485 {
1486         shared_ptr<Route> r2;
1487
1488         if ((r1->fed_by.find (rbase) != r1->fed_by.end()) && (rbase->fed_by.find (r1) != rbase->fed_by.end())) {
1489                 info << string_compose(_("feedback loop setup between %1 and %2"), r1->name(), rbase->name()) << endmsg;
1490                 return;
1491         } 
1492
1493         /* make a copy of the existing list of routes that feed r1 */
1494
1495         set<shared_ptr<Route> > existing = r1->fed_by;
1496
1497         /* for each route that feeds r1, recurse, marking it as feeding
1498            rbase as well.
1499         */
1500
1501         for (set<shared_ptr<Route> >::iterator i = existing.begin(); i != existing.end(); ++i) {
1502                 r2 =* i;
1503
1504                 /* r2 is a route that feeds r1 which somehow feeds base. mark
1505                    base as being fed by r2
1506                 */
1507
1508                 rbase->fed_by.insert (r2);
1509
1510                 if (r2 != rbase) {
1511
1512                         /* 2nd level feedback loop detection. if r1 feeds or is fed by r2,
1513                            stop here.
1514                          */
1515
1516                         if ((r1->fed_by.find (r2) != r1->fed_by.end()) && (r2->fed_by.find (r1) != r2->fed_by.end())) {
1517                                 continue;
1518                         }
1519
1520                         /* now recurse, so that we can mark base as being fed by
1521                            all routes that feed r2
1522                         */
1523
1524                         trace_terminal (r2, rbase);
1525                 }
1526
1527         }
1528 }
1529
1530 void
1531 Session::resort_routes ()
1532 {
1533         /* don't do anything here with signals emitted
1534            by Routes while we are being destroyed.
1535         */
1536
1537         if (_state_of_the_state & Deletion) {
1538                 return;
1539         }
1540
1541
1542         {
1543
1544                 RCUWriter<RouteList> writer (routes);
1545                 shared_ptr<RouteList> r = writer.get_copy ();
1546                 resort_routes_using (r);
1547                 /* writer goes out of scope and forces update */
1548         }
1549
1550 }
1551 void
1552 Session::resort_routes_using (shared_ptr<RouteList> r)
1553 {
1554         RouteList::iterator i, j;
1555         
1556         for (i = r->begin(); i != r->end(); ++i) {
1557                 
1558                 (*i)->fed_by.clear ();
1559                 
1560                 for (j = r->begin(); j != r->end(); ++j) {
1561                         
1562                         /* although routes can feed themselves, it will
1563                            cause an endless recursive descent if we
1564                            detect it. so don't bother checking for
1565                            self-feeding.
1566                         */
1567                         
1568                         if (*j == *i) {
1569                                 continue;
1570                         }
1571                         
1572                         if ((*j)->feeds (*i)) {
1573                                 (*i)->fed_by.insert (*j);
1574                         } 
1575                 }
1576         }
1577         
1578         for (i = r->begin(); i != r->end(); ++i) {
1579                 trace_terminal (*i, *i);
1580         }
1581         
1582         RouteSorter cmp;
1583         r->sort (cmp);
1584         
1585 #if 0
1586         cerr << "finished route resort\n";
1587         
1588         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1589                 cerr << " " << (*i)->name() << " signal order = " << (*i)->order_key ("signal") << endl;
1590         }
1591         cerr << endl;
1592 #endif
1593         
1594 }
1595
1596 list<boost::shared_ptr<MidiTrack> >
1597 Session::new_midi_track (TrackMode mode, uint32_t how_many)
1598 {
1599         char track_name[32];
1600         uint32_t track_id = 0;
1601         uint32_t n = 0;
1602         uint32_t channels_used = 0;
1603         string port;
1604         RouteList new_routes;
1605         list<boost::shared_ptr<MidiTrack> > ret;
1606
1607         /* count existing midi tracks */
1608
1609         {
1610                 shared_ptr<RouteList> r = routes.reader ();
1611
1612                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1613                         if (dynamic_cast<MidiTrack*>((*i).get()) != 0) {
1614                                 if (!(*i)->hidden()) {
1615                                         n++;
1616                                         channels_used += (*i)->n_inputs().get(DataType::MIDI);
1617                                 }
1618                         }
1619                 }
1620         }
1621
1622         while (how_many) {
1623
1624                 /* check for duplicate route names, since we might have pre-existing
1625                    routes with this name (e.g. create Midi1, Midi2, delete Midi1,
1626                    save, close,restart,add new route - first named route is now
1627                    Midi2)
1628                 */
1629                 
1630
1631                 do {
1632                         ++track_id;
1633
1634                         snprintf (track_name, sizeof(track_name), "Midi %" PRIu32, track_id);
1635
1636                         if (route_by_name (track_name) == 0) {
1637                                 break;
1638                         }
1639                         
1640                 } while (track_id < (UINT_MAX-1));
1641
1642                 try {
1643                         shared_ptr<MidiTrack> track (new MidiTrack (*this, track_name, Route::Flag (0), mode));
1644                         
1645                         if (track->ensure_io (ChanCount(DataType::MIDI, 1), ChanCount(DataType::MIDI, 1), false, this)) {
1646                                 error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
1647                         }
1648                         
1649                         channels_used += track->n_inputs ().get(DataType::MIDI);
1650
1651                         track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes));
1652                         track->set_remote_control_id (ntracks());
1653
1654                         new_routes.push_back (track);
1655                         ret.push_back (track);
1656                 }
1657
1658                 catch (failed_constructor &err) {
1659                         error << _("Session: could not create new midi track.") << endmsg;
1660                         // XXX should we delete the tracks already created? 
1661                         ret.clear ();
1662                         return ret;
1663                 }
1664                 
1665                 --how_many;
1666         }
1667
1668         if (!new_routes.empty()) {
1669                 add_routes (new_routes, false);
1670                 save_state (_current_snapshot_name);
1671         }
1672
1673         return ret;
1674 }
1675
1676 list<boost::shared_ptr<AudioTrack> >
1677 Session::new_audio_track (int input_channels, int output_channels, TrackMode mode, uint32_t how_many)
1678 {
1679         char track_name[32];
1680         uint32_t track_id = 0;
1681         uint32_t n = 0;
1682         uint32_t channels_used = 0;
1683         string port;
1684         RouteList new_routes;
1685         list<boost::shared_ptr<AudioTrack> > ret;
1686         uint32_t control_id;
1687
1688         /* count existing audio tracks */
1689
1690         {
1691                 shared_ptr<RouteList> r = routes.reader ();
1692
1693                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1694                         if (dynamic_cast<AudioTrack*>((*i).get()) != 0) {
1695                                 if (!(*i)->hidden()) {
1696                                         n++;
1697                                         channels_used += (*i)->n_inputs().get(DataType::AUDIO);
1698                                 }
1699                         }
1700                 }
1701         }
1702
1703         vector<string> physinputs;
1704         vector<string> physoutputs;
1705         uint32_t nphysical_in;
1706         uint32_t nphysical_out;
1707
1708         _engine.get_physical_outputs (physoutputs);
1709         _engine.get_physical_inputs (physinputs);
1710         control_id = ntracks() + nbusses() + 1;
1711
1712         while (how_many) {
1713
1714                 /* check for duplicate route names, since we might have pre-existing
1715                    routes with this name (e.g. create Audio1, Audio2, delete Audio1,
1716                    save, close,restart,add new route - first named route is now
1717                    Audio2)
1718                 */
1719                 
1720
1721                 do {
1722                         ++track_id;
1723
1724                         snprintf (track_name, sizeof(track_name), "Audio %" PRIu32, track_id);
1725
1726                         if (route_by_name (track_name) == 0) {
1727                                 break;
1728                         }
1729                         
1730                 } while (track_id < (UINT_MAX-1));
1731
1732                 if (Config->get_input_auto_connect() & AutoConnectPhysical) {
1733                         nphysical_in = min (n_physical_inputs, (uint32_t) physinputs.size());
1734                 } else {
1735                         nphysical_in = 0;
1736                 }
1737                 
1738                 if (Config->get_output_auto_connect() & AutoConnectPhysical) {
1739                         nphysical_out = min (n_physical_outputs, (uint32_t) physinputs.size());
1740                 } else {
1741                         nphysical_out = 0;
1742                 }
1743                 
1744                 try {
1745                         shared_ptr<AudioTrack> track (new AudioTrack (*this, track_name, Route::Flag (0), mode));
1746                         
1747                         if (track->ensure_io (ChanCount(DataType::AUDIO, input_channels), ChanCount(DataType::AUDIO, output_channels), false, this)) {
1748                                 error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
1749                                                          input_channels, output_channels)
1750                                       << endmsg;
1751                         }
1752                         
1753                         if (nphysical_in) {
1754                                 for (uint32_t x = 0; x < track->n_inputs().get(DataType::AUDIO) && x < nphysical_in; ++x) {
1755                                         
1756                                         port = "";
1757                                         
1758                                         if (Config->get_input_auto_connect() & AutoConnectPhysical) {
1759                                                 port = physinputs[(channels_used+x)%nphysical_in];
1760                                         } 
1761                                         
1762                                         if (port.length() && track->connect_input (track->input (x), port, this)) {
1763                                                 break;
1764                                         }
1765                                 }
1766                         }
1767                         
1768                         for (uint32_t x = 0; x < track->n_outputs().get(DataType::MIDI); ++x) {
1769                                 
1770                                 port = "";
1771                                 
1772                                 if (nphysical_out && (Config->get_output_auto_connect() & AutoConnectPhysical)) {
1773                                         port = physoutputs[(channels_used+x)%nphysical_out];
1774                                 } else if (Config->get_output_auto_connect() & AutoConnectMaster) {
1775                                         if (_master_out) {
1776                                                 port = _master_out->input (x%_master_out->n_inputs().get(DataType::AUDIO))->name();
1777                                         }
1778                                 }
1779                                 
1780                                 if (port.length() && track->connect_output (track->output (x), port, this)) {
1781                                         break;
1782                                 }
1783                         }
1784                         
1785                         channels_used += track->n_inputs ().get(DataType::AUDIO);
1786
1787                         if (_control_out) {
1788                                 vector<string> cports;
1789                                 uint32_t ni = _control_out->n_inputs().get(DataType::AUDIO);
1790                                 
1791                                 for (n = 0; n < ni; ++n) {
1792                                         cports.push_back (_control_out->input(n)->name());
1793                                 }
1794                                 
1795                                 track->set_control_outs (cports);
1796                         }
1797
1798                         // assert (current_thread != RT_thread)
1799                         
1800                         track->audio_diskstream()->non_realtime_input_change();
1801                         
1802                         track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes));
1803                         track->set_remote_control_id (control_id);
1804                         ++control_id;
1805
1806                         new_routes.push_back (track);
1807                         ret.push_back (track);
1808                 }
1809
1810                 catch (failed_constructor &err) {
1811                         error << _("Session: could not create new audio track.") << endmsg;
1812                         // XXX should we delete the tracks already created? 
1813                         ret.clear ();
1814                         return ret;
1815                 }
1816                 
1817                 --how_many;
1818         }
1819
1820         if (!new_routes.empty()) {
1821                 add_routes (new_routes, false);
1822                 save_state (_current_snapshot_name);
1823         }
1824
1825         return ret;
1826 }
1827
1828 Session::RouteList
1829 Session::new_audio_route (int input_channels, int output_channels, uint32_t how_many)
1830 {
1831         char bus_name[32];
1832         uint32_t bus_id = 1;
1833         uint32_t n = 0;
1834         string port;
1835         RouteList ret;
1836         uint32_t control_id;
1837
1838         /* count existing audio busses */
1839
1840         {
1841                 shared_ptr<RouteList> r = routes.reader ();
1842
1843                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1844                         if (dynamic_cast<AudioTrack*>((*i).get()) == 0) {
1845                                 if (!(*i)->hidden()) {
1846                                         bus_id++;
1847                                 }
1848                         }
1849                 }
1850         }
1851
1852         vector<string> physinputs;
1853         vector<string> physoutputs;
1854
1855         _engine.get_physical_outputs (physoutputs);
1856         _engine.get_physical_inputs (physinputs);
1857         control_id = ntracks() + nbusses() + 1;
1858
1859         while (how_many) {
1860
1861                 do {
1862                         ++bus_id;
1863
1864                         snprintf (bus_name, sizeof(bus_name), "Bus %" PRIu32, bus_id);
1865
1866                         if (route_by_name (bus_name) == 0) {
1867                                 break;
1868                         }
1869
1870                 } while (bus_id < (UINT_MAX-1));
1871
1872                 try {
1873                         shared_ptr<Route> bus (new Route (*this, bus_name, -1, -1, -1, -1, Route::Flag(0), DataType::AUDIO));
1874                         
1875                         if (bus->ensure_io (ChanCount(DataType::AUDIO, input_channels), ChanCount(DataType::AUDIO, output_channels), false, this)) {
1876                                 error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
1877                                                          input_channels, output_channels)
1878                                       << endmsg;
1879                         }
1880                         
1881                         for (uint32_t x = 0; n_physical_inputs && x < bus->n_inputs().get(DataType::AUDIO); ++x) {
1882                                 
1883                                 port = "";
1884
1885                                 if (Config->get_input_auto_connect() & AutoConnectPhysical) {
1886                                                 port = physinputs[((n+x)%n_physical_inputs)];
1887                                 } 
1888                                 
1889                                 if (port.length() && bus->connect_input (bus->input (x), port, this)) {
1890                                         break;
1891                                 }
1892                         }
1893                         
1894                         for (uint32_t x = 0; n_physical_outputs && x < bus->n_outputs().get(DataType::AUDIO); ++x) {
1895                                 
1896                                 port = "";
1897                                 
1898                                 if (Config->get_output_auto_connect() & AutoConnectPhysical) {
1899                                         port = physoutputs[((n+x)%n_physical_outputs)];
1900                                 } else if (Config->get_output_auto_connect() & AutoConnectMaster) {
1901                                         if (_master_out) {
1902                                                 port = _master_out->input (x%_master_out->n_inputs().get(DataType::AUDIO))->name();
1903                                         }
1904                                 }
1905                                 
1906                                 if (port.length() && bus->connect_output (bus->output (x), port, this)) {
1907                                         break;
1908                                 }
1909                         }
1910                         
1911                         if (_control_out) {
1912                                 vector<string> cports;
1913                                 uint32_t ni = _control_out->n_inputs().get(DataType::AUDIO);
1914                                 
1915                                 for (uint32_t n = 0; n < ni; ++n) {
1916                                         cports.push_back (_control_out->input(n)->name());
1917                                 }
1918                                 bus->set_control_outs (cports);
1919                         }
1920
1921                         bus->set_remote_control_id (control_id);
1922                         ++control_id;
1923
1924                         ret.push_back (bus);
1925                 }
1926         
1927
1928                 catch (failed_constructor &err) {
1929                         error << _("Session: could not create new audio route.") << endmsg;
1930                         ret.clear ();
1931                         return ret;
1932                 }
1933
1934                 --how_many;
1935         }
1936
1937         if (!ret.empty()) {
1938                 add_routes (ret, false);
1939                 save_state (_current_snapshot_name);
1940         }
1941
1942         return ret;
1943
1944 }
1945
1946 void
1947 Session::add_routes (RouteList& new_routes, bool save)
1948 {
1949         { 
1950                 RCUWriter<RouteList> writer (routes);
1951                 shared_ptr<RouteList> r = writer.get_copy ();
1952                 r->insert (r->end(), new_routes.begin(), new_routes.end());
1953                 resort_routes_using (r);
1954         }
1955
1956         for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
1957                 
1958                 boost::weak_ptr<Route> wpr (*x);
1959
1960                 (*x)->solo_changed.connect (sigc::bind (mem_fun (*this, &Session::route_solo_changed), wpr));
1961                 (*x)->mute_changed.connect (mem_fun (*this, &Session::route_mute_changed));
1962                 (*x)->output_changed.connect (mem_fun (*this, &Session::set_worst_io_latencies_x));
1963                 (*x)->redirects_changed.connect (mem_fun (*this, &Session::update_latency_compensation_proxy));
1964                 
1965                 if ((*x)->master()) {
1966                         _master_out = (*x);
1967                 }
1968                 
1969                 if ((*x)->control()) {
1970                         _control_out = (*x);
1971                 }
1972         }
1973
1974         set_dirty();
1975
1976         if (save) {
1977                 save_state (_current_snapshot_name);
1978         }
1979
1980         RouteAdded (new_routes); /* EMIT SIGNAL */
1981 }
1982
1983 void
1984 Session::add_diskstream (boost::shared_ptr<Diskstream> dstream)
1985 {
1986         /* need to do this in case we're rolling at the time, to prevent false underruns */
1987         dstream->do_refill_with_alloc();
1988         
1989         { 
1990                 RCUWriter<DiskstreamList> writer (diskstreams);
1991                 boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
1992                 ds->push_back (dstream);
1993         }
1994
1995         dstream->set_block_size (current_block_size);
1996
1997         dstream->PlaylistChanged.connect (sigc::bind (mem_fun (*this, &Session::diskstream_playlist_changed), dstream));
1998         /* this will connect to future changes, and check the current length */
1999         diskstream_playlist_changed (dstream);
2000
2001         dstream->prepare ();
2002 }
2003
2004 void
2005 Session::remove_route (shared_ptr<Route> route)
2006 {
2007         {       
2008                 RCUWriter<RouteList> writer (routes);
2009                 shared_ptr<RouteList> rs = writer.get_copy ();
2010                 
2011                 rs->remove (route);
2012
2013                 /* deleting the master out seems like a dumb
2014                    idea, but its more of a UI policy issue
2015                    than our concern.
2016                 */
2017
2018                 if (route == _master_out) {
2019                         _master_out = shared_ptr<Route> ();
2020                 }
2021
2022                 if (route == _control_out) {
2023                         _control_out = shared_ptr<Route> ();
2024
2025                         /* cancel control outs for all routes */
2026
2027                         vector<string> empty;
2028
2029                         for (RouteList::iterator r = rs->begin(); r != rs->end(); ++r) {
2030                                 (*r)->set_control_outs (empty);
2031                         }
2032                 }
2033
2034                 update_route_solo_state ();
2035                 
2036                 /* writer goes out of scope, forces route list update */
2037         }
2038
2039         Track* t;
2040         boost::shared_ptr<Diskstream> ds;
2041         
2042         if ((t = dynamic_cast<Track*>(route.get())) != 0) {
2043                 ds = t->diskstream();
2044         }
2045         
2046         if (ds) {
2047
2048                 {
2049                         RCUWriter<DiskstreamList> dsl (diskstreams);
2050                         boost::shared_ptr<DiskstreamList> d = dsl.get_copy();
2051                         d->remove (ds);
2052                 }
2053         }
2054
2055         find_current_end ();
2056         
2057         update_latency_compensation (false, false);
2058         set_dirty();
2059
2060         // We need to disconnect the routes inputs and outputs 
2061         route->disconnect_inputs(NULL);
2062         route->disconnect_outputs(NULL);
2063         
2064         /* get rid of it from the dead wood collection in the route list manager */
2065
2066         /* XXX i think this is unsafe as it currently stands, but i am not sure. (pd, october 2nd, 2006) */
2067
2068         routes.flush ();
2069
2070         /* try to cause everyone to drop their references */
2071
2072         route->drop_references ();
2073
2074         /* save the new state of the world */
2075
2076         if (save_state (_current_snapshot_name)) {
2077                 save_history (_current_snapshot_name);
2078         }
2079 }       
2080
2081 void
2082 Session::route_mute_changed (void* src)
2083 {
2084         set_dirty ();
2085 }
2086
2087 void
2088 Session::route_solo_changed (void* src, boost::weak_ptr<Route> wpr)
2089 {      
2090         if (solo_update_disabled) {
2091                 // We know already
2092                 return;
2093         }
2094         
2095         bool is_track;
2096         boost::shared_ptr<Route> route = wpr.lock ();
2097
2098         if (!route) {
2099                 /* should not happen */
2100                 error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_changed")) << endmsg;
2101                 return;
2102         }
2103
2104         is_track = (boost::dynamic_pointer_cast<AudioTrack>(route) != 0);
2105         
2106         shared_ptr<RouteList> r = routes.reader ();
2107
2108         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2109                 
2110                 /* soloing a track mutes all other tracks, soloing a bus mutes all other busses */
2111                 
2112                 if (is_track) {
2113                         
2114                         /* don't mess with busses */
2115                         
2116                         if (dynamic_cast<Track*>((*i).get()) == 0) {
2117                                 continue;
2118                         }
2119                         
2120                 } else {
2121                         
2122                         /* don't mess with tracks */
2123                         
2124                         if (dynamic_cast<Track*>((*i).get()) != 0) {
2125                                 continue;
2126                         }
2127                 }
2128                 
2129                 if ((*i) != route &&
2130                     ((*i)->mix_group () == 0 ||
2131                      (*i)->mix_group () != route->mix_group () ||
2132                      !route->mix_group ()->is_active())) {
2133                         
2134                         if ((*i)->soloed()) {
2135                                 
2136                                 /* if its already soloed, and solo latching is enabled,
2137                                    then leave it as it is.
2138                                 */
2139                                 
2140                                 if (Config->get_solo_latched()) {
2141                                         continue;
2142                                 } 
2143                         }
2144                         
2145                         /* do it */
2146
2147                         solo_update_disabled = true;
2148                         (*i)->set_solo (false, src);
2149                         solo_update_disabled = false;
2150                 }
2151         }
2152         
2153         bool something_soloed = false;
2154         bool same_thing_soloed = false;
2155         bool signal = false;
2156
2157         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2158                 if ((*i)->soloed()) {
2159                         something_soloed = true;
2160                         if (dynamic_cast<Track*>((*i).get())) {
2161                                 if (is_track) {
2162                                         same_thing_soloed = true;
2163                                         break;
2164                                 }
2165                         } else {
2166                                 if (!is_track) {
2167                                         same_thing_soloed = true;
2168                                         break;
2169                                 }
2170                         }
2171                         break;
2172                 }
2173         }
2174         
2175         if (something_soloed != currently_soloing) {
2176                 signal = true;
2177                 currently_soloing = something_soloed;
2178         }
2179         
2180         modify_solo_mute (is_track, same_thing_soloed);
2181
2182         if (signal) {
2183                 SoloActive (currently_soloing);
2184         }
2185
2186         set_dirty();
2187 }
2188
2189 void
2190 Session::update_route_solo_state ()
2191 {
2192         bool mute = false;
2193         bool is_track = false;
2194         bool signal = false;
2195
2196         /* caller must hold RouteLock */
2197
2198         /* this is where we actually implement solo by changing
2199            the solo mute setting of each track.
2200         */
2201         
2202         shared_ptr<RouteList> r = routes.reader ();
2203
2204         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2205                 if ((*i)->soloed()) {
2206                         mute = true;
2207                         if (dynamic_cast<Track*>((*i).get())) {
2208                                 is_track = true;
2209                         }
2210                         break;
2211                 }
2212         }
2213
2214         if (mute != currently_soloing) {
2215                 signal = true;
2216                 currently_soloing = mute;
2217         }
2218
2219         if (!is_track && !mute) {
2220
2221                 /* nothing is soloed */
2222
2223                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2224                         (*i)->set_solo_mute (false);
2225                 }
2226                 
2227                 if (signal) {
2228                         SoloActive (false);
2229                 }
2230
2231                 return;
2232         }
2233
2234         modify_solo_mute (is_track, mute);
2235
2236         if (signal) {
2237                 SoloActive (currently_soloing);
2238         }
2239 }
2240
2241 void
2242 Session::modify_solo_mute (bool is_track, bool mute)
2243 {
2244         shared_ptr<RouteList> r = routes.reader ();
2245
2246         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2247                 
2248                 if (is_track) {
2249                         
2250                         /* only alter track solo mute */
2251                         
2252                         if (dynamic_cast<Track*>((*i).get())) {
2253                                 if ((*i)->soloed()) {
2254                                         (*i)->set_solo_mute (!mute);
2255                                 } else {
2256                                         (*i)->set_solo_mute (mute);
2257                                 }
2258                         }
2259
2260                 } else {
2261
2262                         /* only alter bus solo mute */
2263
2264                         if (!dynamic_cast<Track*>((*i).get())) {
2265
2266                                 if ((*i)->soloed()) {
2267
2268                                         (*i)->set_solo_mute (false);
2269
2270                                 } else {
2271
2272                                         /* don't mute master or control outs
2273                                            in response to another bus solo
2274                                         */
2275                                         
2276                                         if ((*i) != _master_out &&
2277                                             (*i) != _control_out) {
2278                                                 (*i)->set_solo_mute (mute);
2279                                         }
2280                                 }
2281                         }
2282
2283                 }
2284         }
2285 }       
2286
2287
2288 void
2289 Session::catch_up_on_solo ()
2290 {
2291         /* this is called after set_state() to catch the full solo
2292            state, which can't be correctly determined on a per-route
2293            basis, but needs the global overview that only the session
2294            has.
2295         */
2296         update_route_solo_state();
2297 }       
2298                 
2299 shared_ptr<Route>
2300 Session::route_by_name (string name)
2301 {
2302         shared_ptr<RouteList> r = routes.reader ();
2303
2304         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2305                 if ((*i)->name() == name) {
2306                         return *i;
2307                 }
2308         }
2309
2310         return shared_ptr<Route> ((Route*) 0);
2311 }
2312
2313 shared_ptr<Route>
2314 Session::route_by_id (PBD::ID id)
2315 {
2316         shared_ptr<RouteList> r = routes.reader ();
2317
2318         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2319                 if ((*i)->id() == id) {
2320                         return *i;
2321                 }
2322         }
2323
2324         return shared_ptr<Route> ((Route*) 0);
2325 }
2326
2327 shared_ptr<Route>
2328 Session::route_by_remote_id (uint32_t id)
2329 {
2330         shared_ptr<RouteList> r = routes.reader ();
2331
2332         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2333                 if ((*i)->remote_control_id() == id) {
2334                         return *i;
2335                 }
2336         }
2337
2338         return shared_ptr<Route> ((Route*) 0);
2339 }
2340
2341 void
2342 Session::find_current_end ()
2343 {
2344         if (_state_of_the_state & Loading) {
2345                 return;
2346         }
2347
2348         nframes_t max = get_maximum_extent ();
2349
2350         if (max > end_location->end()) {
2351                 end_location->set_end (max);
2352                 set_dirty();
2353                 DurationChanged(); /* EMIT SIGNAL */
2354         }
2355 }
2356
2357 nframes_t
2358 Session::get_maximum_extent () const
2359 {
2360         nframes_t max = 0;
2361         nframes_t me; 
2362
2363         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2364
2365         for (DiskstreamList::const_iterator i = dsl->begin(); i != dsl->end(); ++i) {
2366                 boost::shared_ptr<Playlist> pl = (*i)->playlist();
2367                 if ((me = pl->get_maximum_extent()) > max) {
2368                         max = me;
2369                 }
2370         }
2371
2372         return max;
2373 }
2374
2375 boost::shared_ptr<Diskstream>
2376 Session::diskstream_by_name (string name)
2377 {
2378         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2379
2380         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
2381                 if ((*i)->name() == name) {
2382                         return *i;
2383                 }
2384         }
2385
2386         return boost::shared_ptr<Diskstream>((Diskstream*) 0);
2387 }
2388
2389 boost::shared_ptr<Diskstream>
2390 Session::diskstream_by_id (const PBD::ID& id)
2391 {
2392         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2393
2394         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
2395                 if ((*i)->id() == id) {
2396                         return *i;
2397                 }
2398         }
2399
2400         return boost::shared_ptr<Diskstream>((Diskstream*) 0);
2401 }
2402
2403 /* Region management */
2404
2405 string
2406 Session::new_region_name (string old)
2407 {
2408         string::size_type last_period;
2409         uint32_t number;
2410         string::size_type len = old.length() + 64;
2411         char buf[len];
2412
2413         if ((last_period = old.find_last_of ('.')) == string::npos) {
2414                 
2415                 /* no period present - add one explicitly */
2416
2417                 old += '.';
2418                 last_period = old.length() - 1;
2419                 number = 0;
2420
2421         } else {
2422
2423                 number = atoi (old.substr (last_period+1).c_str());
2424
2425         }
2426
2427         while (number < (UINT_MAX-1)) {
2428
2429                 RegionList::const_iterator i;
2430                 string sbuf;
2431
2432                 number++;
2433
2434                 snprintf (buf, len, "%s%" PRIu32, old.substr (0, last_period + 1).c_str(), number);
2435                 sbuf = buf;
2436
2437                 for (i = regions.begin(); i != regions.end(); ++i) {
2438                         if (i->second->name() == sbuf) {
2439                                 break;
2440                         }
2441                 }
2442                 
2443                 if (i == regions.end()) {
2444                         break;
2445                 }
2446         }
2447
2448         if (number != (UINT_MAX-1)) {
2449                 return buf;
2450         } 
2451
2452         error << string_compose (_("cannot create new name for region \"%1\""), old) << endmsg;
2453         return old;
2454 }
2455
2456 int
2457 Session::region_name (string& result, string base, bool newlevel) const
2458 {
2459         char buf[16];
2460         string subbase;
2461
2462         assert(base.find("/") == string::npos);
2463
2464         if (base == "") {
2465                 
2466                 Glib::Mutex::Lock lm (region_lock);
2467
2468                 snprintf (buf, sizeof (buf), "%d", (int)regions.size() + 1);
2469
2470                 
2471                 result = "region.";
2472                 result += buf;
2473
2474         } else {
2475
2476                 /* XXX this is going to be slow. optimize me later */
2477                 
2478                 if (newlevel) {
2479                         subbase = base;
2480                 } else {
2481                         string::size_type pos;
2482
2483                         pos = base.find_last_of ('.');
2484
2485                         /* pos may be npos, but then we just use entire base */
2486
2487                         subbase = base.substr (0, pos);
2488
2489                 }
2490
2491                 bool name_taken = true;
2492                 
2493                 {
2494                         Glib::Mutex::Lock lm (region_lock);
2495                         
2496                         for (int n = 1; n < 5000; ++n) {
2497                                 
2498                                 result = subbase;
2499                                 snprintf (buf, sizeof (buf), ".%d", n);
2500                                 result += buf;
2501                                 
2502                                 name_taken = false;
2503                                 
2504                                 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2505                                         if (i->second->name() == result) {
2506                                                 name_taken = true;
2507                                                 break;
2508                                         }
2509                                 }
2510                                 
2511                                 if (!name_taken) {
2512                                         break;
2513                                 }
2514                         }
2515                 }
2516                         
2517                 if (name_taken) {
2518                         fatal << string_compose(_("too many regions with names like %1"), base) << endmsg;
2519                         /*NOTREACHED*/
2520                 }
2521         }
2522         return 0;
2523 }       
2524
2525 void
2526 Session::add_region (boost::shared_ptr<Region> region)
2527 {
2528         boost::shared_ptr<Region> other;
2529         bool added = false;
2530
2531         { 
2532                 Glib::Mutex::Lock lm (region_lock);
2533
2534                 RegionList::iterator x;
2535
2536                 for (x = regions.begin(); x != regions.end(); ++x) {
2537
2538                         other = x->second;
2539
2540                         if (region->region_list_equivalent (other)) {
2541                                 break;
2542                         }
2543                 }
2544
2545                 if (x == regions.end()) {
2546
2547                         pair<RegionList::key_type,RegionList::mapped_type> entry;
2548
2549                         entry.first = region->id();
2550                         entry.second = region;
2551
2552                         pair<RegionList::iterator,bool> x = regions.insert (entry);
2553
2554
2555                         if (!x.second) {
2556                                 return;
2557                         }
2558
2559                         added = true;
2560                 } 
2561
2562         }
2563
2564         /* mark dirty because something has changed even if we didn't
2565            add the region to the region list.
2566         */
2567         
2568         set_dirty();
2569         
2570         if (added) {
2571                 region->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_region), boost::weak_ptr<Region>(region)));
2572                 region->StateChanged.connect (sigc::bind (mem_fun (*this, &Session::region_changed), boost::weak_ptr<Region>(region)));
2573                 RegionAdded (region); /* EMIT SIGNAL */
2574         }
2575 }
2576
2577 void
2578 Session::region_changed (Change what_changed, boost::weak_ptr<Region> weak_region)
2579 {
2580         boost::shared_ptr<Region> region (weak_region.lock ());
2581
2582         if (!region) {
2583                 return;
2584         }
2585
2586         if (what_changed & Region::HiddenChanged) {
2587                 /* relay hidden changes */
2588                 RegionHiddenChange (region);
2589         }
2590 }
2591
2592 void
2593 Session::remove_region (boost::weak_ptr<Region> weak_region)
2594 {
2595         RegionList::iterator i;
2596         boost::shared_ptr<Region> region (weak_region.lock ());
2597
2598         if (!region) {
2599                 return;
2600         }
2601
2602         bool removed = false;
2603
2604         { 
2605                 Glib::Mutex::Lock lm (region_lock);
2606
2607                 if ((i = regions.find (region->id())) != regions.end()) {
2608                         regions.erase (i);
2609                         removed = true;
2610                 }
2611         }
2612
2613         /* mark dirty because something has changed even if we didn't
2614            remove the region from the region list.
2615         */
2616
2617         set_dirty();
2618
2619         if (removed) {
2620                  RegionRemoved(region); /* EMIT SIGNAL */
2621         }
2622 }
2623
2624 boost::shared_ptr<Region>
2625 Session::find_whole_file_parent (boost::shared_ptr<Region const> child)
2626 {
2627         RegionList::iterator i;
2628         boost::shared_ptr<Region> region;
2629         
2630         Glib::Mutex::Lock lm (region_lock);
2631
2632         for (i = regions.begin(); i != regions.end(); ++i) {
2633
2634                 region = i->second;
2635
2636                 if (region->whole_file()) {
2637
2638                         if (child->source_equivalent (region)) {
2639                                 return region;
2640                         }
2641                 }
2642         } 
2643
2644         return boost::shared_ptr<Region> ();
2645 }       
2646
2647 void
2648 Session::find_equivalent_playlist_regions (boost::shared_ptr<Region> region, vector<boost::shared_ptr<Region> >& result)
2649 {
2650         for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i)
2651                 (*i)->get_region_list_equivalent_regions (region, result);
2652 }
2653
2654 int
2655 Session::destroy_region (boost::shared_ptr<Region> region)
2656 {
2657         vector<boost::shared_ptr<Source> > srcs;
2658                 
2659         {
2660                 boost::shared_ptr<AudioRegion> aregion;
2661                 
2662                 if ((aregion = boost::dynamic_pointer_cast<AudioRegion> (region)) == 0) {
2663                         return 0;
2664                 }
2665                 
2666                 if (aregion->playlist()) {
2667                         aregion->playlist()->destroy_region (region);
2668                 }
2669                 
2670                 for (uint32_t n = 0; n < aregion->n_channels(); ++n) {
2671                         srcs.push_back (aregion->source (n));
2672                 }
2673         }
2674
2675         region->drop_references ();
2676
2677         for (vector<boost::shared_ptr<Source> >::iterator i = srcs.begin(); i != srcs.end(); ++i) {
2678
2679                 if (!(*i)->used()) {
2680                         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*i);
2681                         
2682                         if (afs) {
2683                                 (afs)->mark_for_remove ();
2684                         }
2685                         
2686                         (*i)->drop_references ();
2687                         
2688                         cerr << "source was not used by any playlist\n";
2689                 }
2690         }
2691
2692         return 0;
2693 }
2694
2695 int
2696 Session::destroy_regions (list<boost::shared_ptr<Region> > regions)
2697 {
2698         for (list<boost::shared_ptr<Region> >::iterator i = regions.begin(); i != regions.end(); ++i) {
2699                 destroy_region (*i);
2700         }
2701         return 0;
2702 }
2703
2704 int
2705 Session::remove_last_capture ()
2706 {
2707         list<boost::shared_ptr<Region> > r;
2708         
2709         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2710         
2711         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
2712                 list<boost::shared_ptr<Region> >& l = (*i)->last_capture_regions();
2713                 
2714                 if (!l.empty()) {
2715                         r.insert (r.end(), l.begin(), l.end());
2716                         l.clear ();
2717                 }
2718         }
2719
2720         destroy_regions (r);
2721         return 0;
2722 }
2723
2724 int
2725 Session::remove_region_from_region_list (boost::shared_ptr<Region> r)
2726 {
2727         remove_region (r);
2728         return 0;
2729 }
2730
2731 /* Source Management */
2732 void
2733 Session::add_source (boost::shared_ptr<Source> source)
2734 {
2735         pair<SourceMap::key_type, SourceMap::mapped_type> entry;
2736         pair<SourceMap::iterator,bool> result;
2737
2738         entry.first = source->id();
2739         entry.second = source;
2740         
2741         {
2742                 Glib::Mutex::Lock lm (source_lock);
2743                 result = sources.insert (entry);
2744         }
2745
2746         if (result.second) {
2747                 source->GoingAway.connect (sigc::bind (mem_fun (this, &Session::remove_source), boost::weak_ptr<Source> (source)));
2748                 set_dirty();
2749         }
2750 }
2751
2752 void
2753 Session::remove_source (boost::weak_ptr<Source> src)
2754 {
2755         SourceMap::iterator i;
2756         boost::shared_ptr<Source> source = src.lock();
2757
2758         if (!source) {
2759                 return;
2760         } 
2761
2762         { 
2763                 Glib::Mutex::Lock lm (source_lock);
2764                 
2765                 { 
2766                         Glib::Mutex::Lock lm (source_lock);
2767                         
2768                         if ((i = sources.find (source->id())) != sources.end()) {
2769                                 sources.erase (i);
2770                         } 
2771                 }
2772         }
2773         
2774         if (!_state_of_the_state & InCleanup) {
2775                 
2776                 /* save state so we don't end up with a session file
2777                    referring to non-existent sources.
2778                 */
2779                 
2780                 save_state (_current_snapshot_name);
2781         }
2782 }
2783
2784 boost::shared_ptr<Source>
2785 Session::source_by_id (const PBD::ID& id)
2786 {
2787         Glib::Mutex::Lock lm (source_lock);
2788         SourceMap::iterator i;
2789         boost::shared_ptr<Source> source;
2790
2791         if ((i = sources.find (id)) != sources.end()) {
2792                 source = i->second;
2793         }
2794
2795         /* XXX search MIDI or other searches here */
2796         
2797         return source;
2798 }
2799
2800 string
2801 Session::peak_path_from_audio_path (string audio_path) const
2802 {
2803         string res;
2804
2805         res = peak_dir ();
2806         res += PBD::basename_nosuffix (audio_path);
2807         res += ".peak";
2808
2809         return res;
2810 }
2811
2812 string
2813 Session::change_audio_path_by_name (string path, string oldname, string newname, bool destructive)
2814 {
2815         string look_for;
2816         string old_basename = PBD::basename_nosuffix (oldname);
2817         string new_legalized = legalize_for_path (newname);
2818
2819         /* note: we know (or assume) the old path is already valid */
2820
2821         if (destructive) {
2822                 
2823                 /* destructive file sources have a name of the form:
2824
2825                     /path/to/Tnnnn-NAME(%[LR])?.wav
2826                   
2827                     the task here is to replace NAME with the new name.
2828                 */
2829                 
2830                 /* find last slash */
2831
2832                 string dir;
2833                 string prefix;
2834                 string::size_type slash;
2835                 string::size_type dash;
2836
2837                 if ((slash = path.find_last_of ('/')) == string::npos) {
2838                         return "";
2839                 }
2840
2841                 dir = path.substr (0, slash+1);
2842
2843                 /* '-' is not a legal character for the NAME part of the path */
2844
2845                 if ((dash = path.find_last_of ('-')) == string::npos) {
2846                         return "";
2847                 }
2848
2849                 prefix = path.substr (slash+1, dash-(slash+1));
2850
2851                 path = dir;
2852                 path += prefix;
2853                 path += '-';
2854                 path += new_legalized;
2855                 path += ".wav";  /* XXX gag me with a spoon */
2856                 
2857         } else {
2858                 
2859                 /* non-destructive file sources have a name of the form:
2860
2861                     /path/to/NAME-nnnnn(%[LR])?.wav
2862                   
2863                     the task here is to replace NAME with the new name.
2864                 */
2865                 
2866                 string dir;
2867                 string suffix;
2868                 string::size_type slash;
2869                 string::size_type dash;
2870                 string::size_type postfix;
2871
2872                 /* find last slash */
2873
2874                 if ((slash = path.find_last_of ('/')) == string::npos) {
2875                         return "";
2876                 }
2877
2878                 dir = path.substr (0, slash+1);
2879
2880                 /* '-' is not a legal character for the NAME part of the path */
2881
2882                 if ((dash = path.find_last_of ('-')) == string::npos) {
2883                         return "";
2884                 }
2885
2886                 suffix = path.substr (dash+1);
2887                 
2888                 // Suffix is now everything after the dash. Now we need to eliminate
2889                 // the nnnnn part, which is done by either finding a '%' or a '.'
2890
2891                 postfix = suffix.find_last_of ("%");
2892                 if (postfix == string::npos) {
2893                         postfix = suffix.find_last_of ('.');
2894                 }
2895
2896                 if (postfix != string::npos) {
2897                         suffix = suffix.substr (postfix);
2898                 } else {
2899                         error << "Logic error in Session::change_audio_path_by_name(), please report to the developers" << endl;
2900                         return "";
2901                 }
2902
2903                 const uint32_t limit = 10000;
2904                 char buf[PATH_MAX+1];
2905
2906                 for (uint32_t cnt = 1; cnt <= limit; ++cnt) {
2907
2908                         snprintf (buf, sizeof(buf), "%s%s-%u%s", dir.c_str(), newname.c_str(), cnt, suffix.c_str());
2909
2910                         if (access (buf, F_OK) != 0) {
2911                                 path = buf;
2912                                 break;
2913                         }
2914                         path = "";
2915                 }
2916
2917                 if (path == "") {
2918                         error << "FATAL ERROR! Could not find a " << endl;
2919                 }
2920
2921         }
2922
2923         return path;
2924 }
2925
2926 string
2927 Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool destructive)
2928 {
2929         string spath;
2930         uint32_t cnt;
2931         char buf[PATH_MAX+1];
2932         const uint32_t limit = 10000;
2933         string legalized;
2934
2935         buf[0] = '\0';
2936         legalized = legalize_for_path (name);
2937
2938         /* find a "version" of the file name that doesn't exist in
2939            any of the possible directories.
2940         */
2941
2942         for (cnt = (destructive ? ++destructive_index : 1); cnt <= limit; ++cnt) {
2943
2944                 vector<space_and_path>::iterator i;
2945                 uint32_t existing = 0;
2946
2947                 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2948
2949                         spath = (*i).path;
2950
2951                         spath += sound_dir (false);
2952
2953                         if (destructive) {
2954                                 if (nchan < 2) {
2955                                         snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav", spath.c_str(), cnt, legalized.c_str());
2956                                 } else if (nchan == 2) {
2957                                         if (chan == 0) {
2958                                                 snprintf (buf, sizeof(buf), "%s/T%04d-%s%%L.wav", spath.c_str(), cnt, legalized.c_str());
2959                                         } else {
2960                                                 snprintf (buf, sizeof(buf), "%s/T%04d-%s%%R.wav", spath.c_str(), cnt, legalized.c_str());
2961                                         }
2962                                 } else if (nchan < 26) {
2963                                         snprintf (buf, sizeof(buf), "%s/T%04d-%s%%%c.wav", spath.c_str(), cnt, legalized.c_str(), 'a' + chan);
2964                                 } else {
2965                                         snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav", spath.c_str(), cnt, legalized.c_str());
2966                                 }
2967
2968                         } else {
2969
2970                                 spath += '/';
2971                                 spath += legalized;
2972
2973                                 if (nchan < 2) {
2974                                         snprintf (buf, sizeof(buf), "%s-%u.wav", spath.c_str(), cnt);
2975                                 } else if (nchan == 2) {
2976                                         if (chan == 0) {
2977                                                 snprintf (buf, sizeof(buf), "%s-%u%%L.wav", spath.c_str(), cnt);
2978                                         } else {
2979                                                 snprintf (buf, sizeof(buf), "%s-%u%%R.wav", spath.c_str(), cnt);
2980                                         }
2981                                 } else if (nchan < 26) {
2982                                         snprintf (buf, sizeof(buf), "%s-%u%%%c.wav", spath.c_str(), cnt, 'a' + chan);
2983                                 } else {
2984                                         snprintf (buf, sizeof(buf), "%s-%u.wav", spath.c_str(), cnt);
2985                                 }
2986                         }
2987
2988                         if (g_file_test (buf, G_FILE_TEST_EXISTS)) {
2989                                 existing++;
2990                         } 
2991
2992                 }
2993
2994                 if (existing == 0) {
2995                         break;
2996                 }
2997
2998                 if (cnt > limit) {
2999                         error << string_compose(_("There are already %1 recordings for %2, which I consider too many."), limit, name) << endmsg;
3000                         destroy ();
3001                         throw failed_constructor();
3002                 }
3003         }
3004
3005         /* we now have a unique name for the file, but figure out where to
3006            actually put it.
3007         */
3008
3009         string foo = buf;
3010
3011         spath = discover_best_sound_dir ();
3012         spath += '/';
3013
3014         string::size_type pos = foo.find_last_of ('/');
3015         
3016         if (pos == string::npos) {
3017                 spath += foo;
3018         } else {
3019                 spath += foo.substr (pos + 1);
3020         }
3021
3022         return spath;
3023 }
3024
3025 boost::shared_ptr<AudioFileSource>
3026 Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bool destructive)
3027 {
3028         string spath = audio_path_from_name (ds.name(), ds.n_channels().get(DataType::AUDIO), chan, destructive);
3029         return boost::dynamic_pointer_cast<AudioFileSource> (
3030                 SourceFactory::createWritable (DataType::AUDIO, *this, spath, destructive, frame_rate()));
3031 }
3032
3033 // FIXME: _terrible_ code duplication
3034 string
3035 Session::change_midi_path_by_name (string path, string oldname, string newname, bool destructive)
3036 {
3037         string look_for;
3038         string old_basename = PBD::basename_nosuffix (oldname);
3039         string new_legalized = legalize_for_path (newname);
3040
3041         /* note: we know (or assume) the old path is already valid */
3042
3043         if (destructive) {
3044                 
3045                 /* destructive file sources have a name of the form:
3046
3047                     /path/to/Tnnnn-NAME(%[LR])?.wav
3048                   
3049                     the task here is to replace NAME with the new name.
3050                 */
3051                 
3052                 /* find last slash */
3053
3054                 string dir;
3055                 string prefix;
3056                 string::size_type slash;
3057                 string::size_type dash;
3058
3059                 if ((slash = path.find_last_of ('/')) == string::npos) {
3060                         return "";
3061                 }
3062
3063                 dir = path.substr (0, slash+1);
3064
3065                 /* '-' is not a legal character for the NAME part of the path */
3066
3067                 if ((dash = path.find_last_of ('-')) == string::npos) {
3068                         return "";
3069                 }
3070
3071                 prefix = path.substr (slash+1, dash-(slash+1));
3072
3073                 path = dir;
3074                 path += prefix;
3075                 path += '-';
3076                 path += new_legalized;
3077                 path += ".mid";  /* XXX gag me with a spoon */
3078                 
3079         } else {
3080                 
3081                 /* non-destructive file sources have a name of the form:
3082
3083                     /path/to/NAME-nnnnn(%[LR])?.wav
3084                   
3085                     the task here is to replace NAME with the new name.
3086                 */
3087                 
3088                 string dir;
3089                 string suffix;
3090                 string::size_type slash;
3091                 string::size_type dash;
3092                 string::size_type postfix;
3093
3094                 /* find last slash */
3095
3096                 if ((slash = path.find_last_of ('/')) == string::npos) {
3097                         return "";
3098                 }
3099
3100                 dir = path.substr (0, slash+1);
3101
3102                 /* '-' is not a legal character for the NAME part of the path */
3103
3104                 if ((dash = path.find_last_of ('-')) == string::npos) {
3105                         return "";
3106                 }
3107
3108                 suffix = path.substr (dash+1);
3109                 
3110                 // Suffix is now everything after the dash. Now we need to eliminate
3111                 // the nnnnn part, which is done by either finding a '%' or a '.'
3112
3113                 postfix = suffix.find_last_of ("%");
3114                 if (postfix == string::npos) {
3115                         postfix = suffix.find_last_of ('.');
3116                 }
3117
3118                 if (postfix != string::npos) {
3119                         suffix = suffix.substr (postfix);
3120                 } else {
3121                         error << "Logic error in Session::change_midi_path_by_name(), please report to the developers" << endl;
3122                         return "";
3123                 }
3124
3125                 const uint32_t limit = 10000;
3126                 char buf[PATH_MAX+1];
3127
3128                 for (uint32_t cnt = 1; cnt <= limit; ++cnt) {
3129
3130                         snprintf (buf, sizeof(buf), "%s%s-%u%s", dir.c_str(), newname.c_str(), cnt, suffix.c_str());
3131
3132                         if (access (buf, F_OK) != 0) {
3133                                 path = buf;
3134                                 break;
3135                         }
3136                         path = "";
3137                 }
3138
3139                 if (path == "") {
3140                         error << "FATAL ERROR! Could not find a " << endl;
3141                 }
3142
3143         }
3144
3145         return path;
3146 }
3147
3148 string
3149 Session::midi_path_from_name (string name)
3150 {
3151         string spath;
3152         uint32_t cnt;
3153         char buf[PATH_MAX+1];
3154         const uint32_t limit = 10000;
3155         string legalized;
3156
3157         buf[0] = '\0';
3158         legalized = legalize_for_path (name);
3159
3160         /* find a "version" of the file name that doesn't exist in
3161            any of the possible directories.
3162         */
3163
3164         for (cnt = 1; cnt <= limit; ++cnt) {
3165
3166                 vector<space_and_path>::iterator i;
3167                 uint32_t existing = 0;
3168
3169                 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3170
3171                         spath = (*i).path;
3172
3173                         // FIXME: different directory from audio?
3174                         spath += sound_dir(false) + "/" + legalized;
3175
3176                         snprintf (buf, sizeof(buf), "%s-%u.mid", spath.c_str(), cnt);
3177
3178                         if (g_file_test (buf, G_FILE_TEST_EXISTS)) {
3179                                 existing++;
3180                         } 
3181                 }
3182
3183                 if (existing == 0) {
3184                         break;
3185                 }
3186
3187                 if (cnt > limit) {
3188                         error << string_compose(_("There are already %1 recordings for %2, which I consider too many."), limit, name) << endmsg;
3189                         throw failed_constructor();
3190                 }
3191         }
3192
3193         /* we now have a unique name for the file, but figure out where to
3194            actually put it.
3195         */
3196
3197         string foo = buf;
3198
3199         // FIXME: different directory than audio?
3200         spath = discover_best_sound_dir ();
3201         spath += '/';
3202
3203         string::size_type pos = foo.find_last_of ('/');
3204         
3205         if (pos == string::npos) {
3206                 spath += foo;
3207         } else {
3208                 spath += foo.substr (pos + 1);
3209         }
3210
3211         return spath;
3212 }
3213
3214 boost::shared_ptr<MidiSource>
3215 Session::create_midi_source_for_session (MidiDiskstream& ds)
3216 {
3217         string spath = midi_path_from_name (ds.name());
3218         
3219         return boost::dynamic_pointer_cast<SMFSource> (SourceFactory::createWritable (DataType::MIDI, *this, spath, false, frame_rate()));
3220 }
3221
3222
3223 /* Playlist management */
3224
3225 boost::shared_ptr<Playlist>
3226 Session::playlist_by_name (string name)
3227 {
3228         Glib::Mutex::Lock lm (playlist_lock);
3229         for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
3230                 if ((*i)->name() == name) {
3231                         return* i;
3232                 }
3233         }
3234         for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
3235                 if ((*i)->name() == name) {
3236                         return* i;
3237                 }
3238         }
3239
3240         return boost::shared_ptr<Playlist>();
3241 }
3242
3243 void
3244 Session::add_playlist (boost::shared_ptr<Playlist> playlist)
3245 {
3246         if (playlist->hidden()) {
3247                 return;
3248         }
3249
3250         { 
3251                 Glib::Mutex::Lock lm (playlist_lock);
3252                 if (find (playlists.begin(), playlists.end(), playlist) == playlists.end()) {
3253                         playlists.insert (playlists.begin(), playlist);
3254                         playlist->InUse.connect (sigc::bind (mem_fun (*this, &Session::track_playlist), boost::weak_ptr<Playlist>(playlist)));
3255                         playlist->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_playlist), boost::weak_ptr<Playlist>(playlist)));
3256                 }
3257         }
3258
3259         set_dirty();
3260
3261         PlaylistAdded (playlist); /* EMIT SIGNAL */
3262 }
3263
3264 void
3265 Session::get_playlists (vector<boost::shared_ptr<Playlist> >& s)
3266 {
3267         { 
3268                 Glib::Mutex::Lock lm (playlist_lock);
3269                 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
3270                         s.push_back (*i);
3271                 }
3272                 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
3273                         s.push_back (*i);
3274                 }
3275         }
3276 }
3277
3278 void
3279 Session::track_playlist (bool inuse, boost::weak_ptr<Playlist> wpl)
3280 {
3281         boost::shared_ptr<Playlist> pl(wpl.lock());
3282
3283         if (!pl) {
3284                 return;
3285         }
3286
3287         PlaylistList::iterator x;
3288
3289         if (pl->hidden()) {
3290                 /* its not supposed to be visible */
3291                 return;
3292         }
3293
3294         { 
3295                 Glib::Mutex::Lock lm (playlist_lock);
3296
3297                 if (!inuse) {
3298
3299                         unused_playlists.insert (pl);
3300                         
3301                         if ((x = playlists.find (pl)) != playlists.end()) {
3302                                 playlists.erase (x);
3303                         }
3304
3305                         
3306                 } else {
3307
3308                         playlists.insert (pl);
3309                         
3310                         if ((x = unused_playlists.find (pl)) != unused_playlists.end()) {
3311                                 unused_playlists.erase (x);
3312                         }
3313                 }
3314         }
3315 }
3316
3317 void
3318 Session::remove_playlist (boost::weak_ptr<Playlist> weak_playlist)
3319 {
3320         if (_state_of_the_state & Deletion) {
3321                 return;
3322         }
3323
3324         boost::shared_ptr<Playlist> playlist (weak_playlist.lock());
3325
3326         if (!playlist) {
3327                 return;
3328         }
3329
3330         { 
3331                 Glib::Mutex::Lock lm (playlist_lock);
3332
3333                 PlaylistList::iterator i;
3334
3335                 i = find (playlists.begin(), playlists.end(), playlist);
3336                 if (i != playlists.end()) {
3337                         playlists.erase (i);
3338                 }
3339
3340                 i = find (unused_playlists.begin(), unused_playlists.end(), playlist);
3341                 if (i != unused_playlists.end()) {
3342                         unused_playlists.erase (i);
3343                 }
3344                 
3345         }
3346
3347         set_dirty();
3348
3349         PlaylistRemoved (playlist); /* EMIT SIGNAL */
3350 }
3351
3352 void 
3353 Session::set_audition (boost::shared_ptr<Region> r)
3354 {
3355         pending_audition_region = r;
3356         post_transport_work = PostTransportWork (post_transport_work | PostTransportAudition);
3357         schedule_butler_transport_work ();
3358 }
3359
3360 void
3361 Session::audition_playlist ()
3362 {
3363         Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0);
3364         ev->region.reset ();
3365         queue_event (ev);
3366 }
3367
3368 void
3369 Session::non_realtime_set_audition ()
3370 {
3371         if (!pending_audition_region) {
3372                 auditioner->audition_current_playlist ();
3373         } else {
3374                 auditioner->audition_region (pending_audition_region);
3375                 pending_audition_region.reset ();
3376         }
3377         AuditionActive (true); /* EMIT SIGNAL */
3378 }
3379
3380 void
3381 Session::audition_region (boost::shared_ptr<Region> r)
3382 {
3383         Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0);
3384         ev->region = r;
3385         queue_event (ev);
3386 }
3387
3388 void
3389 Session::cancel_audition ()
3390 {
3391         if (auditioner->active()) {
3392                 auditioner->cancel_audition ();
3393                 AuditionActive (false); /* EMIT SIGNAL */
3394         }
3395 }
3396
3397 bool
3398 Session::RoutePublicOrderSorter::operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b)
3399 {
3400         return a->order_key(N_("signal")) < b->order_key(N_("signal"));
3401 }
3402
3403 void
3404 Session::remove_empty_sounds ()
3405 {
3406         PathScanner scanner;
3407
3408         vector<string *>* possible_audiofiles = scanner (sound_dir(), "\\.(wav|aiff|caf|w64)$", false, true);
3409         
3410         Glib::Mutex::Lock lm (source_lock);
3411         
3412         regex_t compiled_tape_track_pattern;
3413         int err;
3414
3415         if ((err = regcomp (&compiled_tape_track_pattern, "/T[0-9][0-9][0-9][0-9]-", REG_EXTENDED|REG_NOSUB))) {
3416
3417                 char msg[256];
3418                 
3419                 regerror (err, &compiled_tape_track_pattern, msg, sizeof (msg));
3420                 
3421                 error << string_compose (_("Cannot compile tape track regexp for use (%1)"), msg) << endmsg;
3422                 return;
3423         }
3424
3425         for (vector<string *>::iterator i = possible_audiofiles->begin(); i != possible_audiofiles->end(); ++i) {
3426                 
3427                 /* never remove files that appear to be a tape track */
3428
3429                 if (regexec (&compiled_tape_track_pattern, (*i)->c_str(), 0, 0, 0) == 0) {
3430                         delete *i;
3431                         continue;
3432                 }
3433                         
3434                 if (AudioFileSource::is_empty (*this, *(*i))) {
3435
3436                         unlink ((*i)->c_str());
3437                         
3438                         string peak_path = peak_path_from_audio_path (**i);
3439                         unlink (peak_path.c_str());
3440                 }
3441
3442                 delete* i;
3443         }
3444
3445         delete possible_audiofiles;
3446 }
3447
3448 bool
3449 Session::is_auditioning () const
3450 {
3451         /* can be called before we have an auditioner object */
3452         if (auditioner) {
3453                 return auditioner->active();
3454         } else {
3455                 return false;
3456         }
3457 }
3458
3459 void
3460 Session::set_all_solo (bool yn)
3461 {
3462         shared_ptr<RouteList> r = routes.reader ();
3463         
3464         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3465                 if (!(*i)->hidden()) {
3466                         (*i)->set_solo (yn, this);
3467                 }
3468         }
3469
3470         set_dirty();
3471 }
3472                 
3473 void
3474 Session::set_all_mute (bool yn)
3475 {
3476         shared_ptr<RouteList> r = routes.reader ();
3477         
3478         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3479                 if (!(*i)->hidden()) {
3480                         (*i)->set_mute (yn, this);
3481                 }
3482         }
3483
3484         set_dirty();
3485 }
3486                 
3487 uint32_t
3488 Session::n_diskstreams () const
3489 {
3490         uint32_t n = 0;
3491
3492         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3493
3494         for (DiskstreamList::const_iterator i = dsl->begin(); i != dsl->end(); ++i) {
3495                 if (!(*i)->hidden()) {
3496                         n++;
3497                 }
3498         }
3499         return n;
3500 }
3501
3502 void
3503 Session::graph_reordered ()
3504 {
3505         /* don't do this stuff if we are setting up connections
3506            from a set_state() call.
3507         */
3508
3509         if (_state_of_the_state & InitialConnecting) {
3510                 return;
3511         }
3512         
3513         /* every track/bus asked for this to be handled but it was deferred because
3514            we were connecting. do it now.
3515         */
3516
3517         request_input_change_handling ();
3518
3519         resort_routes ();
3520
3521         /* force all diskstreams to update their capture offset values to 
3522            reflect any changes in latencies within the graph.
3523         */
3524         
3525         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3526
3527         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
3528                 (*i)->set_capture_offset ();
3529         }
3530 }
3531
3532 void
3533 Session::record_disenable_all ()
3534 {
3535         record_enable_change_all (false);
3536 }
3537
3538 void
3539 Session::record_enable_all ()
3540 {
3541         record_enable_change_all (true);
3542 }
3543
3544 void
3545 Session::record_enable_change_all (bool yn)
3546 {
3547         shared_ptr<RouteList> r = routes.reader ();
3548         
3549         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3550                 Track* at;
3551
3552                 if ((at = dynamic_cast<Track*>((*i).get())) != 0) {
3553                         at->set_record_enable (yn, this);
3554                 }
3555         }
3556         
3557         /* since we don't keep rec-enable state, don't mark session dirty */
3558 }
3559
3560 void
3561 Session::add_redirect (Redirect* redirect)
3562 {
3563         Send* send;
3564         Insert* insert;
3565         PortInsert* port_insert;
3566         PluginInsert* plugin_insert;
3567
3568         if ((insert = dynamic_cast<Insert *> (redirect)) != 0) {
3569                 if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
3570                         _port_inserts.insert (_port_inserts.begin(), port_insert);
3571                 } else if ((plugin_insert = dynamic_cast<PluginInsert *> (insert)) != 0) {
3572                         _plugin_inserts.insert (_plugin_inserts.begin(), plugin_insert);
3573                 } else {
3574                         fatal << _("programming error: unknown type of Insert created!") << endmsg;
3575                         /*NOTREACHED*/
3576                 }
3577         } else if ((send = dynamic_cast<Send *> (redirect)) != 0) {
3578                 _sends.insert (_sends.begin(), send);
3579         } else {
3580                 fatal << _("programming error: unknown type of Redirect created!") << endmsg;
3581                 /*NOTREACHED*/
3582         }
3583
3584         redirect->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_redirect), redirect));
3585
3586         set_dirty();
3587 }
3588
3589 void
3590 Session::remove_redirect (Redirect* redirect)
3591 {
3592         Send* send;
3593         Insert* insert;
3594         PortInsert* port_insert;
3595         PluginInsert* plugin_insert;
3596         
3597         if ((insert = dynamic_cast<Insert *> (redirect)) != 0) {
3598                 if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
3599                         list<PortInsert*>::iterator x = find (_port_inserts.begin(), _port_inserts.end(), port_insert);
3600                         if (x != _port_inserts.end()) {
3601                                 insert_bitset[port_insert->bit_slot()] = false;
3602                                 _port_inserts.erase (x);
3603                         }
3604                 } else if ((plugin_insert = dynamic_cast<PluginInsert *> (insert)) != 0) {
3605                         _plugin_inserts.remove (plugin_insert);
3606                 } else {
3607                         fatal << string_compose (_("programming error: %1"),
3608                                                  X_("unknown type of Insert deleted!")) 
3609                               << endmsg;
3610                         /*NOTREACHED*/
3611                 }
3612         } else if ((send = dynamic_cast<Send *> (redirect)) != 0) {
3613                 list<Send*>::iterator x = find (_sends.begin(), _sends.end(), send);
3614                 if (x != _sends.end()) {
3615                         send_bitset[send->bit_slot()] = false;
3616                         _sends.erase (x);
3617                 }
3618         } else {
3619                 fatal << _("programming error: unknown type of Redirect deleted!") << endmsg;
3620                 /*NOTREACHED*/
3621         }
3622
3623         set_dirty();
3624 }
3625
3626 nframes_t
3627 Session::available_capture_duration ()
3628 {
3629         float sample_bytes_on_disk = 4.0; // keep gcc happy
3630
3631         switch (Config->get_native_file_data_format()) {
3632         case FormatFloat:
3633                 sample_bytes_on_disk = 4;
3634                 break;
3635
3636         case FormatInt24:
3637                 sample_bytes_on_disk = 3;
3638                 break;
3639
3640         default: 
3641                 /* impossible, but keep some gcc versions happy */
3642                 fatal << string_compose (_("programming error: %1"),
3643                                          X_("illegal native file data format"))
3644                       << endmsg;
3645                 /*NOTREACHED*/
3646         }
3647
3648         double scale = 4096.0 / sample_bytes_on_disk;
3649
3650         if (_total_free_4k_blocks * scale > (double) max_frames) {
3651                 return max_frames;
3652         }
3653         
3654         return (nframes_t) floor (_total_free_4k_blocks * scale);
3655 }
3656
3657 void
3658 Session::add_connection (ARDOUR::Connection* connection)
3659 {
3660         {
3661                 Glib::Mutex::Lock guard (connection_lock);
3662                 _connections.push_back (connection);
3663         }
3664         
3665         ConnectionAdded (connection); /* EMIT SIGNAL */
3666
3667         set_dirty();
3668 }
3669
3670 void
3671 Session::remove_connection (ARDOUR::Connection* connection)
3672 {
3673         bool removed = false;
3674
3675         {
3676                 Glib::Mutex::Lock guard (connection_lock);
3677                 ConnectionList::iterator i = find (_connections.begin(), _connections.end(), connection);
3678                 
3679                 if (i != _connections.end()) {
3680                         _connections.erase (i);
3681                         removed = true;
3682                 }
3683         }
3684
3685         if (removed) {
3686                  ConnectionRemoved (connection); /* EMIT SIGNAL */
3687         }
3688
3689         set_dirty();
3690 }
3691
3692 ARDOUR::Connection *
3693 Session::connection_by_name (string name) const
3694 {
3695         Glib::Mutex::Lock lm (connection_lock);
3696
3697         for (ConnectionList::const_iterator i = _connections.begin(); i != _connections.end(); ++i) {
3698                 if ((*i)->name() == name) {
3699                         return* i;
3700                 }
3701         }
3702
3703         return 0;
3704 }
3705
3706 void
3707 Session::tempo_map_changed (Change ignored)
3708 {
3709         clear_clicks ();
3710         set_dirty ();
3711 }
3712
3713 /** Ensures that all buffers (scratch, send, silent, etc) are allocated for
3714  * the given count with the current block size.
3715  */
3716 void
3717 Session::ensure_buffers (ChanCount howmany)
3718 {
3719         // FIXME: NASTY assumption (midi block size == audio block size)
3720         _scratch_buffers->ensure_buffers(howmany, current_block_size);
3721         _send_buffers->ensure_buffers(howmany, current_block_size);
3722         _silent_buffers->ensure_buffers(howmany, current_block_size);
3723         
3724         allocate_pan_automation_buffers (current_block_size, howmany.get(DataType::AUDIO), false);
3725 }
3726
3727 uint32_t
3728 Session::next_insert_id ()
3729 {
3730         /* this doesn't really loop forever. just think about it */
3731
3732         while (true) {
3733                 for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < insert_bitset.size(); ++n) {
3734                         if (!insert_bitset[n]) {
3735                                 insert_bitset[n] = true;
3736                                 cerr << "Returning " << n << " as insert ID\n";
3737                                 return n;
3738                                 
3739                         }
3740                 }
3741                 
3742                 /* none available, so resize and try again */
3743
3744                 insert_bitset.resize (insert_bitset.size() + 16, false);
3745         }
3746 }
3747
3748 uint32_t
3749 Session::next_send_id ()
3750 {
3751         /* this doesn't really loop forever. just think about it */
3752
3753         while (true) {
3754                 for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < send_bitset.size(); ++n) {
3755                         if (!send_bitset[n]) {
3756                                 send_bitset[n] = true;
3757                                 cerr << "Returning " << n << " as send ID\n";
3758                                 return n;
3759                                 
3760                         }
3761                 }
3762                 
3763                 /* none available, so resize and try again */
3764
3765                 send_bitset.resize (send_bitset.size() + 16, false);
3766         }
3767 }
3768
3769 void
3770 Session::mark_send_id (uint32_t id)
3771 {
3772         if (id >= send_bitset.size()) {
3773                 send_bitset.resize (id+16, false);
3774         }
3775         if (send_bitset[id]) {
3776                 warning << string_compose (_("send ID %1 appears to be in use already"), id) << endmsg;
3777         }
3778         send_bitset[id] = true;
3779 }
3780
3781 void
3782 Session::mark_insert_id (uint32_t id)
3783 {
3784         if (id >= insert_bitset.size()) {
3785                 insert_bitset.resize (id+16, false);
3786         }
3787         if (insert_bitset[id]) {
3788                 warning << string_compose (_("insert ID %1 appears to be in use already"), id) << endmsg;
3789         }
3790         insert_bitset[id] = true;
3791 }
3792
3793 /* Named Selection management */
3794
3795 NamedSelection *
3796 Session::named_selection_by_name (string name)
3797 {
3798         Glib::Mutex::Lock lm (named_selection_lock);
3799         for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
3800                 if ((*i)->name == name) {
3801                         return* i;
3802                 }
3803         }
3804         return 0;
3805 }
3806
3807 void
3808 Session::add_named_selection (NamedSelection* named_selection)
3809 {
3810         { 
3811                 Glib::Mutex::Lock lm (named_selection_lock);
3812                 named_selections.insert (named_selections.begin(), named_selection);
3813         }
3814
3815         for (list<boost::shared_ptr<Playlist> >::iterator i = named_selection->playlists.begin(); i != named_selection->playlists.end(); ++i) {
3816                 add_playlist (*i);
3817         }
3818
3819         set_dirty();
3820
3821         NamedSelectionAdded (); /* EMIT SIGNAL */
3822 }
3823
3824 void
3825 Session::remove_named_selection (NamedSelection* named_selection)
3826 {
3827         bool removed = false;
3828
3829         { 
3830                 Glib::Mutex::Lock lm (named_selection_lock);
3831
3832                 NamedSelectionList::iterator i = find (named_selections.begin(), named_selections.end(), named_selection);
3833
3834                 if (i != named_selections.end()) {
3835                         delete (*i);
3836                         named_selections.erase (i);
3837                         set_dirty();
3838                         removed = true;
3839                 }
3840         }
3841
3842         if (removed) {
3843                  NamedSelectionRemoved (); /* EMIT SIGNAL */
3844         }
3845 }
3846
3847 void
3848 Session::reset_native_file_format ()
3849 {
3850         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3851
3852         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
3853                 (*i)->reset_write_sources (false);
3854         }
3855 }
3856
3857 bool
3858 Session::route_name_unique (string n) const
3859 {
3860         shared_ptr<RouteList> r = routes.reader ();
3861         
3862         for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
3863                 if ((*i)->name() == n) {
3864                         return false;
3865                 }
3866         }
3867         
3868         return true;
3869 }
3870
3871 uint32_t
3872 Session::n_playlists () const
3873 {
3874         Glib::Mutex::Lock lm (playlist_lock);
3875         return playlists.size();
3876 }
3877
3878 void
3879 Session::allocate_pan_automation_buffers (nframes_t nframes, uint32_t howmany, bool force)
3880 {
3881         if (!force && howmany <= _npan_buffers) {
3882                 return;
3883         }
3884
3885         if (_pan_automation_buffer) {
3886
3887                 for (uint32_t i = 0; i < _npan_buffers; ++i) {
3888                         delete [] _pan_automation_buffer[i];
3889                 }
3890
3891                 delete [] _pan_automation_buffer;
3892         }
3893
3894         _pan_automation_buffer = new pan_t*[howmany];
3895         
3896         for (uint32_t i = 0; i < howmany; ++i) {
3897                 _pan_automation_buffer[i] = new pan_t[nframes];
3898         }
3899
3900         _npan_buffers = howmany;
3901 }
3902
3903 int
3904 Session::freeze (InterThreadInfo& itt)
3905 {
3906         shared_ptr<RouteList> r = routes.reader ();
3907
3908         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3909
3910                 Track *at;
3911
3912                 if ((at = dynamic_cast<Track*>((*i).get())) != 0) {
3913                         /* XXX this is wrong because itt.progress will keep returning to zero at the start
3914                            of every track.
3915                         */
3916                         at->freeze (itt);
3917                 }
3918         }
3919
3920         return 0;
3921 }
3922
3923 int
3924 Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t len,      
3925                                bool overwrite, vector<boost::shared_ptr<Source> >& srcs, InterThreadInfo& itt)
3926 {
3927         int ret = -1;
3928         boost::shared_ptr<Playlist> playlist;
3929         boost::shared_ptr<AudioFileSource> fsource;
3930         uint32_t x;
3931         char buf[PATH_MAX+1];
3932         string dir;
3933         ChanCount nchans(track.audio_diskstream()->n_channels());
3934         nframes_t position;
3935         nframes_t this_chunk;
3936         nframes_t to_do;
3937         BufferSet buffers;
3938
3939         // any bigger than this seems to cause stack overflows in called functions
3940         const nframes_t chunk_size = (128 * 1024)/4;
3941
3942         g_atomic_int_set (&processing_prohibited, 1);
3943         
3944         /* call tree *MUST* hold route_lock */
3945         
3946         if ((playlist = track.diskstream()->playlist()) == 0) {
3947                 goto out;
3948         }
3949
3950         /* external redirects will be a problem */
3951
3952         if (track.has_external_redirects()) {
3953                 goto out;
3954         }
3955         
3956         dir = discover_best_sound_dir ();
3957
3958         for (uint32_t chan_n=0; chan_n < nchans.get(DataType::AUDIO); ++chan_n) {
3959
3960                 for (x = 0; x < 99999; ++x) {
3961                         snprintf (buf, sizeof(buf), "%s/%s-%d-bounce-%" PRIu32 ".wav", dir.c_str(), playlist->name().c_str(), chan_n, x+1);
3962                         if (access (buf, F_OK) != 0) {
3963                                 break;
3964                         }
3965                 }
3966                 
3967                 if (x == 99999) {
3968                         error << string_compose (_("too many bounced versions of playlist \"%1\""), playlist->name()) << endmsg;
3969                         goto out;
3970                 }
3971                 
3972                 try {
3973                         fsource = boost::dynamic_pointer_cast<AudioFileSource> (
3974                                 SourceFactory::createWritable (DataType::AUDIO, *this, buf, false, frame_rate()));
3975                 }
3976                 
3977                 catch (failed_constructor& err) {
3978                         error << string_compose (_("cannot create new audio file \"%1\" for %2"), buf, track.name()) << endmsg;
3979                         goto out;
3980                 }
3981
3982                 srcs.push_back (fsource);
3983         }
3984
3985         /* XXX need to flush all redirects */
3986         
3987         position = start;
3988         to_do = len;
3989
3990         /* create a set of reasonably-sized buffers */
3991         buffers.ensure_buffers(nchans, chunk_size);
3992         buffers.set_count(nchans);
3993
3994         while (to_do && !itt.cancel) {
3995                 
3996                 this_chunk = min (to_do, chunk_size);
3997                 
3998                 if (track.export_stuff (buffers, start, this_chunk)) {
3999                         goto out;
4000                 }
4001
4002                 uint32_t n = 0;
4003                 for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src, ++n) {
4004                         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
4005                         
4006                         if (afs) {
4007                                 if (afs->write (buffers.get_audio(n).data(this_chunk), this_chunk) != this_chunk) {
4008                                         goto out;
4009                                 }
4010                         }
4011                 }
4012                 
4013                 start += this_chunk;
4014                 to_do -= this_chunk;
4015                 
4016                 itt.progress = (float) (1.0 - ((double) to_do / len));
4017
4018         }
4019
4020         if (!itt.cancel) {
4021                 
4022                 time_t now;
4023                 struct tm* xnow;
4024                 time (&now);
4025                 xnow = localtime (&now);
4026                 
4027                 for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src) {
4028                         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
4029                         
4030                         if (afs) {
4031                                 afs->update_header (position, *xnow, now);
4032                         }
4033                 }
4034                 
4035                 /* build peakfile for new source */
4036                 
4037                 for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src) {
4038                         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
4039                         if (afs) {
4040                                 afs->build_peaks ();
4041                         }
4042                 }
4043
4044                 /* construct a region to represent the bounced material */
4045
4046                 boost::shared_ptr<Region> aregion = RegionFactory::create (srcs, 0, srcs.front()->length(), 
4047                                                                            region_name_from_path (srcs.front()->name(), true));
4048
4049                 ret = 0;
4050         }
4051                 
4052   out:
4053         if (ret) {
4054                 for (vector<boost::shared_ptr<Source> >::iterator src = srcs.begin(); src != srcs.end(); ++src) {
4055                         boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
4056
4057                         if (afs) {
4058                                 afs->mark_for_remove ();
4059                         }
4060
4061                         (*src)->drop_references ();
4062                 }
4063         }
4064
4065         g_atomic_int_set (&processing_prohibited, 0);
4066
4067         itt.done = true;
4068
4069         return ret;
4070 }
4071
4072 BufferSet&
4073 Session::get_silent_buffers (ChanCount count)
4074 {
4075         assert(_silent_buffers->available() >= count);
4076         _silent_buffers->set_count(count);
4077
4078         for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
4079                 for (size_t i=0; i < count.get(*t); ++i) {
4080                         _silent_buffers->get(*t, i).clear();
4081                 }
4082         }
4083         
4084         return *_silent_buffers;
4085 }
4086
4087 BufferSet&
4088 Session::get_scratch_buffers (ChanCount count)
4089 {
4090         assert(_scratch_buffers->available() >= count);
4091         _scratch_buffers->set_count(count);
4092         return *_scratch_buffers;
4093 }
4094
4095 BufferSet&
4096 Session::get_send_buffers (ChanCount count)
4097 {
4098         assert(_send_buffers->available() >= count);
4099         _send_buffers->set_count(count);
4100         return *_send_buffers;
4101 }
4102
4103 uint32_t 
4104 Session::ntracks () const
4105 {
4106         uint32_t n = 0;
4107         shared_ptr<RouteList> r = routes.reader ();
4108
4109         for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
4110                 if (dynamic_cast<Track*> ((*i).get())) {
4111                         ++n;
4112                 }
4113         }
4114
4115         return n;
4116 }
4117
4118 uint32_t 
4119 Session::nbusses () const
4120 {
4121         uint32_t n = 0;
4122         shared_ptr<RouteList> r = routes.reader ();
4123
4124         for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
4125                 if (dynamic_cast<Track*> ((*i).get()) == 0) {
4126                         ++n;
4127                 }
4128         }
4129
4130         return n;
4131 }
4132
4133 void
4134 Session::add_automation_list(AutomationList *al)
4135 {
4136         automation_lists[al->id()] = al;
4137 }
4138
4139 nframes_t
4140 Session::compute_initial_length ()
4141 {
4142         return _engine.frame_rate() * 60 * 5;
4143 }
4144