2012-07-13 17:13:35 -04:00
/*
Copyright ( C ) 2012 Paul Davis
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 <iostream>
# include "pbd/compose.h"
# include "ardour/automation_control.h"
# include "ardour/automation_watch.h"
# include "ardour/debug.h"
# include "ardour/session.h"
using namespace ARDOUR ;
using namespace PBD ;
AutomationWatch * AutomationWatch : : _instance = 0 ;
AutomationWatch &
AutomationWatch : : instance ( )
{
if ( _instance = = 0 ) {
_instance = new AutomationWatch ;
}
return * _instance ;
}
AutomationWatch : : AutomationWatch ( )
: _thread ( 0 )
, _run_thread ( false )
{
}
AutomationWatch : : ~ AutomationWatch ( )
{
if ( _thread ) {
_run_thread = false ;
_thread - > join ( ) ;
_thread = 0 ;
}
2012-07-25 13:48:55 -04:00
Glib : : Threads : : Mutex : : Lock lm ( automation_watch_lock ) ;
2012-07-13 17:13:35 -04:00
automation_watches . clear ( ) ;
}
void
AutomationWatch : : add_automation_watch ( boost : : shared_ptr < AutomationControl > ac )
{
2012-07-25 13:48:55 -04:00
Glib : : Threads : : Mutex : : Lock lm ( automation_watch_lock ) ;
2012-11-14 10:06:41 -05:00
DEBUG_TRACE ( DEBUG : : Automation , string_compose ( " now watching control %1 for automation, astate = %2 \n " , ac - > name ( ) , enum_2_string ( ac - > automation_state ( ) ) ) ) ;
automation_watches . insert ( ac ) ;
2012-07-13 17:13:35 -04:00
2012-07-16 23:10:40 -04:00
/* if an automation control is added here while the transport is
* rolling , make sure that it knows that there is a write pass going
* on , rather than waiting for the transport to start .
*/
if ( _session & & _session - > transport_rolling ( ) & & ac - > alist ( ) - > automation_write ( ) ) {
2013-04-02 16:10:51 -04:00
DEBUG_TRACE ( DEBUG : : Automation , string_compose ( " \t transport is rolling @ %1, audible = %2so enter write pass \n " ,
_session - > transport_speed ( ) , _session - > audible_frame ( ) ) ) ;
/* add a guard point since we are already moving */
ac - > list ( ) - > set_in_write_pass ( true , true , _session - > audible_frame ( ) ) ;
2012-07-16 23:10:40 -04:00
}
2012-07-13 17:13:35 -04:00
/* we can't store shared_ptr<Destructible> in connections because it
* creates reference cycles . we don ' t need to make the weak_ptr < >
* explicit here , but it helps to remind us what is going on .
*/
boost : : weak_ptr < AutomationControl > wac ( ac ) ;
ac - > DropReferences . connect_same_thread ( * this , boost : : bind ( & AutomationWatch : : remove_weak_automation_watch , this , wac ) ) ;
}
void
AutomationWatch : : remove_weak_automation_watch ( boost : : weak_ptr < AutomationControl > wac )
{
boost : : shared_ptr < AutomationControl > ac = wac . lock ( ) ;
if ( ! ac ) {
return ;
}
remove_automation_watch ( ac ) ;
}
void
AutomationWatch : : remove_automation_watch ( boost : : shared_ptr < AutomationControl > ac )
{
2012-07-25 13:48:55 -04:00
Glib : : Threads : : Mutex : : Lock lm ( automation_watch_lock ) ;
2012-07-13 17:13:35 -04:00
DEBUG_TRACE ( DEBUG : : Automation , string_compose ( " remove control %1 from automation watch \n " , ac - > name ( ) ) ) ;
2012-11-14 10:06:41 -05:00
automation_watches . erase ( ac ) ;
2012-07-16 23:10:40 -04:00
ac - > list ( ) - > set_in_write_pass ( false ) ;
2012-07-13 17:13:35 -04:00
}
gint
AutomationWatch : : timer ( )
{
if ( ! _session | | ! _session - > transport_rolling ( ) ) {
return TRUE ;
}
{
2012-07-25 13:48:55 -04:00
Glib : : Threads : : Mutex : : Lock lm ( automation_watch_lock ) ;
2012-11-14 10:06:41 -05:00
2012-07-13 17:13:35 -04:00
framepos_t time = _session - > audible_frame ( ) ;
for ( AutomationWatches : : iterator aw = automation_watches . begin ( ) ; aw ! = automation_watches . end ( ) ; + + aw ) {
2012-07-16 23:10:40 -04:00
if ( ( * aw ) - > alist ( ) - > automation_write ( ) ) {
( * aw ) - > list ( ) - > add ( time , ( * aw ) - > user_double ( ) ) ;
}
2012-07-13 17:13:35 -04:00
}
}
return TRUE ;
}
void
AutomationWatch : : thread ( )
{
while ( _run_thread ) {
2012-11-19 16:31:44 -05:00
usleep ( ( useconds_t ) floor ( Config - > get_automation_interval_msecs ( ) * 1000 ) ) ;
2012-07-13 17:13:35 -04:00
timer ( ) ;
}
}
void
AutomationWatch : : set_session ( Session * s )
{
2012-07-16 23:10:40 -04:00
transport_connection . disconnect ( ) ;
2012-07-13 17:13:35 -04:00
if ( _thread ) {
_run_thread = false ;
_thread - > join ( ) ;
_thread = 0 ;
}
SessionHandlePtr : : set_session ( s ) ;
if ( _session ) {
_run_thread = true ;
2012-07-25 13:48:55 -04:00
_thread = Glib : : Threads : : Thread : : create ( boost : : bind ( & AutomationWatch : : thread , this ) ) ;
2012-07-13 17:13:35 -04:00
2012-07-16 23:10:40 -04:00
_session - > TransportStateChange . connect_same_thread ( transport_connection , boost : : bind ( & AutomationWatch : : transport_state_change , this ) ) ;
}
}
void
AutomationWatch : : transport_state_change ( )
{
if ( ! _session ) {
return ;
}
bool rolling = _session - > transport_rolling ( ) ;
{
2012-07-25 13:48:55 -04:00
Glib : : Threads : : Mutex : : Lock lm ( automation_watch_lock ) ;
2012-07-16 23:10:40 -04:00
for ( AutomationWatches : : iterator aw = automation_watches . begin ( ) ; aw ! = automation_watches . end ( ) ; + + aw ) {
DEBUG_TRACE ( DEBUG : : Automation , string_compose ( " %1: transport state changed, speed %2, in write pass ? %3 writing ? %4 \n " ,
( * aw ) - > name ( ) , _session - > transport_speed ( ) , rolling ,
( * aw ) - > alist ( ) - > automation_write ( ) ) ) ;
if ( rolling & & ( * aw ) - > alist ( ) - > automation_write ( ) ) {
( * aw ) - > list ( ) - > set_in_write_pass ( true ) ;
} else {
( * aw ) - > list ( ) - > set_in_write_pass ( false ) ;
}
}
2012-07-13 17:13:35 -04:00
}
}