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