2008-06-02 17:41:35 -04:00
/*
2008-08-04 18:37:24 -04:00
Copyright ( C ) 1999 - 2003 Paul Davis
2008-06-02 17:41:35 -04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include <cmath>
# include <cerrno>
# include <unistd.h>
2009-02-25 13:26:51 -05:00
# include "pbd/undo.h"
# include "pbd/error.h"
2009-11-30 11:12:13 -05:00
# include "pbd/enumwriter.h"
2009-02-25 13:26:51 -05:00
# include "pbd/pthread_utils.h"
# include "pbd/memento_command.h"
2008-06-02 17:41:35 -04:00
2009-02-25 13:26:51 -05:00
# include "midi++/mmc.h"
# include "midi++/port.h"
2010-07-08 18:55:20 -04:00
# include "midi++/manager.h"
2008-06-02 17:41:35 -04:00
2009-02-25 13:26:51 -05:00
# include "ardour/ardour.h"
2009-10-23 19:23:00 -04:00
# include "ardour/audioengine.h"
2009-02-25 13:26:51 -05:00
# include "ardour/auditioner.h"
2009-10-23 19:23:00 -04:00
# include "ardour/butler.h"
2009-11-30 11:12:13 -05:00
# include "ardour/debug.h"
2009-02-25 13:26:51 -05:00
# include "ardour/location.h"
2009-10-23 19:23:00 -04:00
# include "ardour/session.h"
# include "ardour/slave.h"
2008-06-02 17:41:35 -04:00
# include "i18n.h"
using namespace std ;
using namespace ARDOUR ;
using namespace PBD ;
2009-11-08 11:28:21 -05:00
void
Session : : add_post_transport_work ( PostTransportWork ptw )
{
PostTransportWork oldval ;
PostTransportWork newval ;
int tries = 0 ;
while ( tries < 8 ) {
oldval = ( PostTransportWork ) g_atomic_int_get ( & _post_transport_work ) ;
newval = PostTransportWork ( oldval | ptw ) ;
if ( g_atomic_int_compare_and_exchange ( & _post_transport_work , oldval , newval ) ) {
/* success */
return ;
}
}
error < < " Could not set post transport work! Crazy thread madness, call the programmers " < < endmsg ;
}
2008-06-02 17:41:35 -04:00
void
Session : : request_input_change_handling ( )
{
if ( ! ( _state_of_the_state & ( InitialConnecting | Deletion ) ) ) {
2009-12-03 21:15:12 -05:00
SessionEvent * ev = new SessionEvent ( SessionEvent : : InputConfigurationChange , SessionEvent : : Add , SessionEvent : : Immediate , 0 , 0.0 ) ;
2008-06-02 17:41:35 -04:00
queue_event ( ev ) ;
2008-08-04 18:37:24 -04:00
}
2008-06-02 17:41:35 -04:00
}
void
2009-12-03 13:44:06 -05:00
Session : : request_sync_source ( Slave * new_slave )
2008-06-02 17:41:35 -04:00
{
2009-12-03 21:15:12 -05:00
SessionEvent * ev = new SessionEvent ( SessionEvent : : SetSyncSource , SessionEvent : : Add , SessionEvent : : Immediate , 0 , 0.0 ) ;
2009-11-08 11:28:21 -05:00
bool seamless ;
seamless = Config - > get_seamless_loop ( ) ;
2008-06-02 17:41:35 -04:00
2009-12-03 13:44:06 -05:00
if ( dynamic_cast < JACK_Slave * > ( new_slave ) ) {
2009-11-08 11:28:21 -05:00
/* JACK cannot support seamless looping at present */
2008-06-02 17:41:35 -04:00
Config - > set_seamless_loop ( false ) ;
2009-11-08 11:28:21 -05:00
} else {
/* reset to whatever the value was before we last switched slaves */
Config - > set_seamless_loop ( _was_seamless ) ;
2008-06-02 17:41:35 -04:00
}
2009-10-30 14:14:25 -04:00
2009-11-08 11:28:21 -05:00
/* save value of seamless from before the switch */
_was_seamless = seamless ;
2009-12-03 13:44:06 -05:00
ev - > slave = new_slave ;
2008-06-02 17:41:35 -04:00
queue_event ( ev ) ;
}
void
2009-01-09 04:18:24 -05:00
Session : : request_transport_speed ( double speed )
2008-06-02 17:41:35 -04:00
{
2009-12-03 21:15:12 -05:00
SessionEvent * ev = new SessionEvent ( SessionEvent : : SetTransportSpeed , SessionEvent : : Add , SessionEvent : : Immediate , 0 , speed ) ;
2009-11-30 11:12:13 -05:00
DEBUG_TRACE ( DEBUG : : Transport , string_compose ( " Request transport speed = %1 \n " , speed ) ) ;
2008-06-02 17:41:35 -04:00
queue_event ( ev ) ;
}
void
2010-04-21 16:42:22 -04:00
Session : : request_track_speed ( Track * tr , double speed )
2008-06-02 17:41:35 -04:00
{
2010-04-21 16:42:22 -04:00
SessionEvent * ev = new SessionEvent ( SessionEvent : : SetTrackSpeed , SessionEvent : : Add , SessionEvent : : Immediate , 0 , speed ) ;
ev - > set_ptr ( tr ) ;
2008-06-02 17:41:35 -04:00
queue_event ( ev ) ;
}
void
2009-11-08 11:28:21 -05:00
Session : : request_stop ( bool abort , bool clear_state )
2008-06-02 17:41:35 -04:00
{
2009-12-03 21:15:12 -05:00
SessionEvent * ev = new SessionEvent ( SessionEvent : : SetTransportSpeed , SessionEvent : : Add , SessionEvent : : Immediate , 0 , 0.0 , abort , clear_state ) ;
2009-11-30 11:12:13 -05:00
DEBUG_TRACE ( DEBUG : : Transport , string_compose ( " Request transport stop, abort = %1, clear state = %2 \n " , abort , clear_state ) ) ;
2008-06-02 17:41:35 -04:00
queue_event ( ev ) ;
}
void
Session : : request_locate ( nframes_t target_frame , bool with_roll )
{
2009-12-03 21:15:12 -05:00
SessionEvent * ev = new SessionEvent ( with_roll ? SessionEvent : : LocateRoll : SessionEvent : : Locate , SessionEvent : : Add , SessionEvent : : Immediate , target_frame , 0 , false ) ;
2009-11-30 11:12:13 -05:00
DEBUG_TRACE ( DEBUG : : Transport , string_compose ( " Request locate to %1 \n " , target_frame ) ) ;
2008-06-02 17:41:35 -04:00
queue_event ( ev ) ;
}
void
2009-11-08 11:28:21 -05:00
Session : : force_locate ( nframes64_t target_frame , bool with_roll )
2008-06-02 17:41:35 -04:00
{
2009-12-03 21:15:12 -05:00
SessionEvent * ev = new SessionEvent ( with_roll ? SessionEvent : : LocateRoll : SessionEvent : : Locate , SessionEvent : : Add , SessionEvent : : Immediate , target_frame , 0 , true ) ;
2009-11-30 11:12:13 -05:00
DEBUG_TRACE ( DEBUG : : Transport , string_compose ( " Request forced locate to %1 \n " , target_frame ) ) ;
2008-06-02 17:41:35 -04:00
queue_event ( ev ) ;
}
void
2009-10-30 14:14:25 -04:00
Session : : request_play_loop ( bool yn , bool leave_rolling )
2008-06-02 17:41:35 -04:00
{
2009-12-03 21:15:12 -05:00
SessionEvent * ev ;
2008-06-02 17:41:35 -04:00
Location * location = _locations . auto_loop_location ( ) ;
if ( location = = 0 & & yn ) {
error < < _ ( " Cannot loop - no loop range defined " )
< < endmsg ;
return ;
}
2009-12-03 21:15:12 -05:00
ev = new SessionEvent ( SessionEvent : : SetLoop , SessionEvent : : Add , SessionEvent : : Immediate , 0 , ( leave_rolling ? 1.0 : 0.0 ) , yn ) ;
2009-11-30 11:12:13 -05:00
DEBUG_TRACE ( DEBUG : : Transport , string_compose ( " Request set loop = %1, leave rolling ? %2 \n " , yn , leave_rolling ) ) ;
2008-06-02 17:41:35 -04:00
queue_event ( ev ) ;
2009-10-30 14:14:25 -04:00
if ( ! leave_rolling & & ! yn & & Config - > get_seamless_loop ( ) & & transport_rolling ( ) ) {
2010-04-21 16:42:22 -04:00
// request an immediate locate to refresh the tracks
2008-06-02 17:41:35 -04:00
// after disabling looping
request_locate ( _transport_frame - 1 , false ) ;
}
}
void
2009-11-08 11:28:21 -05:00
Session : : request_play_range ( list < AudioRange > * range , bool leave_rolling )
{
2009-12-03 21:15:12 -05:00
SessionEvent * ev = new SessionEvent ( SessionEvent : : SetPlayAudioRange , SessionEvent : : Add , SessionEvent : : Immediate , 0 , ( leave_rolling ? 1.0 : 0.0 ) ) ;
2009-11-08 11:28:21 -05:00
if ( range ) {
ev - > audio_range = * range ;
} else {
ev - > audio_range . clear ( ) ;
}
2009-11-30 11:12:13 -05:00
DEBUG_TRACE ( DEBUG : : Transport , string_compose ( " Request play range, leave rolling ? %1 \n " , leave_rolling ) ) ;
2009-11-08 11:28:21 -05:00
queue_event ( ev ) ;
}
void
Session : : realtime_stop ( bool abort , bool clear_state )
2008-06-02 17:41:35 -04:00
{
2009-11-30 11:12:13 -05:00
DEBUG_TRACE ( DEBUG : : Transport , " realtime stop \n " ) ;
2009-11-08 11:28:21 -05:00
PostTransportWork todo = PostTransportWork ( 0 ) ;
2008-06-02 17:41:35 -04:00
/* assume that when we start, we'll be moving forwards */
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
if ( _transport_speed < 0.0f ) {
2009-11-08 11:28:21 -05:00
todo = ( PostTransportWork ( todo | PostTransportStop | PostTransportReverse ) ) ;
2008-06-02 17:41:35 -04:00
} else {
2009-11-08 11:28:21 -05:00
todo = PostTransportWork ( todo | PostTransportStop ) ;
2008-06-02 17:41:35 -04:00
}
if ( actively_recording ( ) ) {
/* move the transport position back to where the
request for a stop was noticed . we rolled
2010-04-12 18:35:06 -04:00
past that point to pick up delayed input ( and / or to delick )
2008-06-02 17:41:35 -04:00
*/
2010-04-12 18:35:06 -04:00
if ( _worst_output_latency > current_block_size ) {
/* we rolled past the stop point to pick up data that had
not yet arrived . move back to where the stop occured .
*/
decrement_transport_position ( current_block_size + ( _worst_output_latency - current_block_size ) ) ;
} else {
decrement_transport_position ( current_block_size ) ;
}
2008-06-02 17:41:35 -04:00
/* the duration change is not guaranteed to have happened, but is likely */
2009-11-08 11:28:21 -05:00
todo = PostTransportWork ( todo | PostTransportDuration ) ;
2008-06-02 17:41:35 -04:00
}
if ( abort ) {
2009-11-08 11:28:21 -05:00
todo = PostTransportWork ( todo | PostTransportAbort ) ;
}
if ( clear_state ) {
todo = PostTransportWork ( todo | PostTransportClearSubstate ) ;
}
if ( todo ) {
add_post_transport_work ( todo ) ;
2008-06-02 17:41:35 -04:00
}
2009-12-03 21:15:12 -05:00
_clear_event_type ( SessionEvent : : StopOnce ) ;
_clear_event_type ( SessionEvent : : RangeStop ) ;
_clear_event_type ( SessionEvent : : RangeLocate ) ;
2008-06-02 17:41:35 -04:00
2010-04-20 22:24:38 -04:00
/* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
disable_record ( true , ( ! Config - > get_latched_record_enable ( ) & & clear_state ) ) ;
2008-06-02 17:41:35 -04:00
reset_slave_state ( ) ;
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
_transport_speed = 0 ;
2009-06-09 20:03:47 -04:00
_target_transport_speed = 0 ;
2008-06-02 17:41:35 -04:00
2010-05-11 20:29:28 -04:00
g_atomic_int_set ( & _playback_load , 100 ) ;
g_atomic_int_set ( & _capture_load , 100 ) ;
2009-05-15 21:53:43 -04:00
if ( config . get_use_video_sync ( ) ) {
2008-06-02 17:41:35 -04:00
waiting_for_sync_offset = true ;
}
2010-07-08 20:57:58 -04:00
transport_sub_state = 0 ;
2008-06-02 17:41:35 -04:00
}
void
Session : : butler_transport_work ( )
{
restart :
bool finished ;
2009-11-08 11:28:21 -05:00
PostTransportWork ptw ;
2008-06-02 17:41:35 -04:00
boost : : shared_ptr < RouteList > r = routes . reader ( ) ;
2009-10-23 20:39:28 -04:00
int on_entry = g_atomic_int_get ( & _butler - > should_do_transport_work ) ;
2008-06-02 17:41:35 -04:00
finished = true ;
2009-11-08 11:28:21 -05:00
ptw = post_transport_work ( ) ;
2009-11-30 11:12:13 -05:00
DEBUG_TRACE ( DEBUG : : Transport , string_compose ( " Butler transport work, todo = %1 \n " , enum_2_string ( ptw ) ) ) ;
2010-06-09 13:24:07 -04:00
if ( ptw & PostTransportAdjustPlaybackBuffering ) {
for ( RouteList : : iterator i = r - > begin ( ) ; i ! = r - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr ) {
tr - > adjust_playback_buffering ( ) ;
/* and refill those buffers ... */
tr - > non_realtime_locate ( _transport_frame ) ;
}
}
}
if ( ptw & PostTransportAdjustCaptureBuffering ) {
for ( RouteList : : iterator i = r - > begin ( ) ; i ! = r - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr ) {
tr - > adjust_capture_buffering ( ) ;
}
}
}
2009-11-08 11:28:21 -05:00
if ( ptw & PostTransportCurveRealloc ) {
2008-06-02 17:41:35 -04:00
for ( RouteList : : iterator i = r - > begin ( ) ; i ! = r - > end ( ) ; + + i ) {
( * i ) - > curve_reallocate ( ) ;
}
}
2009-11-08 11:28:21 -05:00
if ( ptw & PostTransportInputChange ) {
2010-04-21 16:42:22 -04:00
for ( RouteList : : iterator i = r - > begin ( ) ; i ! = r - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr ) {
tr - > non_realtime_input_change ( ) ;
}
2008-06-02 17:41:35 -04:00
}
}
2009-11-08 11:28:21 -05:00
if ( ptw & PostTransportSpeed ) {
2008-06-02 17:41:35 -04:00
non_realtime_set_speed ( ) ;
}
2009-11-08 11:28:21 -05:00
if ( ptw & PostTransportReverse ) {
2009-10-14 12:10:01 -04:00
2008-06-02 17:41:35 -04:00
clear_clicks ( ) ;
cumulative_rf_motion = 0 ;
reset_rf_scale ( 0 ) ;
/* don't seek if locate will take care of that in non_realtime_stop() */
2009-11-08 11:28:21 -05:00
if ( ! ( ptw & PostTransportLocate ) ) {
2008-08-04 18:37:24 -04:00
2010-04-21 16:42:22 -04:00
for ( RouteList : : iterator i = r - > begin ( ) ; i ! = r - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr & & ! tr - > hidden ( ) ) {
tr - > non_realtime_locate ( _transport_frame ) ;
2008-06-02 17:41:35 -04:00
}
2009-10-23 20:39:28 -04:00
if ( on_entry ! = g_atomic_int_get ( & _butler - > should_do_transport_work ) ) {
2008-06-02 17:41:35 -04:00
/* new request, stop seeking, and start again */
2009-10-23 20:39:28 -04:00
g_atomic_int_dec_and_test ( & _butler - > should_do_transport_work ) ;
2008-06-02 17:41:35 -04:00
goto restart ;
}
}
}
}
2008-08-04 18:37:24 -04:00
2009-11-08 11:28:21 -05:00
if ( ptw & PostTransportLocate ) {
2008-06-02 17:41:35 -04:00
non_realtime_locate ( ) ;
}
2009-11-08 11:28:21 -05:00
if ( ptw & PostTransportStop ) {
non_realtime_stop ( ptw & PostTransportAbort , on_entry , finished ) ;
2008-06-02 17:41:35 -04:00
if ( ! finished ) {
2009-10-23 20:39:28 -04:00
g_atomic_int_dec_and_test ( & _butler - > should_do_transport_work ) ;
2008-06-02 17:41:35 -04:00
goto restart ;
}
}
2009-11-08 11:28:21 -05:00
if ( ptw & PostTransportOverWrite ) {
2008-06-02 17:41:35 -04:00
non_realtime_overwrite ( on_entry , finished ) ;
if ( ! finished ) {
2009-10-23 20:39:28 -04:00
g_atomic_int_dec_and_test ( & _butler - > should_do_transport_work ) ;
2008-06-02 17:41:35 -04:00
goto restart ;
}
}
2009-11-08 11:28:21 -05:00
if ( ptw & PostTransportAudition ) {
2008-06-02 17:41:35 -04:00
non_realtime_set_audition ( ) ;
}
2008-08-04 18:37:24 -04:00
2009-10-23 20:39:28 -04:00
g_atomic_int_dec_and_test ( & _butler - > should_do_transport_work ) ;
2010-04-19 13:48:11 -04:00
DEBUG_TRACE ( DEBUG : : Transport , X_ ( " Butler transport work all done \n " ) ) ;
2008-06-02 17:41:35 -04:00
}
void
Session : : non_realtime_set_speed ( )
{
2010-04-21 16:42:22 -04:00
boost : : shared_ptr < RouteList > rl = routes . reader ( ) ;
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr ) {
tr - > non_realtime_set_speed ( ) ;
}
2008-06-02 17:41:35 -04:00
}
}
void
Session : : non_realtime_overwrite ( int on_entry , bool & finished )
{
2010-04-21 16:42:22 -04:00
boost : : shared_ptr < RouteList > rl = routes . reader ( ) ;
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr & & tr - > pending_overwrite ( ) ) {
tr - > overwrite_existing_buffers ( ) ;
2008-06-02 17:41:35 -04:00
}
2009-10-23 20:39:28 -04:00
if ( on_entry ! = g_atomic_int_get ( & _butler - > should_do_transport_work ) ) {
2008-06-02 17:41:35 -04:00
finished = false ;
return ;
}
}
}
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
void
Session : : non_realtime_locate ( )
{
2010-04-21 16:42:22 -04:00
boost : : shared_ptr < RouteList > rl = routes . reader ( ) ;
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr ) {
tr - > non_realtime_locate ( _transport_frame ) ;
}
2008-06-02 17:41:35 -04:00
}
}
void
Session : : non_realtime_stop ( bool abort , int on_entry , bool & finished )
{
struct tm * now ;
time_t xnow ;
bool did_record ;
bool saved ;
2009-11-08 11:28:21 -05:00
PostTransportWork ptw = post_transport_work ( ) ;
2008-06-02 17:41:35 -04:00
did_record = false ;
saved = false ;
2010-04-21 16:42:22 -04:00
boost : : shared_ptr < RouteList > rl = routes . reader ( ) ;
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr & & tr - > get_captured_frames ( ) ! = 0 ) {
2008-06-02 17:41:35 -04:00
did_record = true ;
break ;
}
}
/* stop and locate are merged here because they share a lot of common stuff */
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
time ( & xnow ) ;
now = localtime ( & xnow ) ;
if ( auditioner ) {
auditioner - > cancel_audition ( ) ;
}
clear_clicks ( ) ;
cumulative_rf_motion = 0 ;
reset_rf_scale ( 0 ) ;
if ( did_record ) {
begin_reversible_command ( " capture " ) ;
_have_captured = true ;
}
2010-04-19 13:48:11 -04:00
DEBUG_TRACE ( DEBUG : : Transport , X_ ( " Butler PTW: DS stop \n " ) ) ;
2010-07-16 10:55:11 -04:00
if ( abort & & did_record ) {
/* no reason to save the session file when we remove sources
*/
_state_of_the_state = StateOfTheState ( _state_of_the_state | InCleanup ) ;
}
2010-04-21 16:42:22 -04:00
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr ) {
tr - > transport_stopped_wallclock ( * now , xnow , abort ) ;
}
2008-06-02 17:41:35 -04:00
}
2008-08-04 18:37:24 -04:00
2010-07-16 10:55:11 -04:00
if ( abort & & did_record ) {
_state_of_the_state = StateOfTheState ( _state_of_the_state & ~ InCleanup ) ;
}
2008-06-02 17:41:35 -04:00
boost : : shared_ptr < RouteList > r = routes . reader ( ) ;
for ( RouteList : : iterator i = r - > begin ( ) ; i ! = r - > end ( ) ; + + i ) {
if ( ! ( * i ) - > is_hidden ( ) ) {
( * i ) - > set_pending_declick ( 0 ) ;
}
}
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
if ( did_record ) {
commit_reversible_command ( ) ;
2008-08-04 18:37:24 -04:00
}
2008-06-02 17:41:35 -04:00
if ( _engine . running ( ) ) {
update_latency_compensation ( true , abort ) ;
}
2009-02-02 17:35:50 -05:00
bool const auto_return_enabled =
2009-11-09 15:05:18 -05:00
( ! config . get_external_sync ( ) & & config . get_auto_return ( ) ) ;
2009-10-14 12:10:01 -04:00
2009-02-02 17:35:50 -05:00
if ( auto_return_enabled | |
2009-11-08 11:28:21 -05:00
( ptw & PostTransportLocate ) | |
2008-06-02 17:41:35 -04:00
( _requested_return_frame > = 0 ) | |
synced_to_jack ( ) ) {
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
if ( pending_locate_flush ) {
flush_all_inserts ( ) ;
}
2008-08-04 18:37:24 -04:00
2009-02-02 17:35:50 -05:00
if ( ( auto_return_enabled | | synced_to_jack ( ) | | _requested_return_frame > = 0 ) & &
2009-11-08 11:28:21 -05:00
! ( ptw & PostTransportLocate ) ) {
2008-06-02 17:41:35 -04:00
2010-04-19 13:48:11 -04:00
/* no explicit locate queued */
2009-10-30 14:14:25 -04:00
2008-06-02 17:41:35 -04:00
bool do_locate = false ;
if ( _requested_return_frame > = 0 ) {
2009-10-30 14:14:25 -04:00
/* explicit return request pre-queued in event list. overrides everything else */
cerr < < " explicit auto-return to " < < _requested_return_frame < < endl ;
2008-06-02 17:41:35 -04:00
_transport_frame = _requested_return_frame ;
do_locate = true ;
2009-10-30 14:14:25 -04:00
2008-06-02 17:41:35 -04:00
} else {
2009-10-30 14:14:25 -04:00
if ( config . get_auto_return ( ) ) {
2008-06-02 17:41:35 -04:00
2009-10-30 14:14:25 -04:00
if ( play_loop ) {
/* don't try to handle loop play when synced to JACK */
if ( ! synced_to_jack ( ) ) {
Location * location = _locations . auto_loop_location ( ) ;
if ( location ! = 0 ) {
_transport_frame = location - > start ( ) ;
} else {
_transport_frame = _last_roll_location ;
}
do_locate = true ;
}
} else if ( _play_range ) {
/* return to start of range */
if ( ! current_audio_range . empty ( ) ) {
_transport_frame = current_audio_range . front ( ) . start ;
do_locate = true ;
}
} else {
/* regular auto-return */
_transport_frame = _last_roll_location ;
do_locate = true ;
}
}
2008-06-02 17:41:35 -04:00
}
2008-08-04 18:37:24 -04:00
2009-10-30 14:14:25 -04:00
_requested_return_frame = - 1 ;
2008-06-02 17:41:35 -04:00
if ( do_locate ) {
_engine . transport_locate ( _transport_frame ) ;
}
2009-10-30 14:14:25 -04:00
}
2008-06-02 17:41:35 -04:00
2009-10-28 19:56:05 -04:00
}
2010-04-21 16:42:22 -04:00
/* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
2009-11-08 11:28:21 -05:00
*/
if ( ptw & PostTransportClearSubstate ) {
_play_range = false ;
unset_play_loop ( ) ;
}
2009-10-30 14:14:25 -04:00
/* this for() block can be put inside the previous if() and has the effect of ... ??? what */
2010-04-19 13:48:11 -04:00
DEBUG_TRACE ( DEBUG : : Transport , X_ ( " Butler PTW: locate \n " ) ) ;
2010-04-21 16:42:22 -04:00
for ( RouteList : : iterator i = r - > begin ( ) ; i ! = r - > end ( ) ; + + i ) {
DEBUG_TRACE ( DEBUG : : Transport , string_compose ( " Butler PTW: locate on %1 \n " , ( * i ) - > name ( ) ) ) ;
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr & & ! tr - > hidden ( ) ) {
tr - > non_realtime_locate ( _transport_frame ) ;
2009-10-28 19:56:05 -04:00
}
2010-04-19 13:48:11 -04:00
2009-10-28 19:56:05 -04:00
if ( on_entry ! = g_atomic_int_get ( & _butler - > should_do_transport_work ) ) {
finished = false ;
/* we will be back */
return ;
2008-06-02 17:41:35 -04:00
}
2009-10-28 19:53:16 -04:00
}
2008-06-02 17:41:35 -04:00
2009-10-28 19:56:05 -04:00
have_looped = false ;
2008-12-12 09:43:24 -05:00
2010-07-07 19:48:46 -04:00
send_full_time_code ( _transport_frame ) ;
2010-07-08 20:58:28 -04:00
MIDI : : Manager : : instance ( ) - > mmc ( ) - > send ( MIDI : : MachineControlCommand ( MIDI : : MachineControl : : cmdStop ) ) ;
send_mmc_locate ( _transport_frame ) ;
2008-12-12 09:43:24 -05:00
2009-11-08 11:28:21 -05:00
if ( ( ptw & PostTransportLocate ) & & get_record_enabled ( ) ) {
2008-06-02 17:41:35 -04:00
/* capture start has been changed, so save pending state */
save_state ( " " , true ) ;
saved = true ;
}
/* always try to get rid of this */
remove_pending_capture_state ( ) ;
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
/* save the current state of things if appropriate */
if ( did_record & & ! saved ) {
save_state ( _current_snapshot_name ) ;
}
2009-11-08 11:28:21 -05:00
if ( ptw & PostTransportStop ) {
2008-06-02 17:41:35 -04:00
_play_range = false ;
2009-10-30 14:14:25 -04:00
play_loop = false ;
2008-06-02 17:41:35 -04:00
}
Merged revisions 6293,6296-6306,6308 via svnmerge from
svn+ssh://ardoursvn@subversion.ardour.org/ardour2/branches/build_fixes
........
r6293 | trutkin | 2009-12-05 08:49:37 -0500 (Sat, 05 Dec 2009) | 2 lines
fix if-statement in build script
........
r6296 | trutkin | 2009-12-05 09:30:19 -0500 (Sat, 05 Dec 2009) | 5 lines
rearrange GTKOSX and darwin dependencies
- moved some GTKOSX include paths to generic darwin
- made GTKOSX dependent on being on darwin anyways
........
r6297 | trutkin | 2009-12-05 09:35:09 -0500 (Sat, 05 Dec 2009) | 2 lines
move coreaudio and audiounit handling to darwin section
........
r6298 | trutkin | 2009-12-05 09:53:40 -0500 (Sat, 05 Dec 2009) | 3 lines
use True/False instead of 1/0
fix another if-statement where it should be an elif-statement
........
r6299 | trutkin | 2009-12-05 14:11:09 -0500 (Sat, 05 Dec 2009) | 10 lines
fixes to get libardour building
- can't cast away volatile, so copy _transport_frame before emitting it.
- const_reverse_iterator::operator!=() isn't defined in this version of gcc.
- removed annoying HERE WE ARE CAAudioFile.h #warning.
- removed unnecessary include of sndfile.h in session.h.
- we don't want to set -march=i686 on the mac, so indent this if-statement so
it's only run on linux.
- DEBUG_STR() fails in the NDEBUG case, so wrap its use in an #ifndef NDEBUG
........
r6300 | trutkin | 2009-12-05 15:48:29 -0500 (Sat, 05 Dec 2009) | 2 lines
remove old scons-style CXXFLAGS_FOO in favor of just CXXFLAGS
........
r6301 | trutkin | 2009-12-05 16:01:10 -0500 (Sat, 05 Dec 2009) | 8 lines
clean up configure flags
- removed useless --aubio and --syslibs flags. The syslibs value is ignored
as we don't bring our own libraries with us anymoreand we use aubio
automatically if it's available
- added ways to turn off fpu_optimization and NLS
- fixed compiling on the mac without fpu_optimization
........
r6302 | trutkin | 2009-12-05 18:12:46 -0500 (Sat, 05 Dec 2009) | 5 lines
go back to prior uselib method for COREAUDIO, AUDIOUNIT, and GTKOSX
- fixed compile of CoreAudioSource
- re-did inclusion of coremidi_midiport.cc to depend on COREAUDIO presence
........
r6303 | trutkin | 2009-12-05 18:59:02 -0500 (Sat, 05 Dec 2009) | 5 lines
fixed compiler warnings about classes with virtual member functions, but no virtual destructor.
- Changed Metering to not use foo() = 0; to indicate it shouldn't be instantiated, but
private: Metering(), which is more idiomatic.
........
r6304 | trutkin | 2009-12-05 19:25:41 -0500 (Sat, 05 Dec 2009) | 2 lines
TOP_MENUBAR isn't used when building ardour.menus. Removed.
........
r6305 | trutkin | 2009-12-05 19:46:11 -0500 (Sat, 05 Dec 2009) | 5 lines
fix some AudioUnit compile errors
- update AudioUnit to use ChanCount
- fix some namespacing issues in audio_unit.h
........
r6306 | trutkin | 2009-12-05 20:08:48 -0500 (Sat, 05 Dec 2009) | 2 lines
make --extra-warn useful
........
r6308 | trutkin | 2009-12-05 22:59:42 -0500 (Sat, 05 Dec 2009) | 10 lines
fix compiling/linking with --coreaudio
- rearrange ardour_ui.h header in editor.cc to avoid conflict
- midi++ depends on OSX as well as COREAUDIO
- fixed including frameworks
- tweaked --extra-warn again. it's kinda redundent with --strict
- improved indentation in wscript
- use #ifdef HAVE_COREMIDI, not #if HAVE_COREMIDI. #if isn't interchangable
with #ifdef and won't work if HAVE_COREMIDI is defined with no value.
........
git-svn-id: svn://localhost/ardour2/branches/3.0@6310 d708f5d6-7413-0410-9779-e7cbd77b26cf
2009-12-05 23:35:48 -05:00
// can't cast away volatile so copy and emit that
nframes64_t tframe = _transport_frame ;
PositionChanged ( tframe ) ; /* EMIT SIGNAL */
2008-06-02 17:41:35 -04:00
TransportStateChange ( ) ; /* EMIT SIGNAL */
/* and start it up again if relevant */
2009-11-09 15:05:18 -05:00
if ( ( ptw & PostTransportLocate ) & & ! config . get_external_sync ( ) & & pending_locate_roll ) {
2008-06-02 17:41:35 -04:00
request_transport_speed ( 1.0 ) ;
pending_locate_roll = false ;
}
}
void
Session : : check_declick_out ( )
{
bool locate_required = transport_sub_state & PendingLocate ;
/* this is called after a process() iteration. if PendingDeclickOut was set,
it means that we were waiting to declick the output ( which has just been
done ) before doing something else . this is where we do that " something else " .
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
note : called from the audio thread .
*/
if ( transport_sub_state & PendingDeclickOut ) {
if ( locate_required ) {
start_locate ( pending_locate_frame , pending_locate_roll , pending_locate_flush ) ;
transport_sub_state & = ~ ( PendingDeclickOut | PendingLocate ) ;
} else {
stop_transport ( pending_abort ) ;
transport_sub_state & = ~ ( PendingDeclickOut | PendingLocate ) ;
}
}
}
void
2009-11-08 11:28:21 -05:00
Session : : unset_play_loop ( )
{
play_loop = false ;
2009-12-03 21:15:12 -05:00
clear_events ( SessionEvent : : AutoLoop ) ;
2009-11-08 11:28:21 -05:00
2010-04-21 16:42:22 -04:00
// set all tracks to NOT use internal looping
boost : : shared_ptr < RouteList > rl = routes . reader ( ) ;
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr & & ! tr - > hidden ( ) ) {
tr - > set_loop ( 0 ) ;
2009-11-08 11:28:21 -05:00
}
}
}
void
Session : : set_play_loop ( bool yn )
2008-06-02 17:41:35 -04:00
{
/* Called from event-handling context */
2008-08-04 18:37:24 -04:00
2009-10-30 14:14:25 -04:00
Location * loc ;
2009-11-08 11:28:21 -05:00
if ( yn = = play_loop | | ( actively_recording ( ) & & yn ) | | ( loc = _locations . auto_loop_location ( ) ) = = 0 ) {
/* nothing to do, or can't change loop status while recording */
2008-06-02 17:41:35 -04:00
return ;
}
2009-11-08 11:28:21 -05:00
2008-06-02 17:41:35 -04:00
set_dirty ( ) ;
2009-11-08 11:28:21 -05:00
2008-06-02 17:41:35 -04:00
if ( yn & & Config - > get_seamless_loop ( ) & & synced_to_jack ( ) ) {
2010-03-13 14:22:34 -05:00
warning < < string_compose ( _ ( " Seamless looping cannot be supported while %1 is using JACK transport. \n "
" Recommend changing the configured options " ) , PROGRAM_NAME )
2008-06-02 17:41:35 -04:00
< < endmsg ;
return ;
}
2009-11-08 11:28:21 -05:00
if ( yn ) {
2008-06-02 17:41:35 -04:00
2009-11-08 11:28:21 -05:00
play_loop = true ;
2008-06-02 17:41:35 -04:00
2009-10-30 14:14:25 -04:00
if ( loc ) {
2008-08-04 18:37:24 -04:00
2009-11-08 11:28:21 -05:00
unset_play_range ( ) ;
2008-06-02 17:41:35 -04:00
if ( Config - > get_seamless_loop ( ) ) {
2010-04-21 16:42:22 -04:00
// set all tracks to use internal looping
boost : : shared_ptr < RouteList > rl = routes . reader ( ) ;
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr & & ! tr - > hidden ( ) ) {
tr - > set_loop ( loc ) ;
2008-06-02 17:41:35 -04:00
}
}
}
else {
2010-04-21 16:42:22 -04:00
// set all tracks to NOT use internal looping
boost : : shared_ptr < RouteList > rl = routes . reader ( ) ;
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr & & ! tr - > hidden ( ) ) {
tr - > set_loop ( 0 ) ;
2008-06-02 17:41:35 -04:00
}
}
}
2009-11-08 11:28:21 -05:00
/* put the loop event into the event list */
2009-12-03 21:15:12 -05:00
SessionEvent * event = new SessionEvent ( SessionEvent : : AutoLoop , SessionEvent : : Replace , loc - > end ( ) , loc - > start ( ) , 0.0f ) ;
2008-06-02 17:41:35 -04:00
merge_event ( event ) ;
2009-11-08 11:28:21 -05:00
/* locate to start of loop and roll. If doing seamless loop, force a
locate + buffer refill even if we are positioned there already .
*/
2008-06-02 17:41:35 -04:00
2009-11-08 11:28:21 -05:00
start_locate ( loc - > start ( ) , true , true , false , Config - > get_seamless_loop ( ) ) ;
}
2008-06-02 17:41:35 -04:00
} else {
2008-08-04 18:37:24 -04:00
2009-11-08 11:28:21 -05:00
unset_play_loop ( ) ;
2008-06-02 17:41:35 -04:00
}
2009-11-08 11:28:21 -05:00
TransportStateChange ( ) ;
}
2008-06-02 17:41:35 -04:00
void
Session : : flush_all_inserts ( )
{
boost : : shared_ptr < RouteList > r = routes . reader ( ) ;
for ( RouteList : : iterator i = r - > begin ( ) ; i ! = r - > end ( ) ; + + i ) {
( * i ) - > flush_processors ( ) ;
}
}
void
2009-11-08 11:28:21 -05:00
Session : : start_locate ( nframes64_t target_frame , bool with_roll , bool with_flush , bool with_loop , bool force )
2008-06-02 17:41:35 -04:00
{
if ( synced_to_jack ( ) ) {
2009-01-09 04:18:24 -05:00
double sp ;
2009-11-08 11:28:21 -05:00
nframes64_t pos ;
2008-06-02 17:41:35 -04:00
_slave - > speed_and_position ( sp , pos ) ;
if ( target_frame ! = pos ) {
/* tell JACK to change transport position, and we will
follow along later in : : follow_slave ( )
*/
_engine . transport_locate ( target_frame ) ;
if ( sp ! = 1.0f & & with_roll ) {
_engine . transport_start ( ) ;
}
}
} else {
2009-11-08 11:28:21 -05:00
locate ( target_frame , with_roll , with_flush , with_loop , force ) ;
2008-06-02 17:41:35 -04:00
}
}
2008-09-10 11:03:30 -04:00
int
Session : : micro_locate ( nframes_t distance )
{
2010-04-21 16:42:22 -04:00
boost : : shared_ptr < RouteList > rl = routes . reader ( ) ;
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr & & ! tr - > can_internal_playback_seek ( distance ) ) {
2008-09-10 11:03:30 -04:00
return - 1 ;
}
}
2010-04-21 16:42:22 -04:00
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr ) {
tr - > internal_playback_seek ( distance ) ;
}
2008-09-10 11:03:30 -04:00
}
2009-10-14 12:10:01 -04:00
2008-09-10 11:03:30 -04:00
_transport_frame + = distance ;
return 0 ;
}
2010-06-28 13:25:40 -04:00
/** @param with_mmc true to send a MMC locate command when the locate is done */
2008-06-02 17:41:35 -04:00
void
2010-06-28 13:25:40 -04:00
Session : : locate ( nframes64_t target_frame , bool with_roll , bool with_flush , bool with_loop , bool force , bool with_mmc )
2008-06-02 17:41:35 -04:00
{
if ( actively_recording ( ) & & ! with_loop ) {
return ;
}
2009-11-08 11:28:21 -05:00
if ( ! force & & _transport_frame = = target_frame & & ! loop_changing & & ! with_loop ) {
2008-06-02 17:41:35 -04:00
if ( with_roll ) {
set_transport_speed ( 1.0 , false ) ;
}
loop_changing = false ;
2010-07-04 21:13:18 -04:00
Located ( ) ; /* EMIT SIGNAL */
2008-06-02 17:41:35 -04:00
return ;
}
2009-10-26 10:38:58 -04:00
// Update Timecode time
2008-06-02 17:41:35 -04:00
// [DR] FIXME: find out exactly where this should go below
_transport_frame = target_frame ;
2009-10-26 10:38:58 -04:00
timecode_time ( _transport_frame , transmitting_timecode_time ) ;
outbound_mtc_timecode_frame = _transport_frame ;
2008-06-02 17:41:35 -04:00
next_quarter_frame_to_send = 0 ;
if ( _transport_speed & & ( ! with_loop | | loop_changing ) ) {
/* schedule a declick. we'll be called again when its done */
if ( ! ( transport_sub_state & PendingDeclickOut ) ) {
transport_sub_state | = ( PendingDeclickOut | PendingLocate ) ;
pending_locate_frame = target_frame ;
pending_locate_roll = with_roll ;
pending_locate_flush = with_flush ;
return ;
2008-08-04 18:37:24 -04:00
}
2008-06-02 17:41:35 -04:00
}
2009-05-13 20:13:27 -04:00
if ( transport_rolling ( ) & & ( ! auto_play_legal | | ! config . get_auto_play ( ) ) & & ! with_roll & & ! ( synced_to_jack ( ) & & play_loop ) ) {
2009-11-08 11:28:21 -05:00
realtime_stop ( false , true ) ; // XXX paul - check if the 2nd arg is really correct
2008-08-04 18:37:24 -04:00
}
2008-06-02 17:41:35 -04:00
2009-11-08 11:28:21 -05:00
if ( force | | ! with_loop | | loop_changing ) {
2008-06-02 17:41:35 -04:00
2009-11-08 11:28:21 -05:00
PostTransportWork todo = PostTransportLocate ;
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
if ( with_roll ) {
2009-11-08 11:28:21 -05:00
todo = PostTransportWork ( todo | PostTransportRoll ) ;
}
2008-06-02 17:41:35 -04:00
2009-11-08 11:28:21 -05:00
add_post_transport_work ( todo ) ;
2009-10-23 20:39:28 -04:00
_butler - > schedule_transport_work ( ) ;
2008-06-02 17:41:35 -04:00
} else {
/* this is functionally what clear_clicks() does but with a tentative lock */
Glib : : RWLock : : WriterLock clickm ( click_lock , Glib : : TRY_LOCK ) ;
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
if ( clickm . locked ( ) ) {
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
for ( Clicks : : iterator i = clicks . begin ( ) ; i ! = clicks . end ( ) ; + + i ) {
delete * i ;
}
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
clicks . clear ( ) ;
}
}
if ( with_roll ) {
/* switch from input if we're going to roll */
if ( Config - > get_monitoring_model ( ) = = HardwareMonitoring ) {
2010-04-21 16:42:22 -04:00
boost : : shared_ptr < RouteList > rl = routes . reader ( ) ;
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr & & tr - > record_enabled ( ) ) {
2008-06-02 17:41:35 -04:00
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
2010-04-21 16:42:22 -04:00
tr - > monitor_input ( ! config . get_auto_input ( ) ) ;
2008-06-02 17:41:35 -04:00
}
}
}
} else {
/* otherwise we're going to stop, so do the opposite */
if ( Config - > get_monitoring_model ( ) = = HardwareMonitoring ) {
2010-04-21 16:42:22 -04:00
boost : : shared_ptr < RouteList > rl = routes . reader ( ) ;
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr & & tr - > record_enabled ( ) ) {
2008-06-02 17:41:35 -04:00
//cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
2010-04-21 16:42:22 -04:00
tr - > monitor_input ( true ) ;
2008-06-02 17:41:35 -04:00
}
}
}
}
/* cancel looped playback if transport pos outside of loop range */
if ( play_loop ) {
Location * al = _locations . auto_loop_location ( ) ;
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
if ( al & & ( _transport_frame < al - > start ( ) | | _transport_frame > al - > end ( ) ) ) {
// cancel looping directly, this is called from event handling context
2009-11-08 11:28:21 -05:00
set_play_loop ( false ) ;
2008-06-02 17:41:35 -04:00
}
else if ( al & & _transport_frame = = al - > start ( ) ) {
if ( with_loop ) {
// this is only necessary for seamless looping
2010-04-21 16:42:22 -04:00
boost : : shared_ptr < RouteList > rl = routes . reader ( ) ;
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr & & tr - > record_enabled ( ) ) {
2008-06-02 17:41:35 -04:00
// tell it we've looped, so it can deal with the record state
2010-04-21 16:42:22 -04:00
tr - > transport_looped ( _transport_frame ) ;
2008-06-02 17:41:35 -04:00
}
}
}
2008-12-12 09:43:24 -05:00
have_looped = true ;
2008-06-02 17:41:35 -04:00
TransportLooped ( ) ; // EMIT SIGNAL
}
}
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
loop_changing = false ;
2009-10-26 10:38:58 -04:00
_send_timecode_update = true ;
2009-07-20 19:42:37 -04:00
2010-07-02 20:11:33 -04:00
if ( with_mmc ) {
2010-07-04 21:13:36 -04:00
send_mmc_locate ( _transport_frame ) ;
2010-06-28 13:25:40 -04:00
}
2009-07-20 19:42:37 -04:00
Located ( ) ; /* EMIT SIGNAL */
2008-06-02 17:41:35 -04:00
}
/** Set the transport speed.
* @ param speed New speed
* @ param abort
*/
void
2009-11-08 11:28:21 -05:00
Session : : set_transport_speed ( double speed , bool abort , bool clear_state )
2008-06-02 17:41:35 -04:00
{
2009-11-30 11:12:13 -05:00
DEBUG_TRACE ( DEBUG : : Transport , string_compose ( " Set transport speed to %1, abort = %2 clear_state = %3, current = %4 \n " , speed , abort , clear_state , _transport_speed ) ) ;
2008-06-02 17:41:35 -04:00
if ( _transport_speed = = speed ) {
return ;
}
2009-06-09 20:03:47 -04:00
_target_transport_speed = fabs ( speed ) ;
2009-05-13 17:34:09 -04:00
/* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
and user needs . We really need CD - style " skip " playback for ffwd and rewind .
*/
2009-10-14 12:10:01 -04:00
2008-06-02 17:41:35 -04:00
if ( speed > 0 ) {
2009-01-09 04:18:24 -05:00
speed = min ( 8.0 , speed ) ;
2008-06-02 17:41:35 -04:00
} else if ( speed < 0 ) {
2009-01-09 04:18:24 -05:00
speed = max ( - 8.0 , speed ) ;
2008-06-02 17:41:35 -04:00
}
if ( transport_rolling ( ) & & speed = = 0.0 ) {
/* we are rolling and we want to stop */
if ( Config - > get_monitoring_model ( ) = = HardwareMonitoring )
{
2010-04-21 16:42:22 -04:00
boost : : shared_ptr < RouteList > rl = routes . reader ( ) ;
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr & & tr - > record_enabled ( ) ) {
2008-06-02 17:41:35 -04:00
//cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
2010-04-21 16:42:22 -04:00
tr - > monitor_input ( true ) ;
2008-06-02 17:41:35 -04:00
}
}
}
if ( synced_to_jack ( ) ) {
2009-11-08 11:28:21 -05:00
if ( clear_state ) {
/* do this here because our response to the slave won't
take care of it .
*/
_play_range = false ;
unset_play_loop ( ) ;
}
2008-06-02 17:41:35 -04:00
_engine . transport_stop ( ) ;
} else {
stop_transport ( abort ) ;
}
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
} else if ( transport_stopped ( ) & & speed = = 1.0 ) {
/* we are stopped and we want to start rolling at speed 1 */
if ( Config - > get_monitoring_model ( ) = = HardwareMonitoring ) {
2010-04-21 16:42:22 -04:00
boost : : shared_ptr < RouteList > rl = routes . reader ( ) ;
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( config . get_auto_input ( ) & & tr & & tr - > record_enabled ( ) ) {
2008-06-02 17:41:35 -04:00
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
2010-04-21 16:42:22 -04:00
tr - > monitor_input ( false ) ;
2008-06-02 17:41:35 -04:00
}
}
}
if ( synced_to_jack ( ) ) {
_engine . transport_start ( ) ;
} else {
start_transport ( ) ;
}
} else {
if ( ( synced_to_jack ( ) ) & & speed ! = 0.0 & & speed ! = 1.0 ) {
2010-03-13 14:22:34 -05:00
warning < < string_compose ( _ ( " Global varispeed cannot be supported while %1 is connected to JACK transport control " ) ,
PROGRAM_NAME )
2008-06-02 17:41:35 -04:00
< < endmsg ;
return ;
}
if ( actively_recording ( ) ) {
return ;
}
2009-01-09 04:18:24 -05:00
if ( speed > 0.0 & & _transport_frame = = current_end_frame ( ) ) {
2008-06-02 17:41:35 -04:00
return ;
}
2009-01-09 04:18:24 -05:00
if ( speed < 0.0 & & _transport_frame = = 0 ) {
2008-06-02 17:41:35 -04:00
return ;
}
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
clear_clicks ( ) ;
/* if we are reversing relative to the current speed, or relative to the speed
before the last stop , then we have to do extra work .
*/
2009-11-08 11:28:21 -05:00
PostTransportWork todo = PostTransportWork ( 0 ) ;
2008-06-02 17:41:35 -04:00
2009-01-09 04:18:24 -05:00
if ( ( _transport_speed & & speed * _transport_speed < 0.0 ) | | ( _last_transport_speed * speed < 0.0 ) | | ( _last_transport_speed = = 0.0f & & speed < 0.0f ) ) {
2009-11-08 11:28:21 -05:00
todo = PostTransportWork ( todo | PostTransportReverse ) ;
2010-04-26 20:57:46 -04:00
_last_roll_or_reversal_location = _transport_frame ;
2008-06-02 17:41:35 -04:00
}
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
_last_transport_speed = _transport_speed ;
_transport_speed = speed ;
2008-08-04 18:37:24 -04:00
2010-04-21 16:42:22 -04:00
boost : : shared_ptr < RouteList > rl = routes . reader ( ) ;
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr & & tr - > realtime_set_speed ( tr - > speed ( ) , true ) ) {
2009-11-08 11:28:21 -05:00
todo = PostTransportWork ( todo | PostTransportSpeed ) ;
break ;
2008-06-02 17:41:35 -04:00
}
}
2008-08-04 18:37:24 -04:00
2009-11-08 11:28:21 -05:00
if ( todo ) {
add_post_transport_work ( todo ) ;
2009-10-23 20:39:28 -04:00
_butler - > schedule_transport_work ( ) ;
2008-06-02 17:41:35 -04:00
}
}
}
/** Stop the transport. */
void
2009-11-08 11:28:21 -05:00
Session : : stop_transport ( bool abort , bool clear_state )
2008-06-02 17:41:35 -04:00
{
if ( _transport_speed = = 0.0f ) {
return ;
}
2008-08-04 18:37:24 -04:00
2010-04-12 18:35:06 -04:00
if ( actively_recording ( ) & & ! ( transport_sub_state & StopPendingCapture ) & & _worst_output_latency > current_block_size ) {
2010-04-21 16:42:22 -04:00
boost : : shared_ptr < RouteList > rl = routes . reader ( ) ;
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr ) {
tr - > prepare_to_stop ( _transport_frame ) ;
}
2010-04-12 18:35:06 -04:00
}
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
/* we need to capture the audio that has still not yet been received by the system
at the time the stop is requested , so we have to roll past that time .
we want to declick before stopping , so schedule the autostop for one
block before the actual end . we ' ll declick in the subsequent block ,
and then we ' ll really be stopped .
*/
2008-08-04 18:37:24 -04:00
2009-12-03 21:15:12 -05:00
SessionEvent * ev = new SessionEvent ( SessionEvent : : StopOnce , SessionEvent : : Replace ,
2008-06-02 17:41:35 -04:00
_transport_frame + _worst_output_latency - current_block_size ,
0 , 0 , abort ) ;
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
merge_event ( ev ) ;
transport_sub_state | = StopPendingCapture ;
pending_abort = abort ;
return ;
2008-08-04 18:37:24 -04:00
}
2008-06-02 17:41:35 -04:00
if ( ( transport_sub_state & PendingDeclickOut ) = = 0 ) {
2010-04-12 18:35:06 -04:00
if ( ! ( transport_sub_state & StopPendingCapture ) ) {
2010-04-21 16:42:22 -04:00
boost : : shared_ptr < RouteList > rl = routes . reader ( ) ;
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr ) {
tr - > prepare_to_stop ( _transport_frame ) ;
}
2010-04-12 18:35:06 -04:00
}
}
2008-06-02 17:41:35 -04:00
transport_sub_state | = PendingDeclickOut ;
/* we'll be called again after the declick */
pending_abort = abort ;
return ;
}
2009-11-08 11:28:21 -05:00
realtime_stop ( abort , clear_state ) ;
2009-10-23 20:39:28 -04:00
_butler - > schedule_transport_work ( ) ;
2008-06-02 17:41:35 -04:00
}
void
Session : : start_transport ( )
{
_last_roll_location = _transport_frame ;
2010-04-26 20:57:46 -04:00
_last_roll_or_reversal_location = _transport_frame ;
2008-12-12 09:43:24 -05:00
have_looped = false ;
2008-06-02 17:41:35 -04:00
/* if record status is Enabled, move it to Recording. if its
2008-08-04 18:37:24 -04:00
already Recording , move it to Disabled .
2008-06-02 17:41:35 -04:00
*/
switch ( record_status ( ) ) {
case Enabled :
2009-05-13 20:13:27 -04:00
if ( ! config . get_punch_in ( ) ) {
2008-06-02 17:41:35 -04:00
enable_record ( ) ;
}
break ;
case Recording :
if ( ! play_loop ) {
disable_record ( false ) ;
}
break ;
default :
break ;
}
transport_sub_state | = PendingDeclickIn ;
2009-10-14 12:10:01 -04:00
2008-06-02 17:41:35 -04:00
_transport_speed = 1.0 ;
2009-06-09 20:03:47 -04:00
_target_transport_speed = 1.0 ;
2008-08-04 18:37:24 -04:00
2010-04-21 16:42:22 -04:00
boost : : shared_ptr < RouteList > rl = routes . reader ( ) ;
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr ) {
tr - > realtime_set_speed ( tr - > speed ( ) , true ) ;
}
2008-06-02 17:41:35 -04:00
}
2010-07-02 20:11:33 -04:00
Timecode : : Time time ;
timecode_time_subframes ( _transport_frame , time ) ;
2010-07-08 18:55:20 -04:00
MIDI : : Manager : : instance ( ) - > mmc ( ) - > send ( MIDI : : MachineControlCommand ( MIDI : : MachineControl : : cmdDeferredPlay ) ) ;
2008-06-02 17:41:35 -04:00
TransportStateChange ( ) ; /* EMIT SIGNAL */
}
/** Do any transport work in the audio thread that needs to be done after the
* transport thread is finished . Audio thread , realtime safe .
*/
void
Session : : post_transport ( )
{
2009-11-08 11:28:21 -05:00
PostTransportWork ptw = post_transport_work ( ) ;
if ( ptw & PostTransportAudition ) {
2010-03-24 23:40:07 -04:00
if ( auditioner & & auditioner - > auditioning ( ) ) {
2008-06-02 17:41:35 -04:00
process_function = & Session : : process_audition ;
} else {
process_function = & Session : : process_with_events ;
}
}
2009-11-08 11:28:21 -05:00
if ( ptw & PostTransportStop ) {
2008-06-02 17:41:35 -04:00
transport_sub_state = 0 ;
}
2009-11-08 11:28:21 -05:00
if ( ptw & PostTransportLocate ) {
2008-06-02 17:41:35 -04:00
2009-11-09 15:05:18 -05:00
if ( ( ( ! config . get_external_sync ( ) & & ( auto_play_legal & & config . get_auto_play ( ) ) ) & & ! _exporting ) | | ( ptw & PostTransportRoll ) ) {
2008-06-02 17:41:35 -04:00
start_transport ( ) ;
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
} else {
transport_sub_state = 0 ;
}
}
set_next_event ( ) ;
2009-11-08 11:28:21 -05:00
/* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
know were handled ?
*/
set_post_transport_work ( PostTransportWork ( 0 ) ) ;
2008-06-02 17:41:35 -04:00
}
void
Session : : reset_rf_scale ( nframes_t motion )
{
cumulative_rf_motion + = motion ;
if ( cumulative_rf_motion < 4 * _current_frame_rate ) {
rf_scale = 1 ;
} else if ( cumulative_rf_motion < 8 * _current_frame_rate ) {
rf_scale = 4 ;
} else if ( cumulative_rf_motion < 16 * _current_frame_rate ) {
rf_scale = 10 ;
} else {
rf_scale = 100 ;
}
if ( motion ! = 0 ) {
set_dirty ( ) ;
}
}
void
2009-12-03 13:44:06 -05:00
Session : : use_sync_source ( Slave * new_slave )
2008-06-02 17:41:35 -04:00
{
2009-12-03 13:44:06 -05:00
/* Runs in process() context */
2008-06-02 17:41:35 -04:00
bool non_rt_required = false ;
2009-12-03 13:44:06 -05:00
/* XXX this deletion is problematic because we're in RT context */
2008-06-02 17:41:35 -04:00
2008-12-18 14:31:00 -05:00
delete _slave ;
2009-12-03 13:44:06 -05:00
_slave = new_slave ;
2008-06-02 17:41:35 -04:00
2010-04-21 16:42:22 -04:00
boost : : shared_ptr < RouteList > rl = routes . reader ( ) ;
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr & & ! tr - > hidden ( ) ) {
if ( tr - > realtime_set_speed ( tr - > speed ( ) , true ) ) {
2009-11-09 15:05:18 -05:00
non_rt_required = true ;
}
2010-04-21 16:42:22 -04:00
tr - > set_slaved ( _slave ! = 0 ) ;
2009-11-09 15:05:18 -05:00
}
2008-06-02 17:41:35 -04:00
}
2009-11-09 15:05:18 -05:00
if ( non_rt_required ) {
add_post_transport_work ( PostTransportSpeed ) ;
_butler - > schedule_transport_work ( ) ;
}
2008-08-04 18:37:24 -04:00
2009-11-09 15:05:18 -05:00
set_dirty ( ) ;
}
void
2009-12-03 13:44:06 -05:00
Session : : drop_sync_source ( )
2009-11-09 15:05:18 -05:00
{
2009-12-03 13:44:06 -05:00
request_sync_source ( 0 ) ;
}
2009-11-09 15:05:18 -05:00
2009-12-03 13:44:06 -05:00
void
Session : : switch_to_sync_source ( SyncSource src )
{
Slave * new_slave ;
2009-11-09 15:05:18 -05:00
2009-12-03 13:44:06 -05:00
DEBUG_TRACE ( DEBUG : : Slave , string_compose ( " Setting up sync source %1 \n " , enum_2_string ( src ) ) ) ;
2009-11-09 15:05:18 -05:00
switch ( src ) {
2008-06-02 17:41:35 -04:00
case MTC :
2009-12-03 13:44:06 -05:00
if ( _slave & & dynamic_cast < MTC_Slave * > ( _slave ) ) {
return ;
}
2010-07-08 18:55:20 -04:00
try {
new_slave = new MTC_Slave ( * this , * MIDI : : Manager : : instance ( ) - > mtc_input_port ( ) ) ;
}
2008-06-02 17:41:35 -04:00
2010-07-08 18:55:20 -04:00
catch ( failed_constructor & err ) {
2008-06-02 17:41:35 -04:00
return ;
}
break ;
2008-08-04 18:37:24 -04:00
case MIDIClock :
2009-12-03 13:44:06 -05:00
if ( _slave & & dynamic_cast < MIDIClock_Slave * > ( _slave ) ) {
return ;
}
2010-07-08 18:55:20 -04:00
try {
new_slave = new MIDIClock_Slave ( * this , * MIDI : : Manager : : instance ( ) - > midi_clock_input_port ( ) , 24 ) ;
}
catch ( failed_constructor & err ) {
2008-08-04 18:37:24 -04:00
return ;
}
break ;
2008-06-02 17:41:35 -04:00
case JACK :
2009-12-03 13:44:06 -05:00
if ( _slave & & dynamic_cast < JACK_Slave * > ( _slave ) ) {
return ;
2008-06-02 17:41:35 -04:00
}
2009-12-03 13:44:06 -05:00
new_slave = new JACK_Slave ( _engine . jack ( ) ) ;
break ;
default :
new_slave = 0 ;
break ;
} ;
2008-06-02 17:41:35 -04:00
2009-12-03 13:44:06 -05:00
request_sync_source ( new_slave ) ;
2008-06-02 17:41:35 -04:00
}
void
2010-04-21 16:42:22 -04:00
Session : : reverse_track_buffers ( )
2008-06-02 17:41:35 -04:00
{
2009-11-08 11:28:21 -05:00
add_post_transport_work ( PostTransportReverse ) ;
2009-10-23 20:39:28 -04:00
_butler - > schedule_transport_work ( ) ;
2008-06-02 17:41:35 -04:00
}
void
2010-04-21 16:42:22 -04:00
Session : : set_track_speed ( Track * track , double speed )
2008-06-02 17:41:35 -04:00
{
2010-04-21 16:42:22 -04:00
if ( track - > realtime_set_speed ( speed , false ) ) {
2009-11-08 11:28:21 -05:00
add_post_transport_work ( PostTransportSpeed ) ;
2009-10-23 20:39:28 -04:00
_butler - > schedule_transport_work ( ) ;
2008-06-02 17:41:35 -04:00
set_dirty ( ) ;
}
}
void
2009-11-08 11:28:21 -05:00
Session : : unset_play_range ( )
2008-06-02 17:41:35 -04:00
{
2009-11-08 11:28:21 -05:00
_play_range = false ;
2009-12-03 21:15:12 -05:00
_clear_event_type ( SessionEvent : : RangeStop ) ;
_clear_event_type ( SessionEvent : : RangeLocate ) ;
2008-06-02 17:41:35 -04:00
}
void
2009-11-08 11:28:21 -05:00
Session : : set_play_range ( list < AudioRange > & range , bool leave_rolling )
2008-06-02 17:41:35 -04:00
{
2009-12-03 21:15:12 -05:00
SessionEvent * ev ;
2008-08-04 18:37:24 -04:00
2009-11-08 11:28:21 -05:00
/* Called from event-processing context */
2008-06-02 17:41:35 -04:00
2009-11-08 11:28:21 -05:00
unset_play_range ( ) ;
if ( range . empty ( ) ) {
/* _play_range set to false in unset_play_range()
*/
if ( ! leave_rolling ) {
/* stop transport */
2009-12-03 21:15:12 -05:00
SessionEvent * ev = new SessionEvent ( SessionEvent : : SetTransportSpeed , SessionEvent : : Add , SessionEvent : : Immediate , 0 , 0.0f , false ) ;
2009-11-08 11:28:21 -05:00
merge_event ( ev ) ;
}
2008-06-02 17:41:35 -04:00
return ;
}
2009-11-08 11:28:21 -05:00
_play_range = true ;
2008-08-04 18:37:24 -04:00
2009-11-08 11:28:21 -05:00
/* cancel loop play */
unset_play_loop ( ) ;
2008-08-04 18:37:24 -04:00
2009-11-08 11:28:21 -05:00
list < AudioRange > : : size_type sz = range . size ( ) ;
if ( sz > 1 ) {
list < AudioRange > : : iterator i = range . begin ( ) ;
2008-06-02 17:41:35 -04:00
list < AudioRange > : : iterator next ;
2009-11-08 11:28:21 -05:00
while ( i ! = range . end ( ) ) {
2008-06-02 17:41:35 -04:00
next = i ;
+ + next ;
2009-11-08 11:28:21 -05:00
2008-06-02 17:41:35 -04:00
/* locating/stopping is subject to delays for declicking.
*/
2009-11-08 11:28:21 -05:00
2008-06-02 17:41:35 -04:00
nframes_t requested_frame = ( * i ) . end ;
2009-11-08 11:28:21 -05:00
2008-06-02 17:41:35 -04:00
if ( requested_frame > current_block_size ) {
requested_frame - = current_block_size ;
} else {
requested_frame = 0 ;
}
2009-11-08 11:28:21 -05:00
if ( next = = range . end ( ) ) {
2009-12-03 21:15:12 -05:00
ev = new SessionEvent ( SessionEvent : : RangeStop , SessionEvent : : Add , requested_frame , 0 , 0.0f ) ;
2008-06-02 17:41:35 -04:00
} else {
2009-12-03 21:15:12 -05:00
ev = new SessionEvent ( SessionEvent : : RangeLocate , SessionEvent : : Add , requested_frame , ( * next ) . start , 0.0f ) ;
2008-06-02 17:41:35 -04:00
}
2009-11-08 11:28:21 -05:00
2008-06-02 17:41:35 -04:00
merge_event ( ev ) ;
2009-11-08 11:28:21 -05:00
2008-06-02 17:41:35 -04:00
i = next ;
}
2009-11-08 11:28:21 -05:00
2008-06-02 17:41:35 -04:00
} else if ( sz = = 1 ) {
2008-08-04 18:37:24 -04:00
2009-12-03 21:15:12 -05:00
ev = new SessionEvent ( SessionEvent : : RangeStop , SessionEvent : : Add , range . front ( ) . end , 0 , 0.0f ) ;
2008-06-02 17:41:35 -04:00
merge_event ( ev ) ;
2009-11-08 11:28:21 -05:00
}
2008-08-04 18:37:24 -04:00
2009-11-08 11:28:21 -05:00
/* save range so we can do auto-return etc. */
current_audio_range = range ;
2008-06-02 17:41:35 -04:00
/* now start rolling at the right place */
2008-08-04 18:37:24 -04:00
2009-12-03 21:15:12 -05:00
ev = new SessionEvent ( SessionEvent : : LocateRoll , SessionEvent : : Add , SessionEvent : : Immediate , range . front ( ) . start , 0.0f , false ) ;
2008-06-02 17:41:35 -04:00
merge_event ( ev ) ;
2009-11-08 11:28:21 -05:00
TransportStateChange ( ) ;
2008-06-02 17:41:35 -04:00
}
void
2009-11-08 11:28:21 -05:00
Session : : request_bounded_roll ( nframes_t start , nframes_t end )
2008-06-02 17:41:35 -04:00
{
2009-11-08 11:28:21 -05:00
AudioRange ar ( start , end , 0 ) ;
list < AudioRange > lar ;
2008-06-02 17:41:35 -04:00
2009-11-08 11:28:21 -05:00
lar . push_back ( ar ) ;
request_play_range ( & lar , true ) ;
}
2008-06-02 17:41:35 -04:00
void
2009-11-08 11:28:21 -05:00
Session : : request_roll_at_and_return ( nframes_t start , nframes_t return_to )
2008-06-02 17:41:35 -04:00
{
2009-12-03 21:15:12 -05:00
SessionEvent * ev = new SessionEvent ( SessionEvent : : LocateRollLocate , SessionEvent : : Add , SessionEvent : : Immediate , return_to , 1.0 ) ;
2009-11-08 11:28:21 -05:00
ev - > target2_frame = start ;
2008-06-02 17:41:35 -04:00
queue_event ( ev ) ;
}
void
Session : : engine_halted ( )
{
bool ignored ;
/* there will be no more calls to process(), so
we ' d better clean up for ourselves , right now .
2008-08-04 18:37:24 -04:00
but first , make sure the butler is out of
2008-06-02 17:41:35 -04:00
the picture .
*/
2009-10-23 20:39:28 -04:00
g_atomic_int_set ( & _butler - > should_do_transport_work , 0 ) ;
2009-11-08 11:28:21 -05:00
set_post_transport_work ( PostTransportWork ( 0 ) ) ;
2009-10-23 20:39:28 -04:00
_butler - > stop ( ) ;
2008-08-04 18:37:24 -04:00
2009-11-08 11:28:21 -05:00
realtime_stop ( false , true ) ;
2008-06-02 17:41:35 -04:00
non_realtime_stop ( false , 0 , ignored ) ;
transport_sub_state = 0 ;
TransportStateChange ( ) ; /* EMIT SIGNAL */
}
void
Session : : xrun_recovery ( )
{
Merged revisions 6293,6296-6306,6308 via svnmerge from
svn+ssh://ardoursvn@subversion.ardour.org/ardour2/branches/build_fixes
........
r6293 | trutkin | 2009-12-05 08:49:37 -0500 (Sat, 05 Dec 2009) | 2 lines
fix if-statement in build script
........
r6296 | trutkin | 2009-12-05 09:30:19 -0500 (Sat, 05 Dec 2009) | 5 lines
rearrange GTKOSX and darwin dependencies
- moved some GTKOSX include paths to generic darwin
- made GTKOSX dependent on being on darwin anyways
........
r6297 | trutkin | 2009-12-05 09:35:09 -0500 (Sat, 05 Dec 2009) | 2 lines
move coreaudio and audiounit handling to darwin section
........
r6298 | trutkin | 2009-12-05 09:53:40 -0500 (Sat, 05 Dec 2009) | 3 lines
use True/False instead of 1/0
fix another if-statement where it should be an elif-statement
........
r6299 | trutkin | 2009-12-05 14:11:09 -0500 (Sat, 05 Dec 2009) | 10 lines
fixes to get libardour building
- can't cast away volatile, so copy _transport_frame before emitting it.
- const_reverse_iterator::operator!=() isn't defined in this version of gcc.
- removed annoying HERE WE ARE CAAudioFile.h #warning.
- removed unnecessary include of sndfile.h in session.h.
- we don't want to set -march=i686 on the mac, so indent this if-statement so
it's only run on linux.
- DEBUG_STR() fails in the NDEBUG case, so wrap its use in an #ifndef NDEBUG
........
r6300 | trutkin | 2009-12-05 15:48:29 -0500 (Sat, 05 Dec 2009) | 2 lines
remove old scons-style CXXFLAGS_FOO in favor of just CXXFLAGS
........
r6301 | trutkin | 2009-12-05 16:01:10 -0500 (Sat, 05 Dec 2009) | 8 lines
clean up configure flags
- removed useless --aubio and --syslibs flags. The syslibs value is ignored
as we don't bring our own libraries with us anymoreand we use aubio
automatically if it's available
- added ways to turn off fpu_optimization and NLS
- fixed compiling on the mac without fpu_optimization
........
r6302 | trutkin | 2009-12-05 18:12:46 -0500 (Sat, 05 Dec 2009) | 5 lines
go back to prior uselib method for COREAUDIO, AUDIOUNIT, and GTKOSX
- fixed compile of CoreAudioSource
- re-did inclusion of coremidi_midiport.cc to depend on COREAUDIO presence
........
r6303 | trutkin | 2009-12-05 18:59:02 -0500 (Sat, 05 Dec 2009) | 5 lines
fixed compiler warnings about classes with virtual member functions, but no virtual destructor.
- Changed Metering to not use foo() = 0; to indicate it shouldn't be instantiated, but
private: Metering(), which is more idiomatic.
........
r6304 | trutkin | 2009-12-05 19:25:41 -0500 (Sat, 05 Dec 2009) | 2 lines
TOP_MENUBAR isn't used when building ardour.menus. Removed.
........
r6305 | trutkin | 2009-12-05 19:46:11 -0500 (Sat, 05 Dec 2009) | 5 lines
fix some AudioUnit compile errors
- update AudioUnit to use ChanCount
- fix some namespacing issues in audio_unit.h
........
r6306 | trutkin | 2009-12-05 20:08:48 -0500 (Sat, 05 Dec 2009) | 2 lines
make --extra-warn useful
........
r6308 | trutkin | 2009-12-05 22:59:42 -0500 (Sat, 05 Dec 2009) | 10 lines
fix compiling/linking with --coreaudio
- rearrange ardour_ui.h header in editor.cc to avoid conflict
- midi++ depends on OSX as well as COREAUDIO
- fixed including frameworks
- tweaked --extra-warn again. it's kinda redundent with --strict
- improved indentation in wscript
- use #ifdef HAVE_COREMIDI, not #if HAVE_COREMIDI. #if isn't interchangable
with #ifdef and won't work if HAVE_COREMIDI is defined with no value.
........
git-svn-id: svn://localhost/ardour2/branches/3.0@6310 d708f5d6-7413-0410-9779-e7cbd77b26cf
2009-12-05 23:35:48 -05:00
// can't cast away volatile so copy and emit that
nframes64_t tframe = _transport_frame ;
Xrun ( tframe ) ; //EMIT SIGNAL
2008-06-02 17:41:35 -04:00
if ( Config - > get_stop_recording_on_xrun ( ) & & actively_recording ( ) ) {
/* it didn't actually halt, but we need
to handle things in the same way .
*/
engine_halted ( ) ;
2008-08-04 18:37:24 -04:00
}
2008-06-02 17:41:35 -04:00
}
2009-11-30 18:16:28 -05:00
void
Session : : route_processors_changed ( RouteProcessorChange c )
{
if ( c . type = = RouteProcessorChange : : MeterPointChange ) {
return ;
}
update_latency_compensation ( false , false ) ;
2010-04-06 08:13:38 -04:00
resort_routes ( ) ;
2009-11-30 18:16:28 -05:00
}
2008-06-02 17:41:35 -04:00
void
Session : : update_latency_compensation ( bool with_stop , bool abort )
{
bool update_jack = false ;
2009-11-08 11:28:21 -05:00
PostTransportWork ptw ;
2008-06-02 17:41:35 -04:00
if ( _state_of_the_state & Deletion ) {
return ;
}
_worst_track_latency = 0 ;
2009-11-08 11:28:21 -05:00
ptw = post_transport_work ( ) ;
2008-06-02 17:41:35 -04:00
2008-09-10 11:03:30 -04:00
# undef DEBUG_LATENCY
# ifdef DEBUG_LATENCY
cerr < < " \n --------------------------------- \n UPDATE LATENCY \n " ;
# endif
2008-06-02 17:41:35 -04:00
boost : : shared_ptr < RouteList > r = routes . reader ( ) ;
for ( RouteList : : iterator i = r - > begin ( ) ; i ! = r - > end ( ) ; + + i ) {
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
if ( with_stop ) {
2009-11-08 11:28:21 -05:00
( * i ) - > handle_transport_stopped ( abort , ( ptw & PostTransportLocate ) , ( ! ( ptw & PostTransportLocate ) | | pending_locate_flush ) ) ;
2008-06-02 17:41:35 -04:00
}
2008-08-04 18:37:24 -04:00
2009-06-09 16:21:19 -04:00
nframes_t old_latency = ( * i ) - > output ( ) - > signal_latency ( ) ;
2008-06-02 17:41:35 -04:00
nframes_t track_latency = ( * i ) - > update_total_latency ( ) ;
2008-08-04 18:37:24 -04:00
2008-06-02 17:41:35 -04:00
if ( old_latency ! = track_latency ) {
2009-06-09 16:21:19 -04:00
( * i ) - > input ( ) - > update_port_total_latencies ( ) ;
( * i ) - > output ( ) - > update_port_total_latencies ( ) ;
2008-06-02 17:41:35 -04:00
update_jack = true ;
}
2009-10-14 12:10:01 -04:00
if ( ! ( * i ) - > is_hidden ( ) & & ( ( * i ) - > active ( ) ) ) {
2008-06-02 17:41:35 -04:00
_worst_track_latency = max ( _worst_track_latency , track_latency ) ;
}
2008-08-04 18:37:24 -04:00
}
2008-06-02 17:41:35 -04:00
if ( update_jack ) {
_engine . update_total_latencies ( ) ;
}
2008-09-10 11:03:30 -04:00
# ifdef DEBUG_LATENCY
cerr < < " \t worst was " < < _worst_track_latency < < endl ;
# endif
2008-06-02 17:41:35 -04:00
for ( RouteList : : iterator i = r - > begin ( ) ; i ! = r - > end ( ) ; + + i ) {
( * i ) - > set_latency_delay ( _worst_track_latency ) ;
}
set_worst_io_latencies ( ) ;
/* reflect any changes in latencies into capture offsets
*/
2010-04-21 16:42:22 -04:00
boost : : shared_ptr < RouteList > rl = routes . reader ( ) ;
for ( RouteList : : iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < Track > tr = boost : : dynamic_pointer_cast < Track > ( * i ) ;
if ( tr ) {
tr - > set_capture_offset ( ) ;
}
2008-06-02 17:41:35 -04:00
}
}
void
Session : : allow_auto_play ( bool yn )
{
auto_play_legal = yn ;
}
void
Session : : reset_jack_connection ( jack_client_t * jack )
{
JACK_Slave * js ;
if ( _slave & & ( ( js = dynamic_cast < JACK_Slave * > ( _slave ) ) ! = 0 ) ) {
js - > reset_client ( jack ) ;
}
}
2009-10-30 14:14:25 -04:00
bool
Session : : maybe_stop ( nframes_t limit )
{
if ( ( _transport_speed > 0.0f & & _transport_frame > = limit ) | | ( _transport_speed < 0.0f & & _transport_frame = = 0 ) ) {
2009-10-30 17:07:29 -04:00
if ( synced_to_jack ( ) & & config . get_jack_time_master ( ) ) {
2009-10-30 14:14:25 -04:00
_engine . transport_stop ( ) ;
} else if ( ! synced_to_jack ( ) ) {
stop_transport ( ) ;
}
return true ;
}
return false ;
}
2010-07-04 21:13:36 -04:00
void
Session : : send_mmc_locate ( nframes64_t t )
{
Timecode : : Time time ;
timecode_time_subframes ( t , time ) ;
2010-07-08 18:55:20 -04:00
MIDI : : Manager : : instance ( ) - > mmc ( ) - > send ( MIDI : : MachineControlCommand ( time ) ) ;
2010-07-04 21:13:36 -04:00
}
2010-08-01 21:59:34 -04:00
/** Ask the transport to not send timecode until further notice. The suspension
* will come into effect some finite time after this call , and timecode_transmission_suspended ( )
* should be checked by the caller to find out when .
*/
void
Session : : request_suspend_timecode_transmission ( )
{
SessionEvent * ev = new SessionEvent ( SessionEvent : : SetTimecodeTransmission , SessionEvent : : Add , SessionEvent : : Immediate , 0 , 0 , false ) ;
queue_event ( ev ) ;
}
void
Session : : request_resume_timecode_transmission ( )
{
SessionEvent * ev = new SessionEvent ( SessionEvent : : SetTimecodeTransmission , SessionEvent : : Add , SessionEvent : : Immediate , 0 , 0 , true ) ;
queue_event ( ev ) ;
}
bool
Session : : timecode_transmission_suspended ( ) const
{
return g_atomic_int_get ( & _suspend_timecode_transmission ) = = 1 ;
}