2005-09-25 18:42:24 +00:00
/*
Copyright ( C ) 2000 Paul Davis
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include <climits>
# include <cerrno>
# include <cmath>
# include <string>
# include <pbd/stl_delete.h>
# include <pbd/xml++.h>
# include <pbd/failed_constructor.h>
2006-08-10 14:41:53 +00:00
# include <gtkmm/widget.h>
2005-09-25 20:33:00 +00:00
# include <gtkmm2ext/click_box.h>
# include <gtkmm2ext/fastmeter.h>
# include <gtkmm2ext/barcontroller.h>
# include <gtkmm2ext/utils.h>
# include <gtkmm2ext/doi.h>
2006-07-07 23:51:30 +00:00
# include <gtkmm2ext/slider_controller.h>
2010-01-15 17:50:03 +00:00
# include <gtkmm2ext/application.h>
2005-09-25 18:42:24 +00:00
# include <midi++/manager.h>
# include <ardour/plugin.h>
# include <ardour/insert.h>
# include <ardour/ladspa_plugin.h>
# ifdef VST_SUPPORT
# include <ardour/vst_plugin.h>
# endif
2008-08-09 00:49:07 +00:00
# ifdef HAVE_LV2
# include <ardour/lv2_plugin.h>
# include "lv2_plugin_ui.h"
# endif
2005-09-25 18:42:24 +00:00
# include <lrdf.h>
# include "ardour_ui.h"
# include "prompter.h"
# include "plugin_ui.h"
# include "utils.h"
# include "gui_thread.h"
2006-08-10 14:41:53 +00:00
# include "public_editor.h"
2008-06-18 19:29:19 +00:00
# include "keyboard.h"
2005-09-25 18:42:24 +00:00
# include "i18n.h"
using namespace std ;
using namespace ARDOUR ;
2006-06-21 23:01:03 +00:00
using namespace PBD ;
2005-09-25 20:33:00 +00:00
using namespace Gtkmm2ext ;
2005-09-25 18:42:24 +00:00
using namespace Gtk ;
2005-09-25 20:33:00 +00:00
using namespace sigc ;
2005-09-25 18:42:24 +00:00
2008-02-23 15:22:58 +00:00
PluginUIWindow : : PluginUIWindow ( Gtk : : Window * win , boost : : shared_ptr < PluginInsert > insert , bool scrollable )
: parent ( win )
2005-09-25 18:42:24 +00:00
{
2007-12-10 21:32:27 +00:00
bool have_gui = false ;
non_gtk_gui = false ;
2008-04-09 21:05:58 +00:00
was_visible = false ;
2005-09-25 18:42:24 +00:00
2007-12-10 21:32:27 +00:00
if ( insert - > plugin ( ) - > has_editor ( ) ) {
switch ( insert - > type ( ) ) {
case ARDOUR : : VST :
have_gui = create_vst_editor ( insert ) ;
break ;
case ARDOUR : : AudioUnit :
2008-01-28 21:33:36 +00:00
have_gui = create_audiounit_editor ( insert ) ;
2007-12-10 21:32:27 +00:00
break ;
2005-09-25 18:42:24 +00:00
2007-12-10 21:32:27 +00:00
case ARDOUR : : LADSPA :
error < < _ ( " Eh? LADSPA plugins don't have editors! " ) < < endmsg ;
break ;
2008-08-09 00:49:07 +00:00
case ARDOUR : : LV2 :
have_gui = create_lv2_editor ( insert ) ;
break ;
2007-12-10 21:32:27 +00:00
default :
2008-01-18 19:58:34 +00:00
# ifndef VST_SUPPORT
2005-09-25 18:42:24 +00:00
error < < _ ( " unknown type of editor-supplying plugin (note: no VST support in this version of ardour) " )
< < endmsg ;
2008-01-18 19:58:34 +00:00
# else
error < < _ ( " unknown type of editor-supplying plugin " )
< < endmsg ;
# endif
2005-09-25 18:42:24 +00:00
throw failed_constructor ( ) ;
}
2007-12-10 21:32:27 +00:00
}
2005-09-25 18:42:24 +00:00
2007-12-10 21:32:27 +00:00
if ( ! have_gui ) {
GenericPluginUI * pu = new GenericPluginUI ( insert , scrollable ) ;
2005-09-25 18:42:24 +00:00
_pluginui = pu ;
2008-02-12 02:51:51 +00:00
add ( * pu ) ;
2005-09-25 18:42:24 +00:00
2007-02-06 20:09:35 +00:00
set_wmclass ( X_ ( " ardour_plugin_editor " ) , " Ardour " ) ;
2007-12-10 21:32:27 +00:00
signal_map_event ( ) . connect ( mem_fun ( * pu , & GenericPluginUI : : start_updating ) ) ;
signal_unmap_event ( ) . connect ( mem_fun ( * pu , & GenericPluginUI : : stop_updating ) ) ;
2005-09-25 18:42:24 +00:00
}
2008-02-12 02:51:51 +00:00
// set_position (Gtk::WIN_POS_MOUSE);
2005-09-25 18:42:24 +00:00
set_name ( " PluginEditor " ) ;
2006-04-26 16:04:04 +00:00
add_events ( Gdk : : KEY_PRESS_MASK | Gdk : : KEY_RELEASE_MASK | Gdk : : BUTTON_PRESS_MASK | Gdk : : BUTTON_RELEASE_MASK ) ;
2005-09-25 18:42:24 +00:00
2008-01-18 19:58:34 +00:00
signal_delete_event ( ) . connect ( bind ( sigc : : ptr_fun ( just_hide_it ) , reinterpret_cast < Window * > ( this ) ) , false ) ;
2009-03-24 15:48:34 +00:00
death_connection = insert - > GoingAway . connect ( mem_fun ( * this , & PluginUIWindow : : plugin_going_away ) ) ;
2005-09-25 18:42:24 +00:00
2007-12-10 21:32:27 +00:00
gint h = _pluginui - > get_preferred_height ( ) ;
gint w = _pluginui - > get_preferred_width ( ) ;
2005-09-25 18:42:24 +00:00
if ( scrollable ) {
if ( h > 600 ) h = 600 ;
2007-12-10 21:32:27 +00:00
if ( w > 600 ) w = 600 ;
if ( w < 0 ) {
w = 450 ;
}
2005-09-25 18:42:24 +00:00
}
2006-08-10 14:41:53 +00:00
2007-12-10 21:32:27 +00:00
set_default_size ( w , h ) ;
2005-09-25 18:42:24 +00:00
}
PluginUIWindow : : ~ PluginUIWindow ( )
{
2009-03-24 15:48:34 +00:00
delete _pluginui ;
2005-09-25 18:42:24 +00:00
}
2006-11-03 01:42:51 +00:00
2008-02-23 15:22:58 +00:00
void
PluginUIWindow : : set_parent ( Gtk : : Window * win )
{
parent = win ;
}
2008-02-22 02:48:38 +00:00
void
PluginUIWindow : : on_map ( )
{
Window : : on_map ( ) ;
set_keep_above ( true ) ;
}
2008-06-18 19:29:19 +00:00
bool
PluginUIWindow : : on_enter_notify_event ( GdkEventCrossing * ev )
{
Keyboard : : the_keyboard ( ) . enter_window ( ev , this ) ;
return false ;
}
bool
PluginUIWindow : : on_leave_notify_event ( GdkEventCrossing * ev )
{
Keyboard : : the_keyboard ( ) . leave_window ( ev , this ) ;
return false ;
}
2008-10-29 07:35:40 +00:00
bool
PluginUIWindow : : on_focus_in_event ( GdkEventFocus * ev )
{
Window : : on_focus_in_event ( ev ) ;
//Keyboard::the_keyboard().magic_widget_grab_focus ();
return false ;
}
bool
PluginUIWindow : : on_focus_out_event ( GdkEventFocus * ev )
{
Window : : on_focus_out_event ( ev ) ;
//Keyboard::the_keyboard().magic_widget_drop_focus ();
return false ;
}
2008-01-18 19:58:34 +00:00
void
PluginUIWindow : : on_show ( )
{
2009-10-01 15:43:52 +00:00
set_role ( " plugin_ui " ) ;
2010-01-13 02:08:37 +00:00
2008-02-20 21:18:01 +00:00
if ( _pluginui ) {
_pluginui - > update_presets ( ) ;
}
2008-02-23 15:22:58 +00:00
2009-10-01 15:43:52 +00:00
if ( _pluginui ) {
if ( _pluginui - > on_window_show ( _title ) ) {
Window : : on_show ( ) ;
}
2010-01-13 02:08:37 +00:00
}
2008-02-23 15:22:58 +00:00
if ( parent ) {
// set_transient_for (*parent);
}
2008-01-18 19:58:34 +00:00
}
void
PluginUIWindow : : on_hide ( )
{
2008-02-12 02:51:51 +00:00
Window : : on_hide ( ) ;
2009-10-01 15:43:52 +00:00
if ( _pluginui ) {
_pluginui - > on_window_hide ( ) ;
}
}
void
PluginUIWindow : : set_title ( const Glib : : ustring & title )
{
//cout << "PluginUIWindow::set_title(\"" << title << "\"" << endl;
Gtk : : Window : : set_title ( title ) ;
_title = title ;
2008-01-18 19:58:34 +00:00
}
2007-12-10 21:32:27 +00:00
bool
PluginUIWindow : : create_vst_editor ( boost : : shared_ptr < PluginInsert > insert )
{
# ifndef VST_SUPPORT
return false ;
# else
2007-12-13 03:59:21 +00:00
boost : : shared_ptr < VSTPlugin > vp ;
if ( ( vp = boost : : dynamic_pointer_cast < VSTPlugin > ( insert - > plugin ( ) ) ) = = 0 ) {
error < < _ ( " unknown type of editor-supplying plugin (note: no VST support in this version of ardour) " )
< < endmsg ;
throw failed_constructor ( ) ;
} else {
VSTPluginUI * vpu = new VSTPluginUI ( insert , vp ) ;
2007-12-10 21:32:27 +00:00
2007-12-13 03:59:21 +00:00
_pluginui = vpu ;
2008-02-12 02:51:51 +00:00
add ( * vpu ) ;
2007-12-13 03:59:21 +00:00
vpu - > package ( * this ) ;
}
2007-12-10 21:32:27 +00:00
non_gtk_gui = true ;
return true ;
# endif
}
bool
PluginUIWindow : : create_audiounit_editor ( boost : : shared_ptr < PluginInsert > insert )
{
# if !defined(HAVE_AUDIOUNITS) || !defined(GTKOSX)
return false ;
# else
VBox * box ;
_pluginui = create_au_gui ( insert , & box ) ;
2008-02-12 02:51:51 +00:00
add ( * box ) ;
2007-12-10 21:32:27 +00:00
non_gtk_gui = true ;
2010-01-15 17:50:03 +00:00
Application : : instance ( ) - > ActivationChanged . connect ( mem_fun ( * this , & PluginUIWindow : : app_activated ) ) ;
2007-12-10 21:32:27 +00:00
return true ;
# endif
}
void
PluginUIWindow : : app_activated ( bool yn )
{
2008-01-07 20:41:51 +00:00
# if defined (HAVE_AUDIOUNITS) && defined(GTKOSX)
2008-02-12 02:51:51 +00:00
if ( _pluginui ) {
if ( yn ) {
2008-04-09 21:05:58 +00:00
if ( was_visible ) {
_pluginui - > activate ( ) ;
2010-01-13 02:08:37 +00:00
// present ();
show ( ) ;
2008-04-09 21:05:58 +00:00
was_visible = true ;
}
2008-02-12 02:51:51 +00:00
} else {
2008-04-09 21:05:58 +00:00
was_visible = is_visible ( ) ;
2008-02-12 02:51:51 +00:00
hide ( ) ;
_pluginui - > deactivate ( ) ;
2008-01-18 19:58:34 +00:00
}
2008-02-12 02:51:51 +00:00
}
2007-12-10 21:32:27 +00:00
# endif
}
2008-08-09 00:49:07 +00:00
bool
PluginUIWindow : : create_lv2_editor ( boost : : shared_ptr < PluginInsert > insert )
{
# ifndef HAVE_LV2
return false ;
# else
boost : : shared_ptr < LV2Plugin > vp ;
if ( ( vp = boost : : dynamic_pointer_cast < LV2Plugin > ( insert - > plugin ( ) ) ) = = 0 ) {
error < < _ ( " create_lv2_editor called on non-LV2 plugin " ) < < endmsg ;
throw failed_constructor ( ) ;
} else {
LV2PluginUI * lpu = new LV2PluginUI ( insert , vp ) ;
_pluginui = lpu ;
add ( * lpu ) ;
lpu - > package ( * this ) ;
}
non_gtk_gui = false ;
return true ;
# endif
}
2006-08-10 14:41:53 +00:00
bool
PluginUIWindow : : on_key_press_event ( GdkEventKey * event )
{
2009-09-13 15:35:30 +00:00
return relay_key_press ( event , this ) ;
2006-08-10 14:41:53 +00:00
}
bool
PluginUIWindow : : on_key_release_event ( GdkEventKey * event )
{
2006-11-08 16:39:19 +00:00
return true ;
2006-08-10 14:41:53 +00:00
}
2005-09-25 18:42:24 +00:00
void
2006-08-25 01:07:15 +00:00
PluginUIWindow : : plugin_going_away ( )
2005-09-25 18:42:24 +00:00
{
2006-08-25 01:07:15 +00:00
ENSURE_GUI_THREAD ( mem_fun ( * this , & PluginUIWindow : : plugin_going_away ) ) ;
2009-03-24 15:48:34 +00:00
2008-01-18 19:58:34 +00:00
if ( _pluginui ) {
_pluginui - > stop_updating ( 0 ) ;
}
2009-03-24 15:48:34 +00:00
death_connection . disconnect ( ) ;
2005-09-25 18:42:24 +00:00
delete_when_idle ( this ) ;
}
2006-07-27 16:52:14 +00:00
PlugUIBase : : PlugUIBase ( boost : : shared_ptr < PluginInsert > pi )
2005-09-25 18:42:24 +00:00
: insert ( pi ) ,
2006-07-27 16:52:14 +00:00
plugin ( insert - > plugin ( ) ) ,
2009-01-28 15:09:36 +00:00
save_button ( _ ( " Save " ) ) ,
2006-04-19 20:42:17 +00:00
bypass_button ( _ ( " Bypass " ) )
2005-09-25 18:42:24 +00:00
{
2008-02-12 19:58:11 +00:00
//preset_combo.set_use_arrows_always(true);
preset_combo . set_size_request ( 100 , - 1 ) ;
2009-01-28 15:09:36 +00:00
update_presets ( ) ;
2008-02-12 19:58:11 +00:00
preset_combo . signal_changed ( ) . connect ( mem_fun ( * this , & PlugUIBase : : setting_selected ) ) ;
2009-01-28 15:09:36 +00:00
no_load_preset = false ;
2005-09-25 18:42:24 +00:00
save_button . set_name ( " PluginSaveButton " ) ;
2005-10-09 05:03:29 +00:00
save_button . signal_clicked ( ) . connect ( mem_fun ( * this , & PlugUIBase : : save_plugin_setting ) ) ;
2005-09-25 18:42:24 +00:00
2008-02-12 19:58:11 +00:00
insert - > active_changed . connect ( mem_fun ( * this , & PlugUIBase : : redirect_active_changed ) ) ;
bypass_button . set_active ( ! pi - > active ( ) ) ;
2005-09-25 18:42:24 +00:00
bypass_button . set_name ( " PluginBypassButton " ) ;
2005-10-09 05:03:29 +00:00
bypass_button . signal_toggled ( ) . connect ( mem_fun ( * this , & PlugUIBase : : bypass_toggled ) ) ;
2008-10-30 23:45:20 +00:00
focus_button . add_events ( Gdk : : ENTER_NOTIFY_MASK | Gdk : : LEAVE_NOTIFY_MASK ) ;
2008-10-29 07:35:40 +00:00
focus_button . signal_button_release_event ( ) . connect ( mem_fun ( * this , & PlugUIBase : : focus_toggled ) ) ;
focus_button . add_events ( Gdk : : ENTER_NOTIFY_MASK | Gdk : : LEAVE_NOTIFY_MASK ) ;
/* these images are not managed, so that we can remove them at will */
focus_out_image = new Image ( get_icon ( X_ ( " computer_keyboard " ) ) ) ;
focus_in_image = new Image ( get_icon ( X_ ( " computer_keyboard_active " ) ) ) ;
focus_button . add ( * focus_out_image ) ;
2008-10-30 23:45:20 +00:00
2009-03-27 18:05:11 +00:00
ARDOUR_UI : : instance ( ) - > set_tip ( & focus_button , _ ( " Click to allow the plugin to receive keyboard events that Ardour would normally use as a shortcut " ) , " " ) ;
2008-10-30 23:45:20 +00:00
ARDOUR_UI : : instance ( ) - > set_tip ( & bypass_button , _ ( " Click to enable/disable this plugin " ) , " " ) ;
2009-07-03 21:21:30 +00:00
insert - > GoingAway . connect ( mem_fun ( * this , & PlugUIBase : : plugin_going_away ) ) ;
2005-09-25 18:42:24 +00:00
}
2009-03-24 15:48:34 +00:00
PlugUIBase : : ~ PlugUIBase ( )
{
}
2009-07-03 21:21:30 +00:00
void
PlugUIBase : : plugin_going_away ( )
{
/* drop references to the plugin/insert */
insert . reset ( ) ;
plugin . reset ( ) ;
}
2008-02-12 19:58:11 +00:00
void
PlugUIBase : : redirect_active_changed ( Redirect * r , void * src )
{
ENSURE_GUI_THREAD ( bind ( mem_fun ( * this , & PlugUIBase : : redirect_active_changed ) , r , src ) ) ;
2009-03-19 20:31:24 +00:00
bypass_button . set_active ( ! r - > active ( ) ) ;
2008-02-12 19:58:11 +00:00
}
2005-11-23 17:21:12 +00:00
void
PlugUIBase : : setting_selected ( )
2005-09-25 18:42:24 +00:00
{
2009-01-28 15:09:36 +00:00
if ( no_load_preset ) {
return ;
}
2008-02-12 19:58:11 +00:00
if ( preset_combo . get_active_text ( ) . length ( ) > 0 ) {
if ( ! plugin - > load_preset ( preset_combo . get_active_text ( ) ) ) {
warning < < string_compose ( _ ( " Plugin preset %1 not found " ) , preset_combo . get_active_text ( ) ) < < endmsg ;
2005-09-25 18:42:24 +00:00
}
}
}
void
PlugUIBase : : save_plugin_setting ( )
{
ArdourPrompter prompter ( true ) ;
2006-04-19 20:42:17 +00:00
prompter . set_prompt ( _ ( " Name of New Preset: " ) ) ;
prompter . add_button ( Gtk : : Stock : : ADD , Gtk : : RESPONSE_ACCEPT ) ;
2006-04-22 15:28:59 +00:00
prompter . set_response_sensitive ( Gtk : : RESPONSE_ACCEPT , false ) ;
2008-11-11 16:00:27 +00:00
prompter . set_type_hint ( Gdk : : WINDOW_TYPE_HINT_UTILITY ) ;
2005-09-25 18:42:24 +00:00
prompter . show_all ( ) ;
2009-03-27 17:11:33 +00:00
prompter . present ( ) ;
2005-09-25 18:42:24 +00:00
2005-10-27 01:10:36 +00:00
switch ( prompter . run ( ) ) {
2005-11-25 03:36:42 +00:00
case Gtk : : RESPONSE_ACCEPT :
2005-09-25 18:42:24 +00:00
string name ;
prompter . get_result ( name ) ;
if ( name . length ( ) ) {
2009-01-28 15:09:36 +00:00
if ( plugin - > save_preset ( name ) ) {
/* a rather inefficient way to add the newly saved preset
to the list .
*/
no_load_preset = true ;
2009-11-19 04:27:25 +00:00
set_popdown_strings ( preset_combo , plugin - > get_presets ( ) ) ;
2008-02-12 19:58:11 +00:00
preset_combo . set_active_text ( name ) ;
2009-01-28 15:09:36 +00:00
no_load_preset = false ;
2005-09-25 18:42:24 +00:00
}
}
2005-10-27 01:10:36 +00:00
break ;
2005-09-25 18:42:24 +00:00
}
}
void
PlugUIBase : : bypass_toggled ( )
{
bool x ;
2006-07-27 16:52:14 +00:00
if ( ( x = bypass_button . get_active ( ) ) = = insert - > active ( ) ) {
insert - > set_active ( ! x , this ) ;
2005-09-25 18:42:24 +00:00
}
}
2006-08-11 20:35:55 +00:00
2008-10-29 07:35:40 +00:00
bool
PlugUIBase : : focus_toggled ( GdkEventButton * ev )
{
if ( Keyboard : : the_keyboard ( ) . some_magic_widget_has_focus ( ) ) {
Keyboard : : the_keyboard ( ) . magic_widget_drop_focus ( ) ;
focus_button . remove ( ) ;
focus_button . add ( * focus_out_image ) ;
focus_out_image - > show ( ) ;
2009-03-27 18:05:11 +00:00
ARDOUR_UI : : instance ( ) - > set_tip ( & focus_button , _ ( " Click to allow the plugin to receive keyboard events that Ardour would normally use as a shortcut " ) , " " ) ;
2008-10-29 07:35:40 +00:00
} else {
Keyboard : : the_keyboard ( ) . magic_widget_grab_focus ( ) ;
focus_button . remove ( ) ;
focus_button . add ( * focus_in_image ) ;
focus_in_image - > show ( ) ;
2009-03-27 18:05:11 +00:00
ARDOUR_UI : : instance ( ) - > set_tip ( & focus_button , _ ( " Click to allow normal use of Ardour keyboard shortcuts " ) , " " ) ;
2008-10-29 07:35:40 +00:00
}
return true ;
}
2008-02-20 21:18:01 +00:00
void
PlugUIBase : : update_presets ( )
{
2009-01-28 15:09:36 +00:00
vector < string > presets = plugin - > get_presets ( ) ;
2009-11-19 04:27:25 +00:00
no_load_preset = true ;
2008-02-20 21:18:01 +00:00
set_popdown_strings ( preset_combo , plugin - > get_presets ( ) ) ;
2009-01-28 15:09:36 +00:00
string current_preset = plugin - > current_preset ( ) ;
if ( ! current_preset . empty ( ) ) {
for ( vector < string > : : iterator p = presets . begin ( ) ; p ! = presets . end ( ) ; + + p ) {
if ( * p = = current_preset ) {
preset_combo . set_active_text ( current_preset ) ;
}
}
}
2009-11-19 04:27:25 +00:00
no_load_preset = false ;
2008-02-20 21:18:01 +00:00
}