1 /* 2 * Copyright (C) 2000-2015 Paul Davis <paul@linuxaudiosystems.com> 3 * Copyright (C) 2013 John Emmas <john@creativepost.co.uk> 4 * Copyright (C) 2015-2017 Robin Gareus <robin@gareus.org> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License along 17 * with this program; if not, write to the Free Software Foundation, Inc., 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 */ 20 21 #ifndef __pbd_base_ui_h__ 22 #define __pbd_base_ui_h__ 23 24 #include <string> 25 #include <stdint.h> 26 27 #include <sigc++/slot.h> 28 #include <sigc++/trackable.h> 29 30 #include <glibmm/threads.h> 31 #include <glibmm/main.h> 32 33 #include "pbd/libpbd_visibility.h" 34 #include "pbd/crossthread.h" 35 #include "pbd/event_loop.h" 36 #include "pbd/pthread_utils.h" 37 38 /** A BaseUI is an abstraction designed to be used with any "user 39 * interface" (not necessarily graphical) that needs to wait on 40 * events/requests and dispatch/process them as they arrive. 41 * 42 * This implementation starts up a thread that runs a Glib main loop 43 * to wait on events/requests etc. 44 */ 45 46 47 class LIBPBD_API BaseUI : public sigc::trackable, public PBD::EventLoop 48 { 49 public: 50 BaseUI (const std::string& name); 51 virtual ~BaseUI(); 52 base_instance()53 BaseUI* base_instance() { return base_ui_instance; } 54 main_loop()55 Glib::RefPtr<Glib::MainLoop> main_loop() const { return _main_loop; } event_loop_thread()56 Glib::Threads::Thread* event_loop_thread() const { return run_loop_thread; } caller_is_self()57 bool caller_is_self () const { return Glib::Threads::Thread::self() == run_loop_thread; } 58 ok()59 bool ok() const { return _ok; } 60 61 static RequestType new_request_type(); 62 static RequestType CallSlot; 63 static RequestType Quit; 64 set_thread_priority(int p)65 static void set_thread_priority (int p) { 66 _thread_priority = p; 67 } 68 69 /** start up a thread to run the main loop 70 */ 71 void run (); 72 73 /** stop the thread running the main loop (and block 74 * until it exits) 75 */ 76 void quit (); 77 78 protected: 79 bool _ok; 80 81 Glib::RefPtr<Glib::MainLoop> _main_loop; 82 Glib::RefPtr<Glib::MainContext> m_context; 83 Glib::Threads::Thread* run_loop_thread; 84 Glib::Threads::Mutex _run_lock; 85 Glib::Threads::Cond _running; 86 87 /* this signals _running from within the event loop, 88 from an idle callback 89 */ 90 91 bool signal_running (); 92 93 /** Derived UI objects can implement thread_init() 94 * which will be called by the event loop thread 95 * immediately before it enters the event loop. 96 */ 97 thread_init()98 virtual void thread_init () {}; 99 100 int set_thread_priority () const; 101 102 /** Called when there input ready on the request_channel 103 */ 104 bool request_handler (Glib::IOCondition); 105 106 void signal_new_request (); 107 void attach_request_source (); 108 109 /** Derived UI objects must implement this method, 110 * which will be called whenever there are requests 111 * to be dealt with. 112 */ 113 virtual void handle_ui_requests () = 0; 114 115 private: 116 BaseUI* base_ui_instance; 117 118 CrossThreadChannel request_channel; 119 120 static uint64_t rt_bit; 121 static int _thread_priority; 122 123 int setup_request_pipe (); 124 void main_thread (); 125 }; 126 127 #endif /* __pbd_base_ui_h__ */ 128