Returns (i.e. sidechains).
[ardour.git] / gtk2_ardour / route_params_ui.cc
1 /*
2     Copyright (C) 2000 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 <algorithm>
21 #define __STDC_FORMAT_MACROS
22 #include <inttypes.h>
23
24 #include <glibmm/thread.h>
25 #include <gtkmm2ext/utils.h>
26 #include <gtkmm2ext/stop_signal.h>
27 #include <gtkmm2ext/window_title.h>
28
29 #include "ardour/ardour.h"
30 #include "ardour/audio_diskstream.h"
31 #include "ardour/audio_track.h"
32 #include "ardour/plugin.h"
33 #include "ardour/plugin_insert.h"
34 #include "ardour/plugin_manager.h"
35 #include "ardour/port_insert.h"
36 #include "ardour/return.h"
37 #include "ardour/route.h"
38 #include "ardour/send.h"
39 #include "ardour/session.h"
40 #include "ardour/session.h"
41 #include "ardour/session_route.h"
42
43 #include "ardour_ui.h"
44 #include "gui_thread.h"
45 #include "io_selector.h"
46 #include "keyboard.h"
47 #include "mixer_strip.h"
48 #include "plugin_selector.h"
49 #include "plugin_ui.h"
50 #include "return_ui.h"
51 #include "route_params_ui.h"
52 #include "send_ui.h"
53 #include "utils.h"
54
55 #include "i18n.h"
56
57 using namespace ARDOUR;
58 using namespace PBD;
59 using namespace Gtk;
60 using namespace Gtkmm2ext;
61 using namespace sigc;
62
63 RouteParams_UI::RouteParams_UI ()
64         : ArdourDialog ("track/bus inspector"),
65           latency_apply_button (Stock::APPLY),
66           track_menu(0)
67         
68 {
69         pre_insert_box = 0;
70         post_insert_box = 0;
71         _input_iosel = 0;
72         _output_iosel = 0;
73         _active_pre_view = 0;
74         _active_post_view = 0;
75         latency_widget = 0;
76
77         using namespace Notebook_Helpers;
78
79         input_frame.set_shadow_type(Gtk::SHADOW_NONE);
80         output_frame.set_shadow_type(Gtk::SHADOW_NONE);
81         latency_frame.set_shadow_type (Gtk::SHADOW_NONE);
82
83         notebook.set_show_tabs (true);
84         notebook.set_show_border (true);
85         notebook.set_name ("RouteParamNotebook");
86
87         // create the tree model
88         route_display_model = ListStore::create(route_display_columns);
89
90         // setup the treeview
91         route_display.set_model(route_display_model);
92         route_display.append_column(_("Tracks/Busses"), route_display_columns.text);
93         route_display.set_name(X_("RouteParamsListDisplay"));
94         route_display.get_selection()->set_mode(Gtk::SELECTION_SINGLE); // default
95         route_display.set_reorderable(false);
96         route_display.set_size_request(75, -1);
97         route_display.set_headers_visible(true);
98         route_display.set_headers_clickable(true);
99
100         route_select_scroller.add(route_display);
101         route_select_scroller.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
102
103         route_select_frame.set_name("RouteSelectBaseFrame");
104         route_select_frame.set_shadow_type (Gtk::SHADOW_IN);
105         route_select_frame.add(route_select_scroller);
106
107         list_vpacker.pack_start (route_select_frame, true, true);
108         
109         notebook.pages().push_back (TabElem (input_frame, _("Inputs")));
110         notebook.pages().push_back (TabElem (output_frame, _("Outputs")));
111         notebook.pages().push_back (TabElem (pre_redir_hpane, _("Pre-fader Redirects")));
112         notebook.pages().push_back (TabElem (post_redir_hpane, _("Post-fader Redirects")));
113         notebook.pages().push_back (TabElem (latency_frame, _("Latency")));
114
115         notebook.set_name ("InspectorNotebook");
116         
117         title_label.set_name ("RouteParamsTitleLabel");
118         update_title();
119         
120         latency_packer.set_spacing (18);
121         latency_button_box.pack_start (latency_apply_button);
122         delay_label.set_alignment (0, 0.5);
123
124         // changeable area
125         route_param_frame.set_name("RouteParamsBaseFrame");
126         route_param_frame.set_shadow_type (Gtk::SHADOW_IN);
127         
128         
129         route_hpacker.pack_start (notebook, true, true);
130         
131         route_vpacker.pack_start (title_label, false, false);
132         route_vpacker.pack_start (route_hpacker, true, true);
133
134         
135         list_hpane.pack1 (list_vpacker);
136         list_hpane.add2 (route_vpacker);
137
138         list_hpane.set_position(110);
139
140         pre_redir_hpane.set_position(110);
141         post_redir_hpane.set_position(110);
142         
143         //global_vpacker.pack_start (list_hpane, true, true);
144         //get_vbox()->pack_start (global_vpacker);
145         get_vbox()->pack_start (list_hpane);
146         
147         
148         set_name ("RouteParamsWindow");
149         set_default_size (620,370);
150         set_wmclass (X_("ardour_route_parameters"), "Ardour");
151
152         WindowTitle title(Glib::get_application_name());
153         title += _("Track/Bus Inspector"); 
154         set_title (title.get_string());
155
156
157         // events
158         route_display.get_selection()->signal_changed().connect(mem_fun(*this, &RouteParams_UI::route_selected));
159         route_display.get_column(0)->signal_clicked().connect(mem_fun(*this, &RouteParams_UI::show_track_menu));
160
161         add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::BUTTON_RELEASE_MASK);
162         
163         _plugin_selector = new PluginSelector (PluginManager::the_manager());
164         _plugin_selector->signal_delete_event().connect (bind (ptr_fun (just_hide_it), 
165                                                      static_cast<Window *> (_plugin_selector)));
166
167
168         signal_delete_event().connect(bind(ptr_fun(just_hide_it), static_cast<Gtk::Window *>(this)));
169 }
170
171 RouteParams_UI::~RouteParams_UI ()
172 {
173 }
174
175 void
176 RouteParams_UI::add_routes (RouteList& routes)
177 {
178         ENSURE_GUI_THREAD(bind (mem_fun(*this, &RouteParams_UI::add_routes), routes));
179         
180         for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
181                 boost::shared_ptr<Route> route = (*x);
182
183                 if (route->is_hidden()) {
184                         return;
185                 }
186                 
187                 TreeModel::Row row = *(route_display_model->append());
188                 row[route_display_columns.text] = route->name();
189                 row[route_display_columns.route] = route;
190                 
191                 //route_select_list.rows().back().select ();
192                 
193                 route->NameChanged.connect (bind (mem_fun(*this, &RouteParams_UI::route_name_changed), route));
194                 route->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::route_removed), route));
195         }
196 }
197
198
199 void
200 RouteParams_UI::route_name_changed (boost::shared_ptr<Route> route)
201 {
202         ENSURE_GUI_THREAD(bind (mem_fun(*this, &RouteParams_UI::route_name_changed), route));
203
204         bool found = false ;
205         TreeModel::Children rows = route_display_model->children();
206         for(TreeModel::Children::iterator iter = rows.begin(); iter != rows.end(); ++iter) {
207                 boost::shared_ptr<Route> r =(*iter)[route_display_columns.route];
208                 if (r == route) {
209                         (*iter)[route_display_columns.text] = route->name() ;
210                         found = true ;
211                         break;
212                 }
213         }
214
215         if(!found) {
216                 error << _("route display list item for renamed route not found!") << endmsg;
217         }
218
219         if (route == _route) {
220                 track_input_label.set_text (route->name());
221                 update_title();
222         }
223 }
224
225 void
226 RouteParams_UI::setup_processor_boxes()
227 {
228         if (session && _route) {
229
230                 // just in case... shouldn't need this
231                 cleanup_processor_boxes();
232                 
233                 // construct new redirect boxes
234                 pre_insert_box = new ProcessorBox(PreFader, *session, *_plugin_selector, _rr_selection);
235                 post_insert_box = new ProcessorBox(PostFader, *session, *_plugin_selector, _rr_selection);
236   
237                 pre_insert_box->set_route (_route);
238                 post_insert_box->set_route (_route);
239
240                 pre_redir_hpane.pack1 (*pre_insert_box);
241                 post_redir_hpane.pack1 (*post_insert_box);
242
243                 pre_insert_box->ProcessorSelected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PreFader));
244                 pre_insert_box->ProcessorUnselected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PreFader));
245                 post_insert_box->ProcessorSelected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PostFader));
246                 post_insert_box->ProcessorUnselected.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_selected), PostFader));
247
248                 pre_redir_hpane.show_all();
249                 post_redir_hpane.show_all();
250         }
251         
252 }
253
254 void
255 RouteParams_UI::cleanup_processor_boxes()
256 {
257         if (pre_insert_box) {
258                 pre_redir_hpane.remove(*pre_insert_box);
259                 delete pre_insert_box;
260                 pre_insert_box = 0;
261         }
262
263         if (post_insert_box) {
264                 post_redir_hpane.remove(*post_insert_box);
265                 delete post_insert_box;
266                 post_insert_box = 0;
267         }
268 }
269
270 void
271 RouteParams_UI::refresh_latency ()
272 {
273         if (latency_widget) {
274                 latency_widget->refresh();
275
276                 char buf[128];
277                 snprintf (buf, sizeof (buf), _("Playback delay: %u samples"), _route->initial_delay());
278                 delay_label.set_text (buf);
279         }
280 }
281
282 void
283 RouteParams_UI::cleanup_latency_frame ()
284 {
285         if (latency_widget) {
286                 latency_frame.remove ();
287                 latency_packer.remove (*latency_widget);
288                 latency_packer.remove (latency_button_box);
289                 latency_packer.remove (delay_label);
290                 delete latency_widget;
291                 latency_widget = 0;
292                 latency_conn.disconnect ();
293                 delay_conn.disconnect ();
294                 latency_apply_conn.disconnect ();
295         }
296 }
297
298 void
299 RouteParams_UI::setup_latency_frame ()
300 {
301         latency_widget = new LatencyGUI (*(_route.get()), session->frame_rate(), session->engine().frames_per_cycle());
302
303         char buf[128];
304         snprintf (buf, sizeof (buf), _("Playback delay: %u samples"), _route->initial_delay());
305         delay_label.set_text (buf);
306
307         latency_packer.pack_start (*latency_widget, false, false);
308         latency_packer.pack_start (latency_button_box, false, false);
309         latency_packer.pack_start (delay_label);
310
311         latency_apply_conn = latency_apply_button.signal_clicked().connect (mem_fun (*latency_widget, &LatencyGUI::finish));
312         latency_conn = _route->signal_latency_changed.connect (mem_fun (*this, &RouteParams_UI::refresh_latency));
313         delay_conn = _route->initial_delay_changed.connect (mem_fun (*this, &RouteParams_UI::refresh_latency));
314         
315         latency_frame.add (latency_packer);
316         latency_frame.show_all ();
317 }
318
319 void
320 RouteParams_UI::setup_io_frames()
321 {
322         cleanup_io_frames();
323         
324         // input
325         _input_iosel = new IOSelector (*session, _route, false);
326         _input_iosel->setup ();
327         input_frame.add (*_input_iosel);
328         input_frame.show_all();
329         
330         // output
331         _output_iosel = new IOSelector (*session, _route, true);
332         _output_iosel->setup ();
333         output_frame.add (*_output_iosel);
334         output_frame.show_all();
335 }
336
337 void
338 RouteParams_UI::cleanup_io_frames()
339 {
340         if (_input_iosel) {
341                 _input_iosel->Finished (IOSelector::Cancelled);
342                 input_frame.remove();
343                 delete _input_iosel;
344                 _input_iosel = 0;
345         }
346
347         if (_output_iosel) {
348                 _output_iosel->Finished (IOSelector::Cancelled);
349
350                 output_frame.remove();
351                 delete _output_iosel;
352                 _output_iosel = 0;
353         }
354 }
355
356 void
357 RouteParams_UI::cleanup_pre_view (bool stopupdate)
358 {
359         if (_active_pre_view) {
360                 GenericPluginUI *   plugui = 0;
361                 
362                 if (stopupdate && (plugui = dynamic_cast<GenericPluginUI*>(_active_pre_view)) != 0) {
363                           plugui->stop_updating (0);
364                 }
365
366                 _pre_plugin_conn.disconnect();
367                 pre_redir_hpane.remove(*_active_pre_view);
368                 delete _active_pre_view;
369                 _active_pre_view = 0;
370         }
371 }
372
373 void
374 RouteParams_UI::cleanup_post_view (bool stopupdate)
375 {
376         if (_active_post_view) {
377                 GenericPluginUI *   plugui = 0;
378                 
379                 if (stopupdate && (plugui = dynamic_cast<GenericPluginUI*>(_active_post_view)) != 0) {
380                           plugui->stop_updating (0);
381                 }
382                 _post_plugin_conn.disconnect();
383                 post_redir_hpane.remove(*_active_post_view);
384                 delete _active_post_view;
385                 _active_post_view = 0;
386         }
387 }
388
389
390 void
391 RouteParams_UI::route_removed (boost::shared_ptr<Route> route)
392 {
393         ENSURE_GUI_THREAD(bind (mem_fun(*this, &RouteParams_UI::route_removed), route));
394
395         TreeModel::Children rows = route_display_model->children();
396         TreeModel::Children::iterator ri;
397
398         for(TreeModel::Children::iterator iter = rows.begin(); iter != rows.end(); ++iter) {
399                 boost::shared_ptr<Route> r =(*iter)[route_display_columns.route];
400
401                 if (r == route) {
402                         route_display_model->erase(iter);
403                         break;
404                 }
405         }
406
407         if (route == _route) {
408                 cleanup_io_frames();
409                 cleanup_pre_view();
410                 cleanup_post_view();
411                 cleanup_processor_boxes();
412                 
413                 _route.reset ((Route*) 0);
414                 _pre_processor.reset ((Processor*) 0);
415                 _post_processor.reset ((Processor*) 0);
416                 update_title();
417         }
418 }
419
420 void
421 RouteParams_UI::set_session (Session *sess)
422 {
423         ArdourDialog::set_session (sess);
424
425         route_display_model->clear();
426
427         if (session) {
428                 boost::shared_ptr<RouteList> r = session->get_routes();
429                 add_routes (*r);
430                 session->GoingAway.connect (mem_fun(*this, &ArdourDialog::session_gone));
431                 session->RouteAdded.connect (mem_fun(*this, &RouteParams_UI::add_routes));
432                 start_updating ();
433         } else {
434                 stop_updating ();
435         }
436
437         //route_select_list.thaw ();
438
439         _plugin_selector->set_session (session);
440 }       
441
442
443 void
444 RouteParams_UI::session_gone ()
445 {
446         ENSURE_GUI_THREAD(mem_fun(*this, &RouteParams_UI::session_gone));
447
448         route_display_model->clear();
449
450         cleanup_io_frames();
451         cleanup_pre_view();
452         cleanup_post_view();
453         cleanup_processor_boxes();
454         cleanup_latency_frame ();
455
456         _route.reset ((Route*) 0);
457         _pre_processor.reset ((Processor*) 0);
458         _post_processor.reset ((Processor*) 0);
459         update_title();
460
461         ArdourDialog::session_gone();
462
463 }
464
465 void
466 RouteParams_UI::route_selected()
467 {
468         Glib::RefPtr<TreeSelection> selection = route_display.get_selection();
469         TreeModel::iterator iter = selection->get_selected(); // only used with Gtk::SELECTION_SINGLE
470
471         if(iter) {
472                 //If anything is selected
473                 boost::shared_ptr<Route> route = (*iter)[route_display_columns.route] ;
474
475                 if (_route == route) {
476                         // do nothing
477                         return;
478                 }
479
480                 // remove event binding from previously selected
481                 if (_route) {
482                         _route_conn.disconnect();
483                         _route_ds_conn.disconnect();
484                         cleanup_processor_boxes();
485                         cleanup_pre_view();
486                         cleanup_post_view();
487                         cleanup_io_frames();
488                         cleanup_latency_frame ();
489                 }
490
491                 // update the other panes with the correct info
492                 _route = route;
493                 //update_routeinfo (route);
494
495                 setup_io_frames();
496                 setup_processor_boxes();
497                 setup_latency_frame ();
498
499                 // bind to redirects changed event for this route
500                 _route_conn = route->processors_changed.connect (mem_fun(*this, &RouteParams_UI::processors_changed));
501
502                 track_input_label.set_text (_route->name());
503
504                 update_title();
505
506         } else {
507                 // no selection
508                 if (_route) {
509                         _route_conn.disconnect();
510
511                         // remove from view
512                         cleanup_io_frames();
513                         cleanup_pre_view();
514                         cleanup_post_view();
515                         cleanup_processor_boxes();
516                         cleanup_latency_frame ();
517
518                         _route.reset ((Route*) 0);
519                         _pre_processor.reset ((Processor*) 0);
520                         _post_processor.reset ((Processor *) 0);
521                         track_input_label.set_text(_("NO TRACK"));
522                         update_title();
523                 }
524         }
525 }
526
527 void
528 RouteParams_UI::processors_changed ()
529 {
530         ENSURE_GUI_THREAD(mem_fun(*this, &RouteParams_UI::processors_changed));
531         cleanup_pre_view();
532         cleanup_post_view();
533         
534         _pre_processor.reset ((Processor*) 0);
535         _post_processor.reset ((Processor*) 0);
536
537         //update_title();
538 }
539
540 void
541 RouteParams_UI::show_track_menu()
542 {
543         using namespace Menu_Helpers;
544         
545         if (track_menu == 0) {
546                 track_menu = new Menu;
547                 track_menu->set_name ("ArdourContextMenu");
548                 track_menu->items().push_back 
549                                 (MenuElem (_("Add Track/Bus"), 
550                                            bind (mem_fun (*(ARDOUR_UI::instance()), &ARDOUR_UI::add_route), (Gtk::Window*) 0)));
551         }
552         track_menu->popup (1, gtk_get_current_event_time());
553 }
554
555 void
556 RouteParams_UI::redirect_selected (boost::shared_ptr<ARDOUR::Processor> insert, ARDOUR::Placement place)
557 {
558         if ((place == PreFader && _pre_processor == insert)
559             || (place == PostFader && _post_processor == insert)){
560                 return;
561         }
562         
563         boost::shared_ptr<Send> send;
564         boost::shared_ptr<Return> retrn;
565         boost::shared_ptr<PluginInsert> plugin_insert;
566         boost::shared_ptr<PortInsert> port_insert;
567         
568         if ((send = boost::dynamic_pointer_cast<Send> (insert)) != 0) {
569
570                 SendUI *send_ui = new SendUI (send, *session);
571
572                 if (place == PreFader) {
573                         cleanup_pre_view();
574                         _pre_plugin_conn = send->GoingAway.connect (bind (
575                                         mem_fun(*this, &RouteParams_UI::redirect_going_away),
576                                         insert));
577                         _active_pre_view = send_ui;
578                         
579                         pre_redir_hpane.add2 (*_active_pre_view);
580                         pre_redir_hpane.show_all();
581                 } else {
582                         cleanup_post_view();
583                         _post_plugin_conn = send->GoingAway.connect (bind (
584                                         mem_fun(*this, &RouteParams_UI::redirect_going_away),
585                                         insert));
586                         _active_post_view = send_ui;
587                         
588                         post_redir_hpane.add2 (*_active_post_view);
589                         post_redir_hpane.show_all();
590                 }
591
592         } else if ((retrn = boost::dynamic_pointer_cast<Return> (insert)) != 0) {
593
594                 ReturnUI *return_ui = new ReturnUI (retrn, *session);
595
596                 if (place == PreFader) {
597                         cleanup_pre_view();
598                         _pre_plugin_conn = retrn->GoingAway.connect (bind (
599                                         mem_fun(*this, &RouteParams_UI::redirect_going_away),
600                                         insert));
601                         _active_pre_view = return_ui;
602                         
603                         pre_redir_hpane.add2 (*_active_pre_view);
604                         pre_redir_hpane.show_all();
605                 } else {
606                         cleanup_post_view();
607                         _post_plugin_conn = retrn->GoingAway.connect (bind (
608                                         mem_fun(*this, &RouteParams_UI::redirect_going_away),
609                                         insert));
610                         _active_post_view = return_ui;
611                         
612                         post_redir_hpane.add2 (*_active_post_view);
613                         post_redir_hpane.show_all();
614                 }
615
616         } else if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (insert)) != 0) {                         
617
618                 GenericPluginUI *plugin_ui = new GenericPluginUI (plugin_insert, true);
619
620                 if (place == PreFader) {
621                         cleanup_pre_view();
622                         _pre_plugin_conn = plugin_insert->plugin()->GoingAway.connect (bind (
623                                         mem_fun(*this, &RouteParams_UI::plugin_going_away),
624                                         PreFader));
625                         plugin_ui->start_updating (0);
626                         _active_pre_view = plugin_ui;
627                         pre_redir_hpane.pack2 (*_active_pre_view);
628                         pre_redir_hpane.show_all();
629                 } else {
630                         cleanup_post_view();
631                         _post_plugin_conn = plugin_insert->plugin()->GoingAway.connect (bind (
632                                         mem_fun(*this, &RouteParams_UI::plugin_going_away),
633                                         PostFader));
634                         plugin_ui->start_updating (0);
635                         _active_post_view = plugin_ui;
636                         post_redir_hpane.pack2 (*_active_post_view);
637                         post_redir_hpane.show_all();
638                 }
639
640         } else if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (insert)) != 0) {
641
642                 PortInsertUI *portinsert_ui = new PortInsertUI (*session, port_insert);
643                                 
644                 if (place == PreFader) {
645                         cleanup_pre_view();
646                         _pre_plugin_conn = port_insert->GoingAway.connect (bind (
647                                         mem_fun(*this, &RouteParams_UI::redirect_going_away),
648                                         insert));
649                         _active_pre_view = portinsert_ui;
650                         pre_redir_hpane.pack2 (*_active_pre_view);
651                         portinsert_ui->redisplay();
652                         pre_redir_hpane.show_all();
653                 } else {
654                         cleanup_post_view();
655                         _post_plugin_conn = port_insert->GoingAway.connect (bind (
656                                         mem_fun(*this, &RouteParams_UI::redirect_going_away),
657                                         insert));
658                         _active_post_view = portinsert_ui;
659                         post_redir_hpane.pack2 (*_active_post_view);
660                         portinsert_ui->redisplay();
661                         post_redir_hpane.show_all();
662                 }
663         }
664                                 
665         if (place == PreFader) {
666                 _pre_processor = insert;
667         } else {
668                 _post_processor = insert;
669         }
670         
671         update_title();
672                 
673 }
674
675 void
676 RouteParams_UI::plugin_going_away (Placement place)
677 {
678         ENSURE_GUI_THREAD(bind (mem_fun(*this, &RouteParams_UI::plugin_going_away), place));
679         
680         // delete the current view without calling finish
681
682         if (place == PreFader) {
683                 cleanup_pre_view (false);
684                 _pre_processor.reset ((Processor*) 0);
685         }
686         else {
687                 cleanup_post_view (false);
688                 _post_processor.reset ((Processor*) 0);
689         }
690 }
691
692 void
693 RouteParams_UI::redirect_going_away (boost::shared_ptr<ARDOUR::Processor> insert)
694
695 {
696         ENSURE_GUI_THREAD(bind (mem_fun(*this, &RouteParams_UI::redirect_going_away), insert));
697         
698         printf ("redirect going away\n");
699         // delete the current view without calling finish
700         if (insert == _pre_processor) {
701                 cleanup_pre_view (false);
702                 _pre_processor.reset ((Processor*) 0);
703         } else if (insert == _post_processor) {
704                 cleanup_post_view (false);
705                 _post_processor.reset ((Processor*) 0);
706         }
707 }
708
709
710 void
711 RouteParams_UI::update_title ()
712 {
713         WindowTitle title(Glib::get_application_name());
714         title += _("Track/Bus Inspector");
715
716         if (_route) {
717
718                 //              title += ": ";
719
720                 //              if (_redirect && (_current_view == PLUGIN_CONFIG_VIEW || _current_view == SEND_CONFIG_VIEW)) {
721                 //                      title += _redirect->name();
722                 //              }
723                 //              else if (_current_view == INPUT_CONFIG_VIEW) {
724                 //                      title += _("INPUT");
725                 //              }
726                 //              else if (_current_view == OUTPUT_CONFIG_VIEW) {
727                 //                      title += _("OUTPUT");
728                 //              }
729
730                 title_label.set_text(_route->name());
731
732                 title += _route->name();
733
734                 set_title(title.get_string());
735         }
736         else {
737                 title_label.set_text(_("No Route Selected"));
738                 title += _("No Route Selected");
739                 set_title(title.get_string());
740         }       
741 }
742
743 void
744 RouteParams_UI::start_updating ()
745 {
746         update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect 
747                 (mem_fun(*this, &RouteParams_UI::update_views));
748 }
749
750 void
751 RouteParams_UI::stop_updating ()
752 {
753         update_connection.disconnect();
754 }
755
756 void
757 RouteParams_UI::update_views ()
758 {
759         SendUI *sui;
760         // TODO: only do it if correct tab is showing
761         
762         if ((sui = dynamic_cast<SendUI*> (_active_pre_view)) != 0) {
763                 sui->update ();
764         }
765         if ((sui = dynamic_cast<SendUI*> (_active_post_view)) != 0) {
766                 sui->update ();
767         }
768
769 }