From 4c2544874d386d4ef90461548994a792625ac0d2 Mon Sep 17 00:00:00 2001 From: "james.k.crook@gmail.com" Date: Sat, 24 Aug 2013 15:38:26 +0000 Subject: [PATCH] Bug 368: VST plugins now have a dialog that gives a list of plugine to choose from. --- images/Arrow.xpm | 164 +++++++++++++++++++++++ src/PluginManager.cpp | 1 + src/effects/VST/VSTEffect.cpp | 242 +++++++++++++++++++++++++++++----- src/effects/VST/VSTEffect.h | 6 + 4 files changed, 381 insertions(+), 32 deletions(-) diff --git a/images/Arrow.xpm b/images/Arrow.xpm index 65599f8c2..c873cb5b0 100644 --- a/images/Arrow.xpm +++ b/images/Arrow.xpm @@ -41,3 +41,167 @@ static const char * empty_9x16_xpm[] = { ".........", ".........", "........."}; + +/* XPM */ +static char * unchecked_xpm[] = { +"15 15 56 1", +" c None", +". c #FFFFFF", +"+ c #8E8F8F", +"@ c #F4F4F4", +"# c #AEB3B9", +"$ c #AFB4BA", +"% c #B4B9BD", +"& c #BBBEC1", +"* c #CBCFD5", +"= c #D0D3D8", +"- c #D5D8DC", +"; c #DBDDDF", +"> c #C1C3C5", +", c #CDD1D6", +"' c #D2D5DA", +") c #D8DBDE", +"! c #DDDFE1", +"~ c #E2E3E4", +"{ c #C6C7C8", +"] c #CDD1D7", +"^ c #D0D4D9", +"/ c #D4D7DB", +"( c #E1E2E3", +"_ c #E5E6E6", +": c #E8E8E8", +"< c #CCCDCD", +"[ c #B2B7BC", +"} c #DADCDF", +"| c #E0E1E3", +"1 c #ECECEC", +"2 c #EDEDED", +"3 c #D4D5D6", +"4 c #B8BBBF", +"5 c #E4E5E5", +"6 c #EAEAEA", +"7 c #EFEFEF", +"8 c #F2F2F2", +"9 c #DCDDDE", +"0 c #BCBFC2", +"a c #E3E4E5", +"b c #E9E9E9", +"c c #F5F5F5", +"d c #E1E2E2", +"e c #C2C4C6", +"f c #F0F0F0", +"g c #F6F6F6", +"h c #E6E6E6", +"i c #CACBCC", +"j c #D4D4D5", +"k c #DBDBDC", +"l c #E0E1E1", +"m c #E6E7E7", +"n c #EAEBEB", +"o c #EBECEC", +"p c #EBEBEC", +"q c #E9E9EA", +"...............", +".+++++++++++++.", +".+@@@@@@@@@@@+.", +".+@######$%&@+.", +".+@#****=-;>@+.", +".+@#**,')!~{@+.", +".+@#]^/;(_:<@+.", +".+@[-}|:1223@+.", +".+@4!5678889@+.", +".+@0ab28@c@d@+.", +".+@eb2f@gggh@+.", +".+@ijklmnopq@+.", +".+@@@@@@@@@@@+.", +".+++++++++++++.", +"..............."}; + +/* XPM */ +static char * checked_xpm[] = { +"15 15 70 1", +" c #FFFFFF", +". c #8E8F8F", +"+ c #F4F4F4", +"@ c #F8F8F8", +"# c #F9F9F9", +"$ c #F6F6F6", +"% c #AEB3B9", +"& c #C9CCD0", +"* c #76DB7E", +"= c #45CE4F", +"- c #DCDFE4", +"; c #F5F5F5", +"> c #CBCFD5", +", c #C9D3D2", +"' c #EBEFEF", +") c #2EAF37", +"! c #289730", +"~ c #9CE5A2", +"{ c #CDD1D6", +"] c #E0E2E6", +"^ c #90E196", +"/ c #3DB351", +"( c #E4EAE5", +"_ c #ADB5B7", +": c #D5D9DD", +"< c #DFE2E5", +"[ c #D5D8DC", +"} c #EFF5F1", +"| c #30B93A", +"1 c #289B31", +"2 c #A1E6A6", +"3 c #DBDCDC", +"4 c #C5C9CD", +"5 c #B3EAB7", +"6 c #87D693", +"7 c #E9F1EA", +"8 c #A0E5A5", +"9 c #299E32", +"0 c #33C23D", +"a c #D5D5D6", +"b c #CDF2D0", +"c c #3ACB45", +"d c #299A33", +"e c #BFE9C6", +"f c #33C43E", +"g c #2A9F32", +"h c #9BE4A0", +"i c #F5F7F5", +"j c #DCDDDE", +"k c #C8D4CC", +"l c #D0EFD5", +"m c #299C31", +"n c #32BD3C", +"o c #F7FAF9", +"p c #DFE4E0", +"q c #C6C8CA", +"r c #E5F0E9", +"s c #62D56A", +"t c #2BA233", +"u c #93E299", +"v c #F7F9F8", +"w c #E5E7E5", +"x c #CACBCC", +"y c #D9DBDA", +"z c #DEE3E8", +"A c #76C38B", +"B c #F2F3F6", +"C c #ECEDED", +"D c #EBEBEC", +"E c #E9E9EA", +" ", +" ............. ", +" .+++++++@#$+. ", +" .+%%%%%&*=-;. ", +" .+%>>>,')!~$. ", +" .+%>>{]^!/(+. ", +" .+_:<[}|123+. ", +" .+4567890@a+. ", +" .+bcdefghij+. ", +" .+klm9gno+p+. ", +" .+qrs9tuv$w+. ", +" .+xyzsABCDE+. ", +" .+++;#@;++++. ", +" ............. ", +" "}; diff --git a/src/PluginManager.cpp b/src/PluginManager.cpp index b97115b69..0ff416906 100644 --- a/src/PluginManager.cpp +++ b/src/PluginManager.cpp @@ -185,6 +185,7 @@ void PluginManager::PurgeType(const wxString & type) path.Printf(wxT("/%s"), type.c_str()); + SetDirty(); mConfig->DeleteGroup(path); } diff --git a/src/effects/VST/VSTEffect.cpp b/src/effects/VST/VSTEffect.cpp index b24d6bdd8..b30b74373 100644 --- a/src/effects/VST/VSTEffect.cpp +++ b/src/effects/VST/VSTEffect.cpp @@ -32,6 +32,8 @@ #include #include #include +#include +#include #if defined(__WXMAC__) #include @@ -57,6 +59,8 @@ #include "../../xml/XMLFileReader.h" #include "../../xml/XMLWriter.h" #include "../EffectManager.h" +#include "../../Theme.h" +#include "../images/Arrow.xpm" #include "VSTEffect.h" @@ -73,7 +77,7 @@ void RegisterVSTEffects() pm.Open(); bool bScanRequired = false; - if (gPrefs->Read(wxT("/VST/Rescan"), (long)true) != false) { + if ( bScanRequired || gPrefs->Read(wxT("/VST/Rescan"), (long)true) != false) { pm.PurgeType(VSTPLUGINTYPE); gPrefs->Write(wxT("/VST/Rescan"), false); gPrefs->Flush(); @@ -81,14 +85,12 @@ void RegisterVSTEffects() } if (!pm.HasType(VSTPLUGINTYPE)) { - // rescan. pm.Close(); if( bScanRequired) VSTEffect::Scan(); pm.Open(); } - EffectManager & em = EffectManager::Get(); wxString path = pm.GetFirstPlugin(VSTPLUGINTYPE); @@ -107,6 +109,164 @@ void RegisterVSTEffects() pm.Close(); } +class PluginRegistrationDialog:public wxDialog { + public: + // constructors and destructors + PluginRegistrationDialog(wxWindow * parent, const wxArrayString & files); + virtual ~PluginRegistrationDialog(); + public: + void Populate(); + void PopulateOrExchange( ShuttleGui & S ); + + void OnApply(wxCommandEvent & event); + void OnCancel(wxCommandEvent & event); + void OnToggleState( wxListEvent & event ); + + wxButton *mOK; + wxButton *mCancel; + wxListCtrl *mPlugins; + wxArrayString mFiles; + wxArrayInt miState; +// wxListCtrl *mList; +// BatchCommands mBatchCommands; + + bool mAbort; + + DECLARE_EVENT_TABLE() +}; + + +#define PluginListID 7001 + +BEGIN_EVENT_TABLE(PluginRegistrationDialog, wxDialog) + EVT_BUTTON(wxID_OK, PluginRegistrationDialog::OnApply) + EVT_BUTTON(wxID_CANCEL, PluginRegistrationDialog::OnCancel) + EVT_LIST_ITEM_SELECTED( wxID_ANY, PluginRegistrationDialog::OnToggleState ) +END_EVENT_TABLE() + +PluginRegistrationDialog::PluginRegistrationDialog(wxWindow * parent, const wxArrayString & files): + mFiles( files ), + wxDialog(parent, wxID_ANY, _("Install VST Plugins"), + wxDefaultPosition, wxDefaultSize, + wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +{ + SetLabel(_("Install VST Plugins")); // Provide visual label + SetName(_("Install VST Plugins")); // Provide audible label + Populate(); + + mAbort = false; +} + +PluginRegistrationDialog::~PluginRegistrationDialog() +{ +} + +void PluginRegistrationDialog::Populate() +{ + //------------------------- Main section -------------------- + ShuttleGui S(this, eIsCreating); + PopulateOrExchange(S); + // ----------------------- End of main section -------------- +} + +/// Defines the dialog and does data exchange with it. +void PluginRegistrationDialog::PopulateOrExchange(ShuttleGui &S) +{ + wxImageList * pImageList = new wxImageList( 16, 16 ); + +#define SHOW_UNCHECKED (0) +#define SHOW_CHECKED (1) +#define SHOW_ARROW (2) + + pImageList->Add(wxIcon(unchecked_xpm)); + pImageList->Add(wxIcon(checked_xpm)); + pImageList->Add(wxIcon(arrow_xpm)); + + S.StartVerticalLay(true); + { + /*i18n-hint: The dialog shows a list of plugins with check-boxes + beside each one.*/ + S.StartStatic(_("&Select Plugins to Install"), true); + { + S.SetStyle(wxSUNKEN_BORDER | wxLC_REPORT | wxLC_HRULES | wxLC_VRULES ); + mPlugins = S.Id(PluginListID).AddListControlReportMode(); + mPlugins->AssignImageList( pImageList, wxIMAGE_LIST_SMALL ); + mPlugins->InsertColumn(0, _("Plugin File"), wxLIST_FORMAT_LEFT); + } + S.EndStatic(); + + S.StartHorizontalLay(wxALIGN_RIGHT, false); + { + S.SetBorder(10); + S.Id(wxID_CANCEL).AddButton(_("&Cancel")); + S.Id(wxID_OK).AddButton(_("OK"))->SetDefault(); + } + S.EndHorizontalLay(); + } + S.EndVerticalLay(); + + wxClientDC dc( this ); + + int iLen = 100; + wxSize siz; + for (int i = 0; i < (int)mFiles.GetCount(); i++) { + miState.Add( SHOW_CHECKED ); // 1 is selected. + mPlugins->InsertItem(i, mFiles[i], SHOW_CHECKED); + siz = dc.GetTextExtent( mFiles[i] ); + if( siz.GetWidth() > iLen ) + iLen = siz.GetWidth(); + } + mPlugins->SetColumnWidth(0, iLen); + mPlugins->SetSizeHints( iLen, 200 ); + Layout(); + Fit(); + SetSizeHints(GetSize()); + Center(); + +} + +void PluginRegistrationDialog::OnToggleState(wxListEvent & event) +{ + int i = event.GetIndex(); + miState[ i ] = (miState[ i ]==SHOW_CHECKED) ? SHOW_UNCHECKED : SHOW_CHECKED; // Toggle it. + mPlugins->SetItemState( i, 0 ,wxLIST_STATE_SELECTED); + mPlugins->SetItemImage( i, miState[i] ); +} + +void PluginRegistrationDialog::OnApply(wxCommandEvent & event) +{ + + size_t cnt = mFiles.GetCount(); + for (size_t i = 0; i < cnt; i++) { + wxString file = mFiles[i]; +#if 0 + int status = progress->Update(wxLongLong(i), + wxLongLong(cnt), + wxString::Format(_("Checking %s"), file.c_str())); + if (status != eProgressSuccess) { + break; + } +#endif + mPlugins->EnsureVisible( i ); + if( miState[ i ] == SHOW_CHECKED ) + { + mPlugins->SetItemImage( i, SHOW_ARROW ); + VSTEffect::ScanOnePlugin( file ); + mPlugins->SetItemImage( i, SHOW_CHECKED ); + } + } + EndModal( true ); +} + +void PluginRegistrationDialog::OnCancel(wxCommandEvent &event) +{ + EndModal(false); +} + + + + + /////////////////////////////////////////////////////////////////////////////// // // VSTEffectDialog @@ -1679,6 +1839,47 @@ void VSTEffect::Unload() } } +void VSTEffect::ScanOnePlugin( const wxString & file ) +{ + const wxChar * argv[4]; + argv[0] = PlatformCompatibility::GetExecutablePath().c_str(); + argv[1] = VSTCMDKEY; + argv[2] = file.c_str(); + argv[3] = NULL; + // ToDo: do we need a try--catch around this in case a bad plug-in + // fails? (JKC Nov09) + wxExecute((wxChar **) argv, wxEXEC_SYNC | wxEXEC_NODISABLE, NULL); +} + +void VSTEffect::ShowPluginListDialog( const wxArrayString & files ) +{ + PluginRegistrationDialog d( wxGetApp().GetTopWindow(), files ); + d.ShowModal(); +} + +void VSTEffect::ShowProgressDialog( const wxString & longest, const wxArrayString & files ) +{ + ProgressDialog *progress = new ProgressDialog(_("Scanning VST Plugins"), + longest, + pdlgHideStopButton); +// progress->SetSize(wxSize(500, -1)); + progress->CenterOnScreen(); + + size_t cnt = files.GetCount(); + for (size_t i = 0; i < cnt; i++) { + wxString file = files[i]; + int status = progress->Update(wxLongLong(i), + wxLongLong(cnt), + wxString::Format(_("Checking %s"), file.c_str())); + if (status != eProgressSuccess) { + break; + } + ScanOnePlugin( file ); + } + + delete progress; +} + /* static */ void VSTEffect::Scan() { @@ -1774,6 +1975,8 @@ void VSTEffect::Scan() #endif + files.Sort(); + // This is a hack to allow for long paths in the progress dialog. The // progress dialog should really truncate the message if it's too wide // for the dialog. @@ -1790,35 +1993,10 @@ void VSTEffect::Scan() longest = files[i]; } } - - ProgressDialog *progress = new ProgressDialog(_("Scanning VST Plugins"), - longest, - pdlgHideStopButton); -// progress->SetSize(wxSize(500, -1)); - progress->CenterOnScreen(); - - const wxChar * argv[4]; - argv[0] = PlatformCompatibility::GetExecutablePath().c_str(); - argv[1] = VSTCMDKEY; - argv[2] = NULL; - argv[3] = NULL; - - for (size_t i = 0; i < cnt; i++) { - wxString file = files[i]; - int status = progress->Update(wxLongLong(i), - wxLongLong(cnt), - wxString::Format(_("Checking %s"), file.c_str())); - if (status != eProgressSuccess) { - break; - } - - argv[2] = file.c_str(); - // ToDo: do we need a try--catch around this in case a bad plug-in - // fails? (JKC Nov09) - wxExecute((wxChar **) argv, wxEXEC_SYNC | wxEXEC_NODISABLE, NULL); - } - - delete progress; + //Choose the first for the original version which scans them all + //The second to selectively scan. + //ShowProgressDialog( longest, files ); + ShowPluginListDialog( files ); } /* static */ diff --git a/src/effects/VST/VSTEffect.h b/src/effects/VST/VSTEffect.h index ff4ffa5d2..cfd4b0f08 100644 --- a/src/effects/VST/VSTEffect.h +++ b/src/effects/VST/VSTEffect.h @@ -68,6 +68,12 @@ class VSTEffect:public Effect static void Scan(); static void Check(const wxChar *fname); + static void ScanOnePlugin( const wxString & file ); + static void ShowPluginListDialog( const wxArrayString & files ); + static void ShowProgressDialog( const wxString & longest, const wxArrayString & files ); + + + // Utility methods int GetChannels();