can't use xgetbv instruction with apple gcc under OS X Lion
[ardour.git] / libs / pbd / timer.cc
1 /*
2     Copyright (C) 2014 Tim Mayberry
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
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include "pbd/timer.h"
21
22 namespace PBD {
23
24 Timer::Timer (unsigned int interval,
25               const Glib::RefPtr<Glib::MainContext>& main_context)
26         : m_timeout_source(NULL)
27         , m_timeout_interval(interval)
28         , m_main_context(main_context)
29 {
30
31 }
32
33 gboolean
34 Timer::_timeout_handler (void *data)
35 {
36         Timer *const timer = static_cast<Timer*>(data);
37         return timer->timeout_handler();
38 }
39
40 unsigned int
41 Timer::get_interval () const
42 {
43         return m_timeout_interval;
44 }
45
46 void
47 Timer::set_interval (unsigned int new_interval)
48 {
49         if (new_interval == m_timeout_interval) return;
50
51         stop ();
52         m_timeout_interval = new_interval;
53         start ();
54 }
55
56 /**
57  * We don't use Glibmm::TimeoutSource::create() here as contrary
58  * to the documentation, SignalTimeout::connect and manually
59  * adding a TimeoutSource to a GMainContext are not equivalent.
60  *
61  * SignalTimeout::connect is the equivalent of g_timeout_add in
62  * terms off callback timing but TimeoutSource tries to adjust
63  * the timeout based on the time elapsed since the last timeout.
64  *
65  * On Windows with a high frequency timeout(40ms) this causes a
66  * small but noticable increase in CPU Usage.
67  */
68 void
69 Timer::start()
70 {
71         if (m_timeout_source) return;
72
73         m_timeout_source = g_timeout_source_new (m_timeout_interval);
74
75 #if 0 // support priorites?
76         if(priority != G_PRIORITY_DEFAULT)
77                 g_source_set_priority(source, priority);
78 #endif
79
80         g_source_set_callback (m_timeout_source, &Timer::_timeout_handler, this, NULL);
81
82         g_source_attach (m_timeout_source, m_main_context->gobj());
83         // GMainContext also holds a reference
84 }
85
86 void
87 Timer::stop()
88 {
89         if (m_timeout_source) {
90                 g_source_destroy (m_timeout_source);
91                 g_source_unref (m_timeout_source);
92                 m_timeout_source = NULL;
93         }
94 }
95
96 bool
97 Timer::timeout_handler()
98 {
99         return on_elapsed();
100 }
101
102 StandardTimer::StandardTimer(unsigned int interval,
103                 const Glib::RefPtr<Glib::MainContext>& main_context)
104         : Timer(interval, main_context)
105 { }
106
107 sigc::connection
108 StandardTimer::connect(const sigc::slot<void>& slot)
109 {
110         if(m_signal.size() == 0) { start(); }
111
112         return m_signal.connect(slot);
113 }
114
115 bool
116 StandardTimer::on_elapsed()
117 {
118         if(m_signal.size() == 0)
119         {
120                 stop();
121                 return false;
122         }
123
124         m_signal();
125         return true;
126 }
127
128 BlinkTimer::BlinkTimer(unsigned int interval,
129                 const Glib::RefPtr<Glib::MainContext>& main_context)
130         : Timer(interval, main_context)
131 { }
132
133 sigc::connection
134 BlinkTimer::connect(const sigc::slot<void, bool>& slot)
135 {
136         if(m_blink_signal.size() == 0) { start(); }
137
138         return m_blink_signal.connect(slot);
139 }
140
141 bool
142 BlinkTimer::on_elapsed()
143 {
144         static bool blink_on = false;
145
146         if(m_blink_signal.size() == 0)
147         {
148                 stop();
149                 return false;
150         }
151
152         m_blink_signal(blink_on = !blink_on);
153         return true;
154 }
155
156 } // namespace PBD