Restore old behaviour when updating the view when the playhead goes off it during...
[ardour.git] / gtk2_ardour / editor_mixer.cc
1 /*
2     Copyright (C) 2003-2004 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 */
19
20 #include <glibmm/miscutils.h>
21 #include <gtkmm2ext/utils.h>
22 #include <gtkmm2ext/window_title.h>
23
24 #include "pbd/enumwriter.h"
25
26 #include "ardour/audioengine.h"
27 #include "ardour/session.h"
28
29 #include "editor.h"
30 #include "mixer_strip.h"
31 #include "ardour_ui.h"
32 #include "selection.h"
33 #include "audio_time_axis.h"
34 #include "actions.h"
35 #include "editor_routes.h"
36 #include "editor_route_groups.h"
37 #include "editor_regions.h"
38 #include "gui_thread.h"
39 #include "editor_drag.h"
40
41 #include "i18n.h"
42
43 using namespace std;
44 using namespace Gtkmm2ext;
45 using namespace PBD;
46
47 void
48 Editor::editor_mixer_button_toggled ()
49 {
50         Glib::RefPtr<Gtk::Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
51         if (act) {
52                 Glib::RefPtr<Gtk::ToggleAction> tact = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(act);
53                 show_editor_mixer (tact->get_active());
54         }
55 }
56
57 void
58 Editor::editor_list_button_toggled ()
59 {
60         Glib::RefPtr<Gtk::Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
61         if (act) {
62                 Glib::RefPtr<Gtk::ToggleAction> tact = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(act);
63                 show_editor_list (tact->get_active());
64         }
65 }
66
67 void
68 Editor::show_editor_mixer (bool yn)
69 {
70         boost::shared_ptr<ARDOUR::Route> r;
71
72         show_editor_mixer_when_tracks_arrive = false;
73
74         if (!_session) {
75                 show_editor_mixer_when_tracks_arrive = yn;
76                 return;
77         }
78
79         if (yn) {
80
81                 if (selection->tracks.empty()) {
82
83                         if (track_views.empty()) {
84                                 show_editor_mixer_when_tracks_arrive = true;
85                                 return;
86                         }
87
88                         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
89                                 RouteTimeAxisView* atv;
90
91                                 if ((atv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
92                                         r = atv->route();
93                                         break;
94                                 }
95                         }
96
97                 } else {
98                         sort_track_selection ();
99
100                         for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
101                                 RouteTimeAxisView* atv;
102
103                                 if ((atv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
104                                         r = atv->route();
105                                         break;
106                                 }
107                         }
108                 }
109
110                 if (r) {
111                         if (current_mixer_strip == 0) {
112                                 create_editor_mixer ();
113                         }
114
115                         current_mixer_strip->set_route (r);
116                         current_mixer_strip->set_width_enum (editor_mixer_strip_width, (void*) this);
117                 }
118
119                 if (current_mixer_strip->get_parent() == 0) {
120                         global_hpacker.pack_start (*current_mixer_strip, Gtk::PACK_SHRINK );
121                         global_hpacker.reorder_child (*current_mixer_strip, 0);
122                         current_mixer_strip->show_all ();
123                 }
124
125         } else {
126
127                 if (current_mixer_strip) {
128                         if (current_mixer_strip->get_parent() != 0) {
129                                 global_hpacker.remove (*current_mixer_strip);
130                         }
131                 }
132         }
133
134 #ifdef GTKOSX
135         /* XXX gtk problem here */
136         ensure_all_elements_drawn();
137 #endif
138 }
139
140 #ifdef GTKOSX
141 void
142 Editor::ensure_all_elements_drawn ()
143 {
144         controls_layout.queue_draw ();
145         ruler_label_event_box.queue_draw ();
146         time_button_event_box.queue_draw ();
147 }
148 #endif
149
150 void
151 Editor::show_editor_list (bool yn)
152 {
153         if (yn) {
154                 the_notebook.show();
155         } else {
156                 the_notebook.hide();
157         }
158 }
159
160 void
161 Editor::create_editor_mixer ()
162 {
163         current_mixer_strip = new MixerStrip (*ARDOUR_UI::instance()->the_mixer(),
164                                               _session,
165                                               false);
166         current_mixer_strip->Hiding.connect (sigc::mem_fun(*this, &Editor::current_mixer_strip_hidden));
167
168 #ifdef GTKOSX
169         current_mixer_strip->WidthChanged.connect (sigc::mem_fun(*this, &Editor::ensure_all_elements_drawn));
170 #endif
171         current_mixer_strip->set_embedded (true);
172 }
173
174 void
175 Editor::set_selected_mixer_strip (TimeAxisView& view)
176 {
177         RouteTimeAxisView* at;
178
179         if (!_session || (at = dynamic_cast<RouteTimeAxisView*>(&view)) == 0) {
180                 return;
181         }
182
183         Glib::RefPtr<Gtk::Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
184
185         if (act) {
186                 Glib::RefPtr<Gtk::ToggleAction> tact = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(act);
187                 if (!tact || !tact->get_active()) {
188                         /* not showing mixer strip presently */
189                         return;
190                 }
191         }
192
193         if (current_mixer_strip == 0) {
194                 create_editor_mixer ();
195         }
196
197         /* might be nothing to do */
198
199         if (current_mixer_strip->route() == at->route()) {
200                 return;
201         }
202
203         current_mixer_strip->set_route (at->route());
204         current_mixer_strip->set_width_enum (editor_mixer_strip_width, (void*) this);
205 }
206
207 double current = 0.0;
208
209 void
210 Editor::update_current_screen ()
211 {
212         if (_pending_locate_request) {
213                 /* we don't update things when there's a pending locate request, otherwise
214                    when the editor requests a locate there is a chance that this method
215                    will move the playhead before the locate request is processed, causing
216                    a visual glitch. */
217                 return;
218         }
219
220         if (_session && _session->engine().running()) {
221
222                 nframes64_t const frame = _session->audible_frame();
223
224                 if (_dragging_playhead) {
225                         goto almost_done;
226                 }
227
228                 /* only update if the playhead is on screen or we are following it */
229
230                 if (_follow_playhead && _session->requested_return_frame() < 0) {
231
232                         //playhead_cursor->canvas_item.show();
233
234                         if (frame != last_update_frame) {
235
236
237 #undef CONTINUOUS_SCROLL
238 #ifndef  CONTINUOUS_SCROLL
239                                 if (frame < leftmost_frame || frame > leftmost_frame + current_page_frames()) {
240
241                                         if (_session->transport_speed() < 0) {
242                                                 if (frame > (current_page_frames()/2)) {
243                                                         center_screen (frame-(current_page_frames()/2));
244                                                 } else {
245                                                         center_screen (current_page_frames()/2);
246                                                 }
247                                                 
248                                         } else {
249
250                                                 if (frame < leftmost_frame) {
251                                                         /* moving left */
252                                                         nframes64_t l = 0;
253                                                         if (_session->transport_rolling()) {
254                                                                 /* rolling; end up with the playhead at the right of the page */
255                                                                 l = frame - current_page_frames ();
256                                                         } else {
257                                                                 /* not rolling: end up with the playhead 3/4 of the way along the page */
258                                                                 l = frame - (3 * current_page_frames() / 4);
259                                                         }
260                                                         
261                                                         if (l < 0) {
262                                                                 l = 0;
263                                                         }
264                                                         
265                                                         center_screen_internal (l + (current_page_frames() / 2), current_page_frames ());
266                                                 } else {
267                                                         /* moving right */
268                                                         if (_session->transport_rolling()) {
269                                                                 /* rolling: end up with the playhead on the left of the page */
270                                                                 center_screen_internal (frame + (current_page_frames() / 2), current_page_frames ());
271                                                         } else {
272                                                                 /* not rolling: end up with the playhead 1/4 of the way along the page */
273                                                                 center_screen_internal (frame + (current_page_frames() / 4), current_page_frames ());
274                                                         }
275                                                 }
276                                         }
277                                 }
278
279                                 playhead_cursor->set_position (frame);
280
281 #else  // CONTINUOUS_SCROLL
282
283                                 /* don't do continuous scroll till the new position is in the rightmost quarter of the
284                                    editor canvas
285                                 */
286
287                                 if (_session->transport_speed()) {
288                                         double target = ((double)frame - (double)current_page_frames()/2.0) / frames_per_unit;
289                                         if (target <= 0.0) target = 0.0;
290                                         if ( fabs(target - current) < current_page_frames()/frames_per_unit ) {
291                                                 target = (target * 0.15) + (current * 0.85);
292                                         } else {
293                                                 /* relax */
294                                         }
295                                         //printf("frame: %d,  cpf: %d,  fpu: %6.6f, current: %6.6f, target : %6.6f\n", frame, current_page_frames(), frames_per_unit, current, target );
296                                         current = target;
297                                         horizontal_adjustment.set_value ( current );
298                                 }
299
300                                 playhead_cursor->set_position (frame);
301
302 #endif // CONTINUOUS_SCROLL
303
304                         }
305
306                 } else {
307                         if (frame != last_update_frame) {
308                                 playhead_cursor->set_position (frame);
309                         }
310                 }
311
312           almost_done:
313                 last_update_frame = frame;
314                 if (current_mixer_strip) {
315                         current_mixer_strip->fast_update ();
316                 }
317
318         }
319 }
320
321 void
322 Editor::current_mixer_strip_hidden ()
323 {
324         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
325
326                 RouteTimeAxisView* tmp;
327
328                 if ((tmp = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
329                         if (tmp->route() == current_mixer_strip->route()) {
330                                 (*i)->set_selected (false);
331                                 break;
332                         }
333                 }
334         }
335
336         Glib::RefPtr<Gtk::Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
337         if (act) {
338                 Glib::RefPtr<Gtk::ToggleAction> tact = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic(act);
339                 tact->set_active (false);
340         }
341 }
342
343 void
344 Editor::session_going_away ()
345 {
346         _have_idled = false;
347
348         _session_connections.drop_connections ();
349
350         stop_scrolling ();
351         selection->clear ();
352         cut_buffer->clear ();
353
354         clicked_regionview = 0;
355         clicked_axisview = 0;
356         clicked_routeview = 0;
357         clicked_crossfadeview = 0;
358         entered_regionview = 0;
359         entered_track = 0;
360         last_update_frame = 0;
361         _drags->abort ();
362
363         playhead_cursor->canvas_item.hide ();
364
365         /* rip everything out of the list displays */
366
367         _regions->clear ();
368         _routes->clear ();
369         _route_groups->clear ();
370
371         /* do this first so that deleting a track doesn't reset cms to null
372            and thus cause a leak.
373         */
374
375         if (current_mixer_strip) {
376                 if (current_mixer_strip->get_parent() != 0) {
377                         global_hpacker.remove (*current_mixer_strip);
378                 }
379                 delete current_mixer_strip;
380                 current_mixer_strip = 0;
381         }
382
383         /* delete all trackviews */
384
385         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
386                 delete *i;
387         }
388         track_views.clear ();
389
390         zoom_range_clock.set_session (0);
391         nudge_clock.set_session (0);
392
393         editor_list_button.set_active(false);
394         editor_list_button.set_sensitive(false);
395
396         /* clear tempo/meter rulers */
397         remove_metric_marks ();
398         hide_measures ();
399         clear_marker_display ();
400
401         delete current_bbt_points;
402         current_bbt_points = 0;
403
404         /* get rid of any existing editor mixer strip */
405
406         WindowTitle title(Glib::get_application_name());
407         title += _("Editor");
408
409         set_title (title.get_string());
410
411         SessionHandlePtr::session_going_away ();
412 }
413
414 void
415 Editor::maybe_add_mixer_strip_width (XMLNode& node)
416 {
417         if (current_mixer_strip) {
418                 node.add_property ("mixer-width", enum_2_string (current_mixer_strip->get_width_enum()));
419         }
420 }
421