Audacity  3.0.3
PluginRegistrationDialog.cpp
Go to the documentation of this file.
1 /*!*********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  @file PluginRegistrationDialog.cpp
6 
7  Paul Licameli split from PluginManager.cpp
8 
9 **********************************************************************/
11 
12 #include "EffectInterface.h"
13 #include "ModuleManager.h"
14 #include "PluginManager.h"
15 #include "ShuttleGui.h"
17 #include "widgets/ProgressDialog.h"
18 
19 #include <wx/setup.h> // for wxUSE_* macros
20 #include <wx/defs.h>
21 #include <wx/dir.h>
22 #include <wx/dynlib.h>
23 #include <wx/filename.h>
24 #include <wx/listctrl.h>
25 #include <wx/radiobut.h>
26 #include <wx/wfstream.h>
27 #include <wx/utils.h>
28 
29 // ============================================================================
30 //
31 //
32 //
33 // ============================================================================
34 #if wxUSE_ACCESSIBILITY
36 
37 class CheckListAx final : public WindowAccessible
38 {
39 public:
40  CheckListAx(wxListCtrl * window);
41 
42  virtual ~ CheckListAx();
43 
44  // Retrieves the address of an IDispatch interface for the specified child.
45  // All objects must support this property.
46  wxAccStatus GetChild( int childId, wxAccessible **child ) override;
47 
48  // Gets the number of children.
49  wxAccStatus GetChildCount( int *childCount ) override;
50 
51  // Gets the default action for this object (0) or > 0 (the action for a child).
52  // Return wxACC_OK even if there is no action. actionName is the action, or the empty
53  // string if there is no action.
54  // The retrieved string describes the action that is performed on an object,
55  // not what the object does as a result. For example, a toolbar button that prints
56  // a document has a default action of "Press" rather than "Prints the current document."
57  wxAccStatus GetDefaultAction( int childId, wxString *actionName ) override;
58 
59  // Returns the description for this object or a child.
60  wxAccStatus GetDescription( int childId, wxString *description ) override;
61 
62  // Gets the window with the keyboard focus.
63  // If childId is 0 and child is NULL, no object in
64  // this subhierarchy has the focus.
65  // If this object has the focus, child should be 'this'.
66  wxAccStatus GetFocus( int *childId, wxAccessible **child ) override;
67 
68  // Returns help text for this object or a child, similar to tooltip text.
69  wxAccStatus GetHelpText( int childId, wxString *helpText ) override;
70 
71  // Returns the keyboard shortcut for this object or child.
72  // Return e.g. ALT+K
73  wxAccStatus GetKeyboardShortcut( int childId, wxString *shortcut ) override;
74 
75  // Returns the rectangle for this object (id = 0) or a child element (id > 0).
76  // rect is in screen coordinates.
77  wxAccStatus GetLocation( wxRect& rect, int elementId ) override;
78 
79  // Gets the name of the specified object.
80  wxAccStatus GetName( int childId, wxString *name ) override;
81 
82  // Returns a role constant.
83  wxAccStatus GetRole( int childId, wxAccRole *role ) override;
84 
85  // Gets a variant representing the selected children
86  // of this object.
87  // Acceptable values:
88  // - a null variant (IsNull() returns TRUE)
89  // - a list variant (GetType() == wxT("list"))
90  // - an integer representing the selected child element,
91  // or 0 if this object is selected (GetType() == wxT("long"))
92  // - a "void*" pointer to a wxAccessible child object
93  wxAccStatus GetSelections( wxVariant *selections ) override;
94 
95  // Returns a state constant.
96  wxAccStatus GetState( int childId, long* state ) override;
97 
98  // Returns a localized string representing the value for the object
99  // or child.
100  wxAccStatus GetValue( int childId, wxString *strValue ) override;
101 
102  void SetSelected( int item, bool focused = true );
103 
104 private:
105  wxListCtrl *mParent;
106  int mLastId;
107 };
108 
109 CheckListAx::CheckListAx( wxListCtrl * window )
110 : WindowAccessible( window )
111 {
112  mParent = window;
113  mLastId = -1;
114 }
115 
116 CheckListAx::~CheckListAx()
117 {
118 }
119 
120 void CheckListAx::SetSelected( int item, bool focused )
121 {
122  if (mLastId != -1)
123  {
124  NotifyEvent( wxACC_EVENT_OBJECT_SELECTIONREMOVE,
125  mParent,
126  wxOBJID_CLIENT,
127  mLastId );
128  mLastId = -1;
129  }
130 
131  if (item != -1)
132  {
133  if (focused)
134  {
135  NotifyEvent( wxACC_EVENT_OBJECT_FOCUS,
136  mParent,
137  wxOBJID_CLIENT,
138  item + 1 );
139  }
140 
141  NotifyEvent( wxACC_EVENT_OBJECT_SELECTION,
142  mParent,
143  wxOBJID_CLIENT,
144  item + 1 );
145 
146  mLastId = item + 1;
147  }
148 }
149 
150 // Retrieves the address of an IDispatch interface for the specified child.
151 // All objects must support this property.
152 wxAccStatus CheckListAx::GetChild( int childId, wxAccessible** child )
153 {
154  if( childId == wxACC_SELF )
155  {
156  *child = this;
157  }
158  else
159  {
160  *child = NULL;
161  }
162 
163  return wxACC_OK;
164 }
165 
166 // Gets the number of children.
167 wxAccStatus CheckListAx::GetChildCount( int *childCount )
168 {
169  *childCount = mParent->GetItemCount();
170 
171  return wxACC_OK;
172 }
173 
174 // Gets the default action for this object (0) or > 0 (the action for a child).
175 // Return wxACC_OK even if there is no action. actionName is the action, or the empty
176 // string if there is no action.
177 // The retrieved string describes the action that is performed on an object,
178 // not what the object does as a result. For example, a toolbar button that prints
179 // a document has a default action of "Press" rather than "Prints the current document."
180 wxAccStatus CheckListAx::GetDefaultAction( int WXUNUSED(childId), wxString *actionName )
181 {
182  actionName->clear();
183 
184  return wxACC_OK;
185 }
186 
187 // Returns the description for this object or a child.
188 wxAccStatus CheckListAx::GetDescription( int WXUNUSED(childId), wxString *description )
189 {
190  description->clear();
191 
192  return wxACC_OK;
193 }
194 
195 // Gets the window with the keyboard focus.
196 // If childId is 0 and child is NULL, no object in
197 // this subhierarchy has the focus.
198 // If this object has the focus, child should be 'this'.
199 wxAccStatus CheckListAx::GetFocus( int *childId, wxAccessible **child )
200 {
201  *childId = 0;
202  *child = this;
203 
204  return wxACC_OK;
205 }
206 
207 // Returns help text for this object or a child, similar to tooltip text.
208 wxAccStatus CheckListAx::GetHelpText( int WXUNUSED(childId), wxString *helpText )
209 {
210  helpText->clear();
211 
212  return wxACC_OK;
213 }
214 
215 // Returns the keyboard shortcut for this object or child.
216 // Return e.g. ALT+K
217 wxAccStatus CheckListAx::GetKeyboardShortcut( int WXUNUSED(childId), wxString *shortcut )
218 {
219  shortcut->clear();
220 
221  return wxACC_OK;
222 }
223 
224 // Returns the rectangle for this object (id = 0) or a child element (id > 0).
225 // rect is in screen coordinates.
226 wxAccStatus CheckListAx::GetLocation( wxRect& rect, int elementId )
227 {
228  if( elementId == wxACC_SELF )
229  {
230  rect = mParent->GetRect();
231  rect.SetPosition( mParent->GetParent()->ClientToScreen( rect.GetPosition() ) );
232  }
233  else
234  {
235  if( elementId <= mParent->GetItemCount() )
236  {
237  mParent->GetItemRect( elementId - 1, rect, wxLIST_RECT_LABEL );
238  rect.SetPosition( mParent->ClientToScreen( rect.GetPosition() ) );
239  }
240  }
241 
242  return wxACC_OK;
243 }
244 
245 // Gets the name of the specified object.
246 wxAccStatus CheckListAx::GetName( int WXUNUSED(childId), wxString *name )
247 {
248  *name = mParent->GetName();
249 
250  return wxACC_OK;
251 }
252 
253 // Returns a role constant.
254 wxAccStatus CheckListAx::GetRole( int childId, wxAccRole *role )
255 {
256  if( childId == wxACC_SELF )
257  {
258  *role = wxROLE_SYSTEM_LIST;
259  }
260  else
261  {
262  *role = wxROLE_SYSTEM_LISTITEM;
263  }
264 
265  return wxACC_OK;
266 }
267 
268 // Gets a variant representing the selected children
269 // of this object.
270 // Acceptable values:
271 // - a null variant (IsNull() returns TRUE)
272 // - a list variant (GetType() == wxT("list"))
273 // - an integer representing the selected child element,
274 // or 0 if this object is selected (GetType() == wxT("long"))
275 // - a "void*" pointer to a wxAccessible child object
276 wxAccStatus CheckListAx::GetSelections( wxVariant * WXUNUSED(selections) )
277 {
278  return wxACC_NOT_IMPLEMENTED;
279 }
280 
281 // Returns a state constant.
282 wxAccStatus CheckListAx::GetState( int childId, long *pState )
283 {
284  int flag = wxACC_STATE_SYSTEM_FOCUSABLE;
285 
286  if( childId == wxACC_SELF )
287  {
288  flag |= wxACC_STATE_SYSTEM_FOCUSED;
289  }
290  else
291  {
292  wxListItem item;
293 
294  item.SetId( childId - 1 );
295  item.SetState( wxLIST_STATE_FOCUSED | wxLIST_STATE_SELECTED );
296  item.SetMask( wxLIST_MASK_STATE );
297 
298  if( mParent->GetItem( item ) )
299  {
300  flag |= wxACC_STATE_SYSTEM_SELECTABLE;
301 
302  long state = item.GetState();
303 
304  if( state & wxLIST_STATE_FOCUSED )
305  {
306  flag |= wxACC_STATE_SYSTEM_FOCUSED;
307  }
308 
309  if( state & wxLIST_STATE_SELECTED )
310  {
311  flag |= wxACC_STATE_SYSTEM_SELECTED;
312  }
313  }
314  }
315 
316  *pState = flag;
317 
318  return wxACC_OK;
319 }
320 
321 // Returns a localized string representing the value for the object
322 // or child.
323 wxAccStatus CheckListAx::GetValue( int childId, wxString *strValue )
324 {
325  if( childId == 0 )
326  {
327  return wxACC_OK;
328  }
329  else
330  {
331  *strValue = mParent->GetItemText( childId - 1 );
332  }
333 
334  return wxACC_OK;
335 }
336 
337 #endif
338 enum
339 {
343 
345 };
346 
347 enum
348 {
349  ID_ShowAll = 10000,
358 };
359 
360 enum
361 {
365 
366  COL_COUNT
367 };
368 
369 BEGIN_EVENT_TABLE(PluginRegistrationDialog, wxDialogWrapper)
370  EVT_LIST_COL_CLICK(ID_List, PluginRegistrationDialog::OnSort)
382 
384 : wxDialogWrapper(parent,
385  wxID_ANY,
386  XO("Manage Plug-ins"),
387  wxDefaultPosition, wxDefaultSize,
388  wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
389 {
390  mType = type;
391  mEffects = NULL;
392  SetName();
393 
394  mStates.resize(STATE_COUNT);
395  mStates[STATE_Enabled] = _("Enabled");
396  mStates[STATE_Disabled] = _("Disabled");
397  mStates[STATE_New] = _("New");
398 
399  mSortColumn = COL_Name;
400  mSortDirection = 1;
401 
402  Populate();
403 
404  DoSort( mSortColumn );
405 }
406 
408 {
409  //------------------------- Main section --------------------
410  ShuttleGui S(this, eIsCreating);
412  // ----------------------- End of main section --------------
413 }
414 
417 {
418  S.StartVerticalLay(true);
419  {
420  /*i18n-hint: The dialog shows a list of plugins with check-boxes
421  beside each one.*/
422 // S.StartStatic(XO("Effects"), true);
423  S.StartVerticalLay();
424  {
425  S.StartHorizontalLay(wxEXPAND, 0);
426  {
427  S.StartHorizontalLay(wxALIGN_LEFT, 0);
428  {
429  S.AddPrompt(XXO("Select effects, click the Enable or Disable button, then click OK."));
430  }
431  S.EndHorizontalLay();
432 
433  S.StartHorizontalLay(wxCENTER, 1);
434  {
435  S.AddSpace(1);
436  }
437  S.EndHorizontalLay();
438 
439  S.StartHorizontalLay(wxALIGN_NOT | wxALIGN_LEFT, 0);
440  {
441  wxRadioButton *rb;
442 
443  /* i18n-hint: This is before radio buttons selecting which effects to show */
444  S.AddPrompt(XXO("Show:"));
445  rb = S.Id(ID_ShowAll)
446  /* i18n-hint: Radio button to show all effects */
447  .Name(XO("Show all"))
448  /* i18n-hint: Radio button to show all effects */
449  .AddRadioButton(XXO("&All"));
450 #if wxUSE_ACCESSIBILITY
451  // so that name can be set on a standard control
452  rb->SetAccessible(safenew WindowAccessible(rb));
453 #endif
454 
455  rb = S.Id(ID_ShowDisabled)
456  /* i18n-hint: Radio button to show just the currently disabled effects */
457  .Name(XO("Show disabled"))
458  /* i18n-hint: Radio button to show just the currently disabled effects */
459  .AddRadioButtonToGroup(XXO("D&isabled"));
460 #if wxUSE_ACCESSIBILITY
461  // so that name can be set on a standard control
462  rb->SetAccessible(safenew WindowAccessible(rb));
463 #endif
464 
465  rb = S.Id(ID_ShowEnabled)
466  /* i18n-hint: Radio button to show just the currently enabled effects */
467  .Name(XO("Show enabled"))
468  /* i18n-hint: Radio button to show just the currently enabled effects */
469  .AddRadioButtonToGroup(XXO("E&nabled"));
470 #if wxUSE_ACCESSIBILITY
471  // so that name can be set on a standard control
472  rb->SetAccessible(safenew WindowAccessible(rb));
473 #endif
474 
475  rb = S.Id(ID_ShowNew)
476  /* i18n-hint: Radio button to show just the newly discovered effects */
477  .Name(XO("Show new"))
478  /* i18n-hint: Radio button to show just the newly discovered effects */
479  .AddRadioButtonToGroup(XXO("Ne&w"));
480 #if wxUSE_ACCESSIBILITY
481  // so that name can be set on a standard control
482  rb->SetAccessible(safenew WindowAccessible(rb));
483 #endif
484  }
485  S.EndHorizontalLay();
486  }
487  S.EndHorizontalLay();
488 
489  mEffects = S.Id(ID_List)
490  .Style(wxSUNKEN_BORDER | wxLC_REPORT | wxLC_HRULES | wxLC_VRULES )
491  .ConnectRoot(wxEVT_KEY_DOWN,
493  .AddListControlReportMode({ XO("Name"), XO("State"), XO("Path") });
494 #if wxUSE_ACCESSIBILITY
495  mEffects->SetAccessible(mAx = safenew CheckListAx(mEffects));
496 #endif
497 
498  S.StartHorizontalLay(wxALIGN_LEFT | wxEXPAND, 0);
499  {
500  S.Id(ID_SelectAll).AddButton(XXO("&Select All"));
501  S.Id(ID_ClearAll).AddButton(XXO("C&lear All"));
502 
503  S.StartHorizontalLay(wxALIGN_CENTER);
504  {
505  S.AddSpace(1);
506  }
507  S.EndHorizontalLay();
508 
509  S.Id(ID_Enable).AddButton(XXO("&Enable"));
510  S.Id(ID_Disable).AddButton(XXO("&Disable"));
511  }
512  S.EndHorizontalLay();
513  }
514 // S.EndStatic();
515  S.EndVerticalLay();
516 
518  }
519  S.EndVerticalLay();
520 
521  std::vector<int> colWidths;
522  for (int i = 0, cnt = mEffects->GetColumnCount(); i < cnt; i++)
523  {
524  colWidths.push_back(0);
525  }
526 
527  for (int i = 0, cnt = mStates.size(); i < cnt; i++)
528  {
529  int x;
530  mEffects->GetTextExtent(mStates[i], &x, NULL);
531  colWidths[COL_State] = wxMax(colWidths[COL_State], x + 4); // 2 pixel margin on each side
532  }
533 
535  for (auto &plug : pm.AllPlugins()) {
536  PluginType plugType = plug.GetPluginType();
537  if (plugType != PluginTypeEffect && plugType != PluginTypeStub)
538  continue;
539 
540  const auto &path = plug.GetPath();
541  ItemData & item = mItems[path]; // will create NEW entry
542  item.plugs.push_back(&plug);
543  item.path = path;
544  item.state = plug.IsEnabled() ? STATE_Enabled : STATE_Disabled;
545  item.valid = plug.IsValid();
546 
547  if (plugType == PluginTypeEffect)
548  {
549  item.name = plug.GetSymbol().Translation();
550  }
551  // This is not right and will not work when other plugin types are added.
552  // But it's presumed that the plugin manager dialog will be fully developed
553  // by then.
554  else if (plugType == PluginTypeStub)
555  {
556  wxFileName fname { path };
557  item.name = fname.GetName().Trim(false).Trim(true);
558  if (!item.valid)
559  {
560  item.state = STATE_New;
561  }
562  }
563 
564  int x;
565  mEffects->GetTextExtent(item.name, &x, NULL);
566  colWidths[COL_Name] = wxMax(colWidths[COL_Name], x);
567 
568  mEffects->GetTextExtent(item.path, &x, NULL);
569  if (x > colWidths[COL_Path])
570  {
571  mLongestPath = item.path;
572  }
573  colWidths[COL_Path] = wxMax(colWidths[COL_Path], x);
574  }
575 
576  wxRect r = wxGetClientDisplayRect();
577 
578  int maxW = 0;
579  for (int i = 0, cnt = mEffects->GetColumnCount(); i < cnt; i++)
580  {
581  int w = colWidths[i] + /* fudge */ 10;
582  mEffects->SetColumnWidth(i, w);
583  maxW += w;
584  }
585 
586  // Keep dialog from getting too wide
587  int w = r.GetWidth() - (GetClientSize().GetWidth() - mEffects->GetSize().GetWidth());
588  mEffects->SetMinSize({ std::min(maxW, w), 200 });
589  mEffects->SetMaxSize({ w, -1 });
590 
592 
593  Layout();
594  Fit();
595 
596  wxSize sz = GetSize();
597  sz.SetWidth(wxMin(sz.GetWidth(), r.GetWidth()));
598  sz.SetHeight(wxMin(sz.GetHeight(), r.GetHeight()));
599  SetMinSize(sz);
600 
601  // Parent window is usually not there yet, so centre on screen rather than on parent.
602  CenterOnScreen();
603 
604  if (mEffects->GetItemCount() > 0)
605  {
606  // Make sure first item is selected/focused.
607  mEffects->SetFocus();
608  mEffects->SetItemState(0, wxLIST_STATE_FOCUSED | wxLIST_STATE_SELECTED, wxLIST_STATE_FOCUSED | wxLIST_STATE_SELECTED);
609 #if wxUSE_ACCESSIBILITY
610  mAx->SetSelected(0);
611 #endif
612  }
613 
614 }
615 
617 {
618  mFilter = filter;
619 
620  mEffects->DeleteAllItems();
621 
622  int i = 0;
623  for (ItemDataMap::iterator iter = mItems.begin(); iter != mItems.end(); ++iter)
624  {
625  ItemData & item = iter->second;
626  bool add = false;
627 
628  switch (mFilter)
629  {
630  case ID_ShowAll:
631  add = true;
632  break;
633  case ID_ShowNew:
634  if (item.state == STATE_New)
635  {
636  add = true;
637  }
638  break;
639  case ID_ShowEnabled:
640  if (item.state == STATE_Enabled)
641  {
642  add = true;
643  }
644  break;
645  case ID_ShowDisabled:
646  if (item.state == STATE_Disabled)
647  {
648  add = true;
649  }
650  break;
651  }
652 
653  if (add)
654  {
655  mEffects->InsertItem(i, item.name);
656  mEffects->SetItem(i, COL_State, mStates[item.state]);
657  mEffects->SetItem(i, COL_Path, item.path);
658  mEffects->SetItemPtrData(i, (wxUIntPtr) &item);
659 
660  ++i;
661  }
662  }
663 
664  mEffects->SortItems(SortCompare, (wxUIntPtr) this);
665 
666  if (mEffects->GetItemCount() > 0)
667  {
668  // Make sure first item is selected/focused.
669 // mEffects->SetFocus();
670  mEffects->SetItemState(0, wxLIST_STATE_FOCUSED|wxLIST_STATE_SELECTED, wxLIST_STATE_FOCUSED|wxLIST_STATE_SELECTED);
671 #if wxUSE_ACCESSIBILITY
672  mAx->SetSelected(0, false);
673 #endif
674  }
675 }
676 
677 void PluginRegistrationDialog::SetState(int i, bool toggle, bool state)
678 {
679  wxListItem li;
680 
681  li.m_mask = wxLIST_MASK_DATA;
682  li.m_itemId = i;
683 
684  mEffects->GetItem(li);
685 
686  ItemData *item = (ItemData *) li.m_data;
687 
688  // If changing the state of a "New" (stub) entry, then we mark it as valid
689  // since it will either be registered if "Enabled" or ignored if "Disabled".
690  if (item->state == STATE_New)
691  {
692  item->valid = true;
693  }
694 
695  if (toggle)
696  {
698  }
699  else
700  {
701  item->state = state;
702  }
703 
704  if (mFilter == ID_ShowNew && item->state != STATE_New)
705  {
706  mEffects->DeleteItem(i);
707  }
708  else if (mFilter == ID_ShowDisabled && item->state != STATE_Disabled)
709  {
710  mEffects->DeleteItem(i);
711  }
712  else if (mFilter == ID_ShowEnabled && item->state != STATE_Enabled)
713  {
714  mEffects->DeleteItem(i);
715  }
716  else
717  {
718  mEffects->SetItem(i, COL_State, mStates[item->state]);
719 #if wxUSE_ACCESSIBILITY
720  mAx->SetSelected(i);
721 #endif
722  }
723 }
724 
725 int wxCALLBACK PluginRegistrationDialog::SortCompare(wxIntPtr item1, wxIntPtr item2, wxIntPtr sortData)
726 {
728  ItemData *i1 = (ItemData *) item1;
729  ItemData *i2 = (ItemData *) item2;
730 
731  return dlg->SortCompare(i1, i2);
732 }
733 
735 {
736  // This function is a three-valued comparator
737 
738  wxString *str1;
739  wxString *str2;
740 
741  switch (mSortColumn)
742  {
743  case COL_Name:
744  str1 = &item1->name;
745  str2 = &item2->name;
746  break;
747  case COL_State:
748  str1 = &mStates[item1->state];
749  str2 = &mStates[item2->state];
750  break;
751  case COL_Path:
752  str1 = &item1->path;
753  str2 = &item2->path;
754  break;
755  default:
756  return 0;
757  }
758 
759  return str2->CmpNoCase(*str1) * mSortDirection;
760 }
761 
763 {
764  // Go and show the relevant items.
765  RegenerateEffectsList(evt.GetId());
766 }
767 
768 void PluginRegistrationDialog::OnSort(wxListEvent & evt)
769 {
770  int col = evt.GetColumn();
771  DoSort( col );
772 }
773 
775 {
776  if (col != mSortColumn)
777  {
778  mSortDirection = 1;
779  }
780  else
781  {
782  mSortDirection *= -1;
783  }
784 
785  mSortColumn = col;
786  mEffects->SortItems(SortCompare, (wxUIntPtr) this);
787 
788  // Without a refresh, wxMac doesn't redisplay the list properly after a sort
789  mEffects->Refresh();
790 }
791 
793 {
794  switch (evt.GetKeyCode())
795  {
796  case WXK_SPACE:
797  {
798  int item = mEffects->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
799  if (item != wxNOT_FOUND)
800  {
801  SetState(item, true);
802  }
803  }
804  break;
805 
806  case WXK_RETURN:
807  // Don't know why wxListCtrls prevent default dialog action,
808  // but they do, so handle it.
809  EmulateButtonClickIfPresent(GetAffirmativeId());
810  break;
811 
812  default:
813  evt.Skip();
814  break;
815  }
816 }
817 
818 void PluginRegistrationDialog::OnSelectAll(wxCommandEvent & WXUNUSED(evt))
819 {
820  for (int i = 0, cnt = mEffects->GetItemCount(); i < cnt; i++)
821  {
822  mEffects->SetItemState(i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
823  }
824 }
825 
826 void PluginRegistrationDialog::OnClearAll(wxCommandEvent & WXUNUSED(evt))
827 {
828  for (int i = 0, cnt = mEffects->GetItemCount(); i < cnt; i++)
829  {
830  mEffects->SetItemState(i, 0, wxLIST_STATE_SELECTED);
831  }
832 }
833 
834 void PluginRegistrationDialog::OnEnable(wxCommandEvent & WXUNUSED(evt))
835 {
836  std::vector<long> items;
837 
838  {
839  long i = mEffects->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
840  while (i != wxNOT_FOUND)
841  {
842  items.insert(items.begin(), i);
843  i = mEffects->GetNextItem(i, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
844  }
845  }
846 
847  for (size_t i = 0, cnt = items.size(); i < cnt; i++)
848  {
849  SetState(items[i], false, STATE_Enabled);
850  }
851 }
852 
853 void PluginRegistrationDialog::OnDisable(wxCommandEvent & WXUNUSED(evt))
854 {
855  std::vector<long> items;
856 
857  {
858  long i = mEffects->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
859  while (i != wxNOT_FOUND)
860  {
861  items.insert(items.begin(), i);
862  i = mEffects->GetNextItem(i, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
863  }
864  }
865 
866  for (size_t i = 0, cnt = items.size(); i < cnt; i++)
867  {
868  SetState(items[i], false, STATE_Disabled);
869  }
870 }
871 
872 void PluginRegistrationDialog::OnOK(wxCommandEvent & WXUNUSED(evt))
873 {
876 
877  int enableCount = 0;
878  for (ItemDataMap::iterator iter = mItems.begin(); iter != mItems.end(); ++iter)
879  {
880  ItemData & item = iter->second;
881  wxString path = item.path;
882 
883  if (item.state == STATE_Enabled && item.plugs[0]->GetPluginType() == PluginTypeStub)
884  {
885  enableCount++;
886  }
887  }
888 
889  wxString last3 = mLongestPath + wxT("\n") +
890  mLongestPath + wxT("\n") +
891  mLongestPath + wxT("\n");
892 
893  auto msg = XO("Enabling effects or commands:\n\n%s").Format( last3 );
894 
895  // Make sure the progress dialog is deleted before we call EndModal() or
896  // we will leave the project window in an unusable state on OSX.
897  // See bug #1192.
898  {
899  ProgressDialog progress{
900  Verbatim( GetTitle() ), msg, pdlgHideStopButton };
901  progress.CenterOnParent();
902 
903  int i = 0;
904  for (ItemDataMap::iterator iter = mItems.begin(); iter != mItems.end(); ++iter)
905  {
906  ItemData & item = iter->second;
907  wxString path = item.path;
908 
909  if (item.state == STATE_Enabled && item.plugs[0]->GetPluginType() == PluginTypeStub)
910  {
911  last3 = last3.AfterFirst(wxT('\n')) + item.path + wxT("\n");
912  auto status = progress.Update(++i, enableCount,
913  XO("Enabling effect or command:\n\n%s").Format( last3 ));
914  if (status == ProgressResult::Cancelled)
915  {
916  break;
917  }
918 
919  TranslatableString errMsgs;
920 
921  // Try to register the plugin via each provider until one succeeds
922  for (size_t j = 0, cntj = item.plugs.size(); j < cntj; j++)
923  {
924  TranslatableString errMsg;
925  if (mm.RegisterEffectPlugin(item.plugs[j]->GetProviderID(), path,
926  errMsg))
927  {
928  for (auto plug : item.plugs)
929  pm.UnregisterPlugin(
930  plug->GetProviderID() + wxT("_") + path);
931  // Bug 1893. We've found a provider that works.
932  // Error messages from any that failed are no longer useful.
933  errMsgs = {};
934  break;
935  }
936  else
937  {
938  if (!errMsgs.empty())
939  errMsgs.Join( errMsg, '\n' );
940  else
941  errMsgs = errMsg;
942  }
943  }
944  if (!errMsgs.empty())
946  XO("Effect or Command at %s failed to register:\n%s")
947  .Format( path, errMsgs ) );
948  }
949  else if (item.state == STATE_New) {
950  for (auto plug : item.plugs)
951  plug->SetValid(false);
952  }
953  else if (item.state != STATE_New) {
954  for (auto plug : item.plugs) {
955  plug->SetEnabled(item.state == STATE_Enabled);
956  plug->SetValid(item.valid);
957  }
958  }
959  }
960 
961  pm.Save();
962  }
963 
964  EndModal(wxID_OK);
965 }
966 
967 void PluginRegistrationDialog::OnCancel(wxCommandEvent & WXUNUSED(evt))
968 {
969  EndModal(wxID_CANCEL);
970 }
EVT_BUTTON
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
PluginRegistrationDialog::Populate
void Populate()
Definition: PluginRegistrationDialog.cpp:407
eIsCreating
@ eIsCreating
Definition: ShuttleGui.h:38
PluginRegistrationDialog::ItemData::valid
bool valid
Definition: PluginRegistrationDialog.h:37
TranslatableString::empty
bool empty() const
Definition: TranslatableString.h:72
PluginTypeEffect
@ PluginTypeEffect
Definition: PluginManager.h:35
PluginRegistrationDialog::SortCompare
static int wxCALLBACK SortCompare(wxIntPtr item1, wxIntPtr item2, wxIntPtr sortData)
Definition: PluginRegistrationDialog.cpp:725
ShuttleGuiBase::StartVerticalLay
void StartVerticalLay(int iProp=1)
Definition: ShuttleGui.cpp:1184
PluginManager::Save
void Save()
Save to preferences.
Definition: PluginManager.cpp:1210
ID_SelectAll
@ ID_SelectAll
Definition: PluginRegistrationDialog.cpp:355
STATE_COUNT
@ STATE_COUNT
Definition: PluginRegistrationDialog.cpp:344
AudacityMessageBox
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
Definition: AudacityMessageBox.cpp:17
ID_ShowAll
@ ID_ShowAll
Definition: PluginRegistrationDialog.cpp:349
ID_Disable
@ ID_Disable
Definition: PluginRegistrationDialog.cpp:357
PluginRegistrationDialog::ItemData::name
wxString name
Definition: PluginRegistrationDialog.h:34
PluginRegistrationDialog::mItems
ItemDataMap mItems
Definition: PluginRegistrationDialog.h:69
flag
static std::once_flag flag
Definition: WaveformView.cpp:1119
PluginRegistrationDialog::ItemData::state
int state
Definition: PluginRegistrationDialog.h:36
PluginRegistrationDialog::OnChangedVisibility
void OnChangedVisibility(wxCommandEvent &evt)
Definition: PluginRegistrationDialog.cpp:762
EffectInterface.h
ModuleManager.h
pdlgHideStopButton
@ pdlgHideStopButton
Definition: ProgressDialog.h:38
Format
Abstract base class used in importing a file.
ShuttleGuiBase::AddRadioButtonToGroup
wxRadioButton * AddRadioButtonToGroup(const TranslatableString &Prompt, int selector=1, int initValue=0)
Definition: ShuttleGui.cpp:574
ShuttleGui::AddSpace
wxSizerItem * AddSpace(int width, int height, int prop=0)
Definition: ShuttleGui.cpp:2459
RefreshCode::Cancelled
@ Cancelled
Definition: RefreshCode.h:23
XO
#define XO(s)
Definition: Internat.h:31
ModuleManager::RegisterEffectPlugin
bool RegisterEffectPlugin(const PluginID &provider, const PluginPath &path, TranslatableString &errMsg)
Definition: ModuleManager.cpp:490
PluginRegistrationDialog::OnSort
void OnSort(wxListEvent &evt)
Definition: PluginRegistrationDialog.cpp:768
ProgressDialog.h
COL_State
@ COL_State
Definition: PluginRegistrationDialog.cpp:363
PluginRegistrationDialog::ItemData
Definition: PluginRegistrationDialog.h:32
PluginRegistrationDialog
Definition: PluginRegistrationDialog.h:25
ID_ClearAll
@ ID_ClearAll
Definition: PluginRegistrationDialog.cpp:354
PluginRegistrationDialog::OnDisable
void OnDisable(wxCommandEvent &evt)
Definition: PluginRegistrationDialog.cpp:853
PluginRegistrationDialog::mSortDirection
int mSortDirection
Definition: PluginRegistrationDialog.h:72
ShuttleGui::Id
ShuttleGui & Id(int id)
Definition: ShuttleGui.cpp:2274
PluginType
PluginType
Definition: PluginManager.h:32
COL_Path
@ COL_Path
Definition: PluginRegistrationDialog.cpp:364
PluginRegistrationDialog::ItemData::plugs
std::vector< PluginDescriptor * > plugs
Definition: PluginRegistrationDialog.h:33
ShuttleGui::Style
ShuttleGui & Style(long iStyle)
Definition: ShuttleGui.h:727
COL_Name
@ COL_Name
Definition: PluginRegistrationDialog.cpp:362
PluginRegistrationDialog.h
XXO
#define XXO(s)
Definition: Internat.h:44
eCancelButton
@ eCancelButton
Definition: ShuttleGui.h:601
ShuttleGuiBase::EndHorizontalLay
void EndHorizontalLay()
Definition: ShuttleGui.cpp:1177
ModuleManager
Definition: ModuleManager.h:71
ProgressDialog
ProgressDialog Class.
Definition: ProgressDialog.h:51
PluginRegistrationDialog::OnEnable
void OnEnable(wxCommandEvent &evt)
Definition: PluginRegistrationDialog.cpp:834
PluginRegistrationDialog::OnListChar
void OnListChar(wxKeyEvent &evt)
Definition: PluginRegistrationDialog.cpp:792
ShuttleGuiBase::StartHorizontalLay
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
Definition: ShuttleGui.cpp:1167
PluginManager.h
ShuttleGuiBase::EndVerticalLay
void EndVerticalLay()
Definition: ShuttleGui.cpp:1203
PluginRegistrationDialog::OnCancel
void OnCancel(wxCommandEvent &evt)
Definition: PluginRegistrationDialog.cpp:967
ModuleManager::Get
static ModuleManager & Get()
Definition: ModuleManager.cpp:395
PluginRegistrationDialog::mEffects
wxListCtrl * mEffects
Definition: PluginRegistrationDialog.h:76
ID_Enable
@ ID_Enable
Definition: PluginRegistrationDialog.cpp:356
name
const TranslatableString name
Definition: Distortion.cpp:98
PluginRegistrationDialog::mFilter
int mFilter
Definition: PluginRegistrationDialog.h:66
STATE_Enabled
@ STATE_Enabled
Definition: PluginRegistrationDialog.cpp:340
STATE_New
@ STATE_New
Definition: PluginRegistrationDialog.cpp:342
WindowAccessible
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
ID_ShowEnabled
@ ID_ShowEnabled
Definition: PluginRegistrationDialog.cpp:350
ShuttleGuiBase::AddRadioButton
wxRadioButton * AddRadioButton(const TranslatableString &Prompt, int selector=0, int initValue=0)
Definition: ShuttleGui.cpp:568
PluginManager::UnregisterPlugin
void UnregisterPlugin(const PluginID &ID)
Definition: PluginManager.cpp:1434
PluginRegistrationDialog::DoSort
void DoSort(int col)
Definition: PluginRegistrationDialog.cpp:774
ShuttleGui.h
ShuttleGuiBase::AddButton
wxButton * AddButton(const TranslatableString &Text, int PositionFlags=wxALIGN_CENTRE, bool setDefault=false)
Definition: ShuttleGui.cpp:360
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
PluginRegistrationDialog::PopulateOrExchange
void PopulateOrExchange(ShuttleGui &S)
Defines the dialog and does data exchange with it.
Definition: PluginRegistrationDialog.cpp:416
ShuttleGui::Name
ShuttleGui & Name(const TranslatableString &name)
Definition: ShuttleGui.h:663
ID_ShowNew
@ ID_ShowNew
Definition: PluginRegistrationDialog.cpp:352
wxDialogWrapper
Definition: wxPanelWrapper.h:81
PluginManager::Get
static PluginManager & Get()
Definition: PluginManager.cpp:695
PluginRegistrationDialog::mSortColumn
int mSortColumn
Definition: PluginRegistrationDialog.h:71
WindowAccessible.h
eOkButton
@ eOkButton
Definition: ShuttleGui.h:600
PluginRegistrationDialog::ItemData::path
PluginPath path
Definition: PluginRegistrationDialog.h:35
PluginManager
PluginManager maintains a list of all plug ins. That covers modules, effects, generators,...
Definition: PluginManager.h:174
PluginManager::AllPlugins
Range AllPlugins()
Definition: PluginManager.h:280
_
#define _(s)
Definition: Internat.h:75
PluginRegistrationDialog::OnSelectAll
void OnSelectAll(wxCommandEvent &evt)
Definition: PluginRegistrationDialog.cpp:818
ShuttleGui::ConnectRoot
auto ConnectRoot(wxEventTypeTag< Tag > eventType, void(Handler::*func)(Argument &)) -> typename std::enable_if< std::is_base_of< Argument, Tag >::value, ShuttleGui & >::type
Definition: ShuttleGui.h:699
AudacityMessageBox.h
PluginRegistrationDialog::mStates
wxArrayString mStates
Definition: PluginRegistrationDialog.h:68
ID_List
@ ID_List
Definition: PluginRegistrationDialog.cpp:353
Verbatim
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
Definition: TranslatableString.h:321
ShuttleGui::AddStandardButtons
void AddStandardButtons(long buttons=eOkButton|eCancelButton, wxWindow *extra=NULL)
Definition: ShuttleGui.cpp:2444
PluginRegistrationDialog::mLongestPath
PluginPath mLongestPath
Definition: PluginRegistrationDialog.h:74
PluginRegistrationDialog::RegenerateEffectsList
void RegenerateEffectsList(int iShowWhat)
Definition: PluginRegistrationDialog.cpp:616
ID_ShowDisabled
@ ID_ShowDisabled
Definition: PluginRegistrationDialog.cpp:351
ShuttleGuiBase::AddPrompt
void AddPrompt(const TranslatableString &Prompt, int wrapWidth=0)
Right aligned text string.
Definition: ShuttleGui.cpp:238
PluginTypeStub
@ PluginTypeStub
Definition: PluginManager.h:34
TranslatableString::Join
TranslatableString & Join(TranslatableString arg, const wxString &separator={}) &
Append another translatable string.
Definition: TranslatableString.cpp:124
EffectType
EffectType
Definition: EffectInterface.h:55
safenew
#define safenew
Definition: MemoryX.h:10
PluginRegistrationDialog::OnClearAll
void OnClearAll(wxCommandEvent &evt)
Definition: PluginRegistrationDialog.cpp:826
END_EVENT_TABLE
END_EVENT_TABLE()
COL_COUNT
@ COL_COUNT
Definition: PluginRegistrationDialog.cpp:366
ShuttleGui
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:631
STATE_Disabled
@ STATE_Disabled
Definition: PluginRegistrationDialog.cpp:341
PluginRegistrationDialog::SetState
void SetState(int i, bool toggle, bool state=true)
Definition: PluginRegistrationDialog.cpp:677
PluginRegistrationDialog::OnOK
void OnOK(wxCommandEvent &evt)
Definition: PluginRegistrationDialog.cpp:872