#include "ardour/auditioner.h"
#include "ardour/buffer_set.h"
#include "ardour/bundle.h"
+#include "ardour/butler.h"
#include "ardour/click.h"
#include "ardour/configuration.h"
#include "ardour/crossfade.h"
#include "ardour/plugin_insert.h"
#include "ardour/port_insert.h"
#include "ardour/processor.h"
+#include "ardour/rc_configuration.h"
#include "ardour/recent_sessions.h"
#include "ardour/region_factory.h"
#include "ardour/return.h"
sigc::signal<int,nframes_t,nframes_t> Session::AskAboutSampleRateMismatch;
sigc::signal<void> Session::SendFeedback;
-sigc::signal<void> Session::SMPTEOffsetChanged;
+sigc::signal<void> Session::TimecodeOffsetChanged;
sigc::signal<void> Session::StartTimeChanged;
sigc::signal<void> Session::EndTimeChanged;
sigc::signal<void> Session::AutoBindingOn;
_session_dir (new SessionDirectory(fullpath)),
pending_events (2048),
state_tree (0),
- post_transport_work((PostTransportWork)0),
- _send_smpte_update (false),
+ _butler (new Butler (this)),
+ _post_transport_work (0),
+ _send_timecode_update (false),
midi_thread (pthread_t (0)),
midi_requests (128), // the size of this should match the midi request pool size
diskstreams (new DiskstreamList),
_session_dir ( new SessionDirectory(fullpath)),
pending_events (2048),
state_tree (0),
- post_transport_work((PostTransportWork)0),
- _send_smpte_update (false),
+ _butler (new Butler (this)),
+ _post_transport_work (0),
+ _send_timecode_update (false),
midi_thread (pthread_t (0)),
midi_requests (16),
diskstreams (new DiskstreamList),
delete state_tree;
/* reset dynamic state version back to default */
-
+
Stateful::loading_state_version = 0;
- terminate_butler_thread ();
+ _butler->terminate_thread ();
//terminate_midi_thread ();
if (click_data != default_click) {
}
void
-Session::diskstream_playlist_changed (boost::shared_ptr<Diskstream> dstream)
+Session::diskstream_playlist_changed (boost::weak_ptr<Diskstream> wp)
{
+ boost::shared_ptr<Diskstream> dstream = wp.lock ();
+ if (!dstream) {
+ return;
+ }
+
boost::shared_ptr<Playlist> playlist;
if ((playlist = dstream->playlist()) != 0) {
if (transport_rolling() && play_loop) {
- //if (_transport_frame < location->start() || _transport_frame > location->end()) {
- if (_transport_frame > location->end()) {
+ // if (_transport_frame > location->end()) {
+
+ if (_transport_frame < location->start() || _transport_frame > location->end()) {
// relocate to beginning of loop
clear_events (Event::LocateRoll);
auto_loop_end_changed_connection.disconnect();
auto_loop_changed_connection.disconnect();
- auto_loop_start_changed_connection = location->start_changed.connect (mem_fun (this, &Session::auto_loop_changed));
- auto_loop_end_changed_connection = location->end_changed.connect (mem_fun (this, &Session::auto_loop_changed));
- auto_loop_changed_connection = location->changed.connect (mem_fun (this, &Session::auto_loop_changed));
+ auto_loop_start_changed_connection = location->start_changed.connect (
+ mem_fun (this, &Session::auto_loop_changed));
+ auto_loop_end_changed_connection = location->end_changed.connect (
+ mem_fun (this, &Session::auto_loop_changed));
+ auto_loop_changed_connection = location->changed.connect (
+ mem_fun (this, &Session::auto_loop_changed));
location->set_auto_loop (true, this);
set_dirty();
}
-nframes_t
+nframes64_t
Session::audible_frame () const
{
- nframes_t ret;
+ nframes64_t ret;
+ nframes64_t tf;
nframes_t offset;
- nframes_t tf;
/* the first of these two possible settings for "offset"
mean that the audible frame is stationary until
RouteList
-Session::new_audio_route (int input_channels, int output_channels, RouteGroup* route_group, uint32_t how_many)
+Session::new_audio_route (bool aux, int input_channels, int output_channels, RouteGroup* route_group, uint32_t how_many)
{
char bus_name[32];
uint32_t bus_id = 1;
bus->set_remote_control_id (control_id);
++control_id;
+ if (aux) {
+ bus->add_internal_return ();
+ }
+
ret.push_back (bus);
}
add_internal_sends (dest, p, t);
}
-
void
Session::add_internal_sends (boost::shared_ptr<Route> dest, Placement p, boost::shared_ptr<RouteList> senders)
{
(*i)->listen_via (dest, p, true, true);
}
+
+ graph_reordered ();
}
void
/* writer goes out of scope, copies ds back to main */
}
- dstream->PlaylistChanged.connect (sigc::bind (mem_fun (*this, &Session::diskstream_playlist_changed), dstream));
+ dstream->PlaylistChanged.connect (sigc::bind (mem_fun (*this, &Session::diskstream_playlist_changed), boost::weak_ptr<Diskstream> (dstream)));
/* this will connect to future changes, and check the current length */
- diskstream_playlist_changed (dstream);
+ diskstream_playlist_changed (boost::weak_ptr<Diskstream> (dstream));
dstream->RecordEnableChanged.connect (mem_fun (*this, &Session::update_have_rec_enabled_diskstream));
shared_ptr<RouteList> r = routes.reader ();
int32_t delta;
- if (route->soloed()) {
+ if (route->self_soloed()) {
delta = 1;
} else {
delta = -1;
*/
solo_update_disabled = true;
+
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+ bool via_sends_only;
- if ((*i)->feeds (route) && !(*i)->is_hidden() && !(*i)->is_master() && !(*i)->is_control()) {
- /* do it */
- (*i)->mod_solo_level (delta);
- }
+
+ if ((*i) == route || !(*i)->solo_isolated() || !(*i)->is_master() || !(*i)->is_control() || (*i)->is_hidden()) {
+ continue;
+ } else if ((*i)->feeds (route, &via_sends_only)) {
+ if (!via_sends_only) {
+ (*i)->mod_solo_by_others (delta);
+ }
+ }
}
/* make sure master is never muted by solo */
- if (route != _master_out && _master_out->solo_level() == 0 && !_master_out->soloed()) {
- _master_out->mod_solo_level (1);
- }
-
+ if (_master_out && route != _master_out && _master_out->soloed_by_others() == 0 && !_master_out->soloed()) {
+ _master_out->mod_solo_by_others (1);
+ }
+
/* ditto for control outs make sure master is never muted by solo */
- if (route != _control_out && _control_out && _control_out->solo_level() == 0) {
- _control_out->mod_solo_level (1);
+ if (_control_out && route != _control_out && _control_out && _control_out->soloed_by_others() == 0) {
+ _control_out->mod_solo_by_others (1);
}
solo_update_disabled = false;
}
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if (!(*i)->is_master() && !(*i)->is_control() && !(*i)->is_hidden() && (*i)->soloed()) {
+ if (!(*i)->is_master() && !(*i)->is_control() && !(*i)->is_hidden() && (*i)->self_soloed()) {
something_soloed = true;
break;
}
}
}
+boost::shared_ptr<RouteList>
+Session::get_routes_with_internal_returns() const
+{
+ shared_ptr<RouteList> r = routes.reader ();
+ boost::shared_ptr<RouteList> rl (new RouteList);
+
+ for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+ if ((*i)->internal_return ()) {
+ rl->push_back (*i);
+ }
+ }
+ return rl;
+}
+
shared_ptr<Route>
Session::route_by_name (string name)
{
}
}
+/** Return the number of playlists (not regions) that contain @a src */
+uint32_t
+Session::source_use_count (boost::shared_ptr<const Source> src) const
+{
+ uint32_t count = 0;
+ for (PlaylistList::const_iterator p = playlists.begin(); p != playlists.end(); ++p) {
+ for (Playlist::RegionList::const_iterator r = (*p)->region_list().begin();
+ r != (*p)->region_list().end(); ++r) {
+ if ((*r)->uses_source(src)) {
+ ++count;
+ break;
+ }
+ }
+ }
+ return count;
+}
+
boost::shared_ptr<Source>
Session::source_by_id (const PBD::ID& id)
{
Session::set_audition (boost::shared_ptr<Region> r)
{
pending_audition_region = r;
- post_transport_work = PostTransportWork (post_transport_work | PostTransportAudition);
- schedule_butler_transport_work ();
+ add_post_transport_work (PostTransportAudition);
+ _butler->schedule_transport_work ();
}
void
{
RouteGroupChanged (); /* EMIT SIGNAL */
}
+
+vector<SyncSource>
+Session::get_available_sync_options () const
+{
+ vector<SyncSource> ret;
+
+ ret.push_back (JACK);
+
+ if (mtc_port()) {
+ ret.push_back (MTC);
+ }
+
+ if (midi_clock_port()) {
+ ret.push_back (MIDIClock);
+ }
+
+ return ret;
+}