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