1 /*
2  * Copyright (C) 2009-2011 David Robillard <d@drobilla.net>
3  * Copyright (C) 2009-2017 Paul Davis <paul@linuxaudiosystems.com>
4  * Copyright (C) 2010-2012 Carl Hetherington <carl@carlh.net>
5  * Copyright (C) 2013 John Emmas <john@creativepost.co.uk>
6  * Copyright (C) 2015-2017 Robin Gareus <robin@gareus.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22 
23 #ifndef __ardour_butler_h__
24 #define __ardour_butler_h__
25 
26 #include <pthread.h>
27 
28 #include <glibmm/threads.h>
29 
30 #include "pbd/crossthread.h"
31 #include "pbd/ringbuffer.h"
32 #include "pbd/pool.h"
33 #include "pbd/g_atomic_compat.h"
34 
35 #include "ardour/libardour_visibility.h"
36 #include "ardour/types.h"
37 #include "ardour/session_handle.h"
38 
39 namespace ARDOUR {
40 
41 /**
42  *  One of the Butler's functions is to clean up (ie delete) unused CrossThreadPools.
43  *  When a thread with a CrossThreadPool terminates, its CTP is added to pool_trash.
44  *  When the Butler thread wakes up, we check this trash buffer for CTPs, and if they
45  *  are empty they are deleted.
46  */
47 
48 class LIBARDOUR_API Butler : public SessionHandleRef
49 {
50   public:
51 	Butler (Session& session);
52 	~Butler();
53 
54 	int  start_thread();
55 	void terminate_thread();
56 	void schedule_transport_work();
57 	void summon();
58 	void stop();
59 	void wait_until_finished();
60 	bool transport_work_requested() const;
61 	void drop_references ();
62 
63         void map_parameters ();
64 
audio_capture_buffer_size()65 	samplecnt_t audio_capture_buffer_size() const { return _audio_capture_buffer_size; }
audio_playback_buffer_size()66 	samplecnt_t audio_playback_buffer_size() const { return _audio_playback_buffer_size; }
midi_buffer_size()67 	uint32_t midi_buffer_size()  const { return _midi_buffer_size; }
68 
69 	bool flush_tracks_to_disk_after_locate (boost::shared_ptr<RouteList>, uint32_t& errors);
70 
71 	static void* _thread_work(void *arg);
72 	void*         thread_work();
73 
74 	struct Request {
75 		enum Type {
76 			Run,
77 			Pause,
78 			Quit
79 		};
80 	};
81 
82 	pthread_t thread;
83 	bool      have_thread;
84 
85 	Glib::Threads::Mutex      request_lock;
86 	Glib::Threads::Cond       paused;
87 	bool                      should_run;
88 	mutable GATOMIC_QUAL gint should_do_transport_work;
89 
90 	samplecnt_t _audio_capture_buffer_size;
91 	samplecnt_t _audio_playback_buffer_size;
92 	uint32_t    _midi_buffer_size;
93 
94 	PBD::RingBuffer<CrossThreadPool*> pool_trash;
95 
96 private:
97 	void empty_pool_trash ();
98 	void config_changed (std::string);
99 
100 	bool flush_tracks_to_disk_normal (boost::shared_ptr<RouteList>, uint32_t& errors);
101 
102 	/**
103 	 * Add request to butler thread request queue
104 	 */
105 	void queue_request (Request::Type r);
106 
107 	CrossThreadChannel _xthread;
108 
109 };
110 
111 } // namespace ARDOUR
112 
113 #endif // __ardour_butler_h__
114