1 /*
2  * Copyright (C) 2018-2019 Paul Davis <paul@linuxaudiosystems.com>
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 along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #ifndef __ardour_transport_master_manager_h__
20 #define __ardour_transport_master_manager_h__
21 
22 #include <string>
23 
24 #include <boost/noncopyable.hpp>
25 
26 #include "ardour/transport_master.h"
27 #include "ardour/types.h"
28 
29 namespace ARDOUR {
30 
31 class UI_TransportMaster;
32 
33 class LIBARDOUR_API TransportMasterManager : public boost::noncopyable
34 {
35   public:
36 	static TransportMasterManager& create ();
37 	~TransportMasterManager ();
38 
39 	int set_default_configuration ();
40 	void restart ();
41 	void engine_stopped ();
42 
43 	static TransportMasterManager& instance();
44 	static void destroy();
45 	/* this method is not thread-safe and is intended to be used only
46 	 * very early in application-lifetime to check if the TMM has
47 	 * been created yet. Do not use in other code.
48 	 */
exists()49 	static bool exists() { return _instance != 0; }
50 
51 	typedef std::list<boost::shared_ptr<TransportMaster> > TransportMasters;
52 
53 	int add (SyncSource type, std::string const & name, bool removeable = true);
54 	int remove (std::string const & name);
55 	void clear ();
56 
57 	PBD::Signal1<void,boost::shared_ptr<TransportMaster> > Added;
58 	PBD::Signal1<void,boost::shared_ptr<TransportMaster> > Removed; // null argument means "clear"
59 
60 	double pre_process_transport_masters (pframes_t, samplepos_t session_transport_position);
61 
get_current_speed_in_process_context()62 	double get_current_speed_in_process_context() const { return _master_speed; }
get_current_position_in_process_context()63 	samplepos_t get_current_position_in_process_context() const { return _master_position; }
64 
current()65 	boost::shared_ptr<TransportMaster> current() const { return _current_master; }
66 	int set_current (boost::shared_ptr<TransportMaster>);
67 	int set_current (SyncSource);
68 	int set_current (std::string const &);
69 
70 	PBD::Signal2<void,boost::shared_ptr<TransportMaster>, boost::shared_ptr<TransportMaster> > CurrentChanged;
71 
72 	int set_state (XMLNode const &, int);
73 	XMLNode& get_state();
74 
75 	void set_session (Session*);
session()76 	Session* session() const { return _session; }
77 
master_invalid_this_cycle()78 	bool master_invalid_this_cycle() const { return _master_invalid_this_cycle; }
79 
80 	boost::shared_ptr<TransportMaster> master_by_type (SyncSource src) const;
81 	boost::shared_ptr<TransportMaster> master_by_name (std::string const &) const;
82 	boost::shared_ptr<TransportMaster> master_by_port (boost::shared_ptr<Port> const &p) const;
83 
transport_masters()84 	TransportMasters const & transport_masters() const { return _transport_masters; }
85 
86 	static const std::string state_node_name;
87 
88 	void reconnect_ports ();
89 
90 	void block_disk_output ();
91 	void unblock_disk_output ();
92 	void reinit (double speed, samplepos_t pos);
93 
94   private:
95 	TransportMasterManager();
96 
97 	TransportMasters      _transport_masters;
98 	mutable Glib::Threads::RWLock  lock;
99 	double                _master_speed;
100 	samplepos_t           _master_position;
101 
102 	boost::shared_ptr<TransportMaster> _current_master;
103 	Session* _session;
104 
105 	bool _master_invalid_this_cycle;
106 	bool disk_output_blocked;
107 
108 	/* a DLL to chase the transport master, calculate playback speed
109 	 * by matching Ardour's current playhead position against
110 	 * the position of the transport-master */
111 	double t0; // PH position at the beginning of this cycle
112 	double t1; // expected PH position if next cycle
113 	double e2; // second order loop error
114 	double bandwidth; // DLL filter bandwidth
115 	double b, c, omega; // DLL filter coefficients
116 
117 	void init_transport_master_dll (double speed, samplepos_t pos);
118 	int master_dll_initstate; // play-direction -1, +1, or 0: not initialized
119 
120 	static TransportMasterManager* _instance;
121 
122 	/* original TC format in case the slave changed it */
123 	boost::optional<Timecode::TimecodeFormat> _session_tc_format;
124 	void maybe_restore_tc_format ();
125 	void maybe_set_tc_format ();
126 
127 	int add_locked (boost::shared_ptr<TransportMaster>);
128 	double compute_matching_master_speed (pframes_t nframes, samplepos_t, bool& locate_required);
129 	int set_current_locked (boost::shared_ptr<TransportMaster>);
130 
131 	PBD::ScopedConnection config_connection;
132 	void parameter_changed (std::string const & what);
133 };
134 
135 } // namespace ARDOUR
136 
137 #endif /* __ardour_transport_master_manager_h__ */
138