"finalmunge" patch from nick, plus work on editor region list and actions infrastruct...
[ardour.git] / gtk2_ardour / meter_bridge.cc
1 /*
2     Copyright (C) 2002 Paul Davis 
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     $Id$
19 */
20
21 #include <ardour/session.h>
22 #include <ardour/session_route.h>
23 #include <ardour/diskstream.h>
24 #include <ardour/audio_track.h>
25
26 #include "ardour_ui.h"
27 #include "meter_bridge.h"
28 #include "meter_bridge_strip.h"
29 #include "utils.h"
30 #include "gui_thread.h"
31
32 #include "i18n.h"
33
34 using namespace ARDOUR;
35 using namespace Gtk;
36 using namespace sigc;
37
38 #define FRAME_SHADOW_STYLE Gtk::SHADOW_IN
39 #define FRAME_NAME "BaseFrame"
40
41 MeterBridge::MeterBridge ()
42         : ArdourDialog ("meter bridge")
43 {
44         meter_base.set_name ("MeterBase");
45         meter_frame.set_shadow_type (FRAME_SHADOW_STYLE);
46         meter_frame.set_name (FRAME_NAME);
47         meter_frame.add (meter_base);
48
49         upper_metering_box.set_name ("AboveMeterZone");
50         lower_metering_box.set_name ("BelowMeterZone");
51
52         metering_vbox.set_spacing (5);
53         metering_vbox.set_border_width (10);
54         metering_vbox.pack_start (upper_metering_box, false, false);
55         metering_vbox.pack_start (meter_frame, false, false);
56         metering_vbox.pack_start (lower_metering_box, false, false);
57
58         metering_hbox.pack_start (metering_vbox, false, false);
59
60         meter_scroll_base.set_name ("MeterScrollBase");
61         meter_scroll_base.add (metering_hbox);
62
63         meter_viewport.add (meter_scroll_base);
64         meter_viewport.set_shadow_type (Gtk::SHADOW_NONE);
65
66         meter_scroller.add (meter_viewport);
67         meter_scroller.set_name ("MeterBridgeWindow");
68         meter_scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
69         meter_scroller.set_border_width (5);
70
71         add (meter_scroller);
72         add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
73         set_name ("MeterBridgeWindow");
74         set_title (_("ardour: meter bridge"));
75         set_wmclass (_("ardour_meter_bridge"), "Ardour");
76         // set_policy (false, false, false); // no user resizing of any kind
77
78         signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Gtk::Window*>(this)));
79
80         metering = false;
81
82         /* don't show: this window doesn't come up by default */
83 }
84
85 MeterBridge::~MeterBridge ()
86 {
87         stop_metering ();
88 }
89
90 void
91 MeterBridge::set_session (Session *s)
92 {
93         ArdourDialog::set_session (s);
94
95         if (session) {
96                 // XXX this stuff has to be fixed if we ever use this code again
97                 // (refs vs. ptrs)
98                 // session->foreach_route (this, &MeterBridge::add_route);
99                 session->RouteAdded.connect (mem_fun(*this, &MeterBridge::add_route));
100                 session->going_away.connect (mem_fun(*this, &MeterBridge::session_gone));
101                 start_metering ();
102         }
103 }
104
105 void
106 MeterBridge::session_gone ()
107 {
108         ENSURE_GUI_THREAD(mem_fun(*this, &MeterBridge::session_gone));
109         
110         stop_metering ();
111         hide_all ();
112
113         list<MeterBridgeStrip *>::iterator i;
114
115         for (i = meters.begin(); i != meters.end(); ++i) {
116
117                 upper_metering_box.remove ((*i)->above_box());
118                 meter_base.remove ((*i)->meter_widget());
119                 lower_metering_box.remove ((*i)->below_box());
120
121 //              delete (*i);
122         }
123
124         meters.clear ();
125
126         ArdourDialog::session_gone();
127 }       
128
129 void
130 MeterBridge::add_route (ARDOUR::Route* route)
131 {
132         ENSURE_GUI_THREAD(bind (mem_fun(*this, &MeterBridge::add_route), route));
133         
134         uint32_t n;
135         char buf[32];
136
137         if (!session || route->hidden() || dynamic_cast<AudioTrack*>(route) == 0) {
138                 return;
139         }
140
141         n = meters.size();
142         snprintf (buf, sizeof (buf), "%u", n+1);
143
144         MeterBridgeStrip *meter = new MeterBridgeStrip (session->engine(), 
145                                                         *session,
146                                                         *route,
147                                                         buf,
148                                                         session->over_length_long,
149                                                         session->over_length_short,
150                                                         200);
151         
152 #define packing_factor 30
153
154         upper_metering_box.put (meter->above_box(), n * packing_factor, 0);
155
156         meter_base.put (meter->meter_widget(), (n * packing_factor) + (meter->meter_width()/2), 0);
157         lower_metering_box.put (meter->below_box(), n * packing_factor, 0);
158
159         meter->above_box().show_all ();
160         meter->meter_widget().show ();
161         meter->below_box().show_all ();
162
163         route->GoingAway.connect (bind (mem_fun(*this, &MeterBridge::remove_route), route));
164         meters.insert (meters.begin(), meter);
165
166         set_default_size (30 + ((n+1) * packing_factor), 315);
167     
168         meter->set_meter_on(true);
169         
170         session->going_away.connect (mem_fun(*this, &MeterBridge::session_gone));
171 }
172
173 void
174 MeterBridge::remove_route (Route* route)
175 {
176         ENSURE_GUI_THREAD(bind (mem_fun(*this, &MeterBridge::remove_route), route));
177         list<MeterBridgeStrip *>::iterator i;
178
179         for (i = meters.begin(); i != meters.end(); ++i) {
180                 if (&((*i)->route()) == route) {
181                         delete *i;
182                         meters.erase (i);
183                         return;
184                 }
185         }
186 }
187
188 void
189 MeterBridge::clear_all_meters ()
190 {
191         list<MeterBridgeStrip *>::iterator i;
192
193         for (i = meters.begin(); i != meters.end(); ++i) {
194                 (*i)->clear_meter ();
195         }
196 }
197
198 void
199 MeterBridge::update ()
200 {
201         list<MeterBridgeStrip *>::iterator i;
202
203         for (i = meters.begin(); i != meters.end(); ++i) {
204                 (*i)->update ();
205         }
206 }
207
208 void
209 MeterBridge::start_metering ()
210 {
211         list<MeterBridgeStrip *>::iterator i;
212         
213         for (i = meters.begin(); i != meters.end(); ++i) {
214                 (*i)->set_meter_on (true);
215         }
216         metering_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect 
217                 (mem_fun(*this, &MeterBridge::update));
218         metering = true;
219 }
220
221 void
222 MeterBridge::stop_metering ()
223 {
224         list<MeterBridgeStrip *>::iterator i;
225         
226         for (i = meters.begin(); i != meters.end(); ++i) {
227                 (*i)->set_meter_on (false);
228         }
229         metering_connection.disconnect();
230         metering = false;
231 }
232
233 void
234 MeterBridge::toggle_metering ()
235 {
236         if (!metering) {
237                 start_metering ();
238         } else {
239                 stop_metering ();
240         }
241 }
242
243 bool
244 MeterBridge::on_map (GdkEventAny *ev)
245 {
246         start_metering ();
247         return Window::on_map (ev);
248 }
249
250 bool
251 MeterBridge::on_unmap (GdkEventAny *ev)
252 {
253         stop_metering ();
254         return Window::on_unmap (ev);
255 }
256