mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-03 17:19:43 +02:00
This brings the builtin, LV2, and VAMP effects inline with the Audio Units, LADSPA, and VST effects. All effects now share a common UI. This gives all effects (though not implemented for all): User and factory preset capability Preset import/export capability Shared or private configuration options Builtin effects can now be migrated to RTP, depending on algorithm. LV2 effects now support graphical interfaces if the plugin supplies one. Nyquist prompt enhanced to provide some features of the Nyquist Workbench. It may not look like it, but this was a LOT of work, so trust me, there WILL be problems and everything effect related should be suspect. Keep a sharp eye (or two) open.
1738 lines
47 KiB
C++
1738 lines
47 KiB
C++
/**********************************************************************
|
|
|
|
NyqBench.cpp
|
|
|
|
Leland Lucius
|
|
|
|
**********************************************************************/
|
|
|
|
#include "Audacity.h"
|
|
|
|
#include <wx/defs.h>
|
|
|
|
#include <wx/aboutdlg.h>
|
|
#include <wx/filedlg.h>
|
|
#include <wx/font.h>
|
|
#include <wx/fontdlg.h>
|
|
#include <wx/settings.h>
|
|
#include <wx/sizer.h>
|
|
#include <wx/splitter.h>
|
|
#include <wx/statbox.h>
|
|
#include <wx/textctrl.h>
|
|
#include <wx/toolbar.h>
|
|
|
|
#include "AudacityApp.h"
|
|
#include "AudioIO.h"
|
|
#include "LabelTrack.h"
|
|
#include "ModuleManager.h"
|
|
#include "Prefs.h"
|
|
#include "Project.h"
|
|
#include "ShuttleGui.h"
|
|
#include "effects/EffectManager.h"
|
|
#include "effects/nyquist/Nyquist.h"
|
|
#include "../images/AudacityLogo.xpm"
|
|
|
|
#include "NyqBench.h"
|
|
|
|
#include <iostream>
|
|
#include <ostream>
|
|
#include <sstream>
|
|
|
|
//
|
|
// Images are from the Tango Icon Gallery
|
|
// http://tango.freedesktop.org/Tango_Icon_Gallery
|
|
//
|
|
#include "images/document-new-small.xpm"
|
|
#include "images/document-open-small.xpm"
|
|
#include "images/document-save-as-small.xpm"
|
|
#include "images/document-save-small.xpm"
|
|
#include "images/edit-clear-small.xpm"
|
|
#include "images/edit-copy-small.xpm"
|
|
#include "images/edit-cut-small.xpm"
|
|
#include "images/edit-delete-small.xpm"
|
|
#include "images/edit-find-small.xpm"
|
|
#include "images/edit-paste-small.xpm"
|
|
#include "images/edit-redo-small.xpm"
|
|
#include "images/edit-select-all-small.xpm"
|
|
#include "images/edit-undo-small.xpm"
|
|
#include "images/go-top-small.xpm"
|
|
#include "images/go-up-small.xpm"
|
|
#include "images/go-previous-small.xpm"
|
|
#include "images/go-next-small.xpm"
|
|
#include "images/system-search-small.xpm"
|
|
#include "images/media-playback-start-small.xpm"
|
|
#include "images/media-playback-stop-small.xpm"
|
|
|
|
#include "images/document-new-large.xpm"
|
|
#include "images/document-open-large.xpm"
|
|
#include "images/document-save-as-large.xpm"
|
|
#include "images/document-save-large.xpm"
|
|
#include "images/edit-clear-large.xpm"
|
|
#include "images/edit-copy-large.xpm"
|
|
#include "images/edit-cut-large.xpm"
|
|
#include "images/edit-delete-large.xpm"
|
|
#include "images/edit-find-large.xpm"
|
|
#include "images/edit-paste-large.xpm"
|
|
#include "images/edit-redo-large.xpm"
|
|
#include "images/edit-select-all-large.xpm"
|
|
#include "images/edit-undo-large.xpm"
|
|
#include "images/go-top-large.xpm"
|
|
#include "images/go-up-large.xpm"
|
|
#include "images/go-previous-large.xpm"
|
|
#include "images/go-next-large.xpm"
|
|
#include "images/system-search-large.xpm"
|
|
#include "images/media-playback-start-large.xpm"
|
|
#include "images/media-playback-stop-large.xpm"
|
|
|
|
/*
|
|
There are several functions that can be used in a GUI module.
|
|
|
|
//#define versionFnName "GetVersionString"
|
|
If the version is wrong, the module will be rejected.
|
|
That is it will be loaded and then unloaded.
|
|
|
|
//#define ModuleDispatchName "ModuleDispatch"
|
|
The most useful function. See the example in this
|
|
file. It has several cases/options in it.
|
|
|
|
//#define scriptFnName "RegScriptServerFunc"
|
|
This function is run from a non gui thread. It was originally
|
|
created for the benefit of mod-script-pipe.
|
|
|
|
//#define mainPanelFnName "MainPanelFunc"
|
|
This function is the hijacking function, to take over Audacity
|
|
and replace the main project window with our own wxFrame.
|
|
|
|
*/
|
|
|
|
extern "C"
|
|
{
|
|
static NyqBench *gBench = NULL;
|
|
|
|
#ifdef _MSC_VER
|
|
#define DLL_API _declspec(dllexport)
|
|
#else
|
|
#define DLL_API __attribute__ ((visibility("default")))
|
|
#endif
|
|
|
|
extern DLL_API const wxChar * GetVersionString();
|
|
// GetVersionString
|
|
// REQUIRED for the module to be accepted by Audacity.
|
|
// Without it Audacity will see a version number mismatch.
|
|
const wxChar * GetVersionString()
|
|
{
|
|
// For now, the versions must match exactly for Audacity to
|
|
// agree to load the module.
|
|
return AUDACITY_VERSION_STRING;
|
|
}
|
|
|
|
extern int DLL_API ModuleDispatch(ModuleDispatchTypes type);
|
|
// ModuleDispatch
|
|
// is called by Audacity to initialize/terminmate the module,
|
|
// and ask if it has anything for the menus.
|
|
int ModuleDispatch(ModuleDispatchTypes type){
|
|
switch (type){
|
|
case AppInitialized:{
|
|
wxASSERT(gBench == NULL);
|
|
gBench = new NyqBench(NULL);
|
|
}
|
|
break;
|
|
case AppQuiting: {
|
|
wxASSERT(gBench != NULL);
|
|
if (gBench) {
|
|
delete gBench;
|
|
gBench = NULL;
|
|
}
|
|
}
|
|
break;
|
|
case ProjectInitialized:
|
|
case MenusRebuilt: {
|
|
AudacityProject *p = GetActiveProject();
|
|
wxASSERT(p != NULL);
|
|
CommandManager *c = p->GetCommandManager();
|
|
wxASSERT(c != NULL);
|
|
|
|
wxMenuBar * pBar = p->GetMenuBar();
|
|
wxASSERT(pBar != NULL );
|
|
wxMenu * pMenu = pBar->GetMenu( 2 ); // Menu 2 is the View Menu.
|
|
wxASSERT( pMenu != NULL );
|
|
|
|
c->SetToMenu( pMenu );
|
|
c->AddSeparator();
|
|
// c->BeginMenu(_("T&ools"));
|
|
c->SetDefaultFlags(AudioIONotBusyFlag, AudioIONotBusyFlag);
|
|
c->AddItem(wxT("NyqBench"),
|
|
_("&Nyquist Workbench..."),
|
|
new ModNyqBenchCommandFunctor());
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
};
|
|
|
|
//----------------------------------------------------------------------------
|
|
// NyqTextCtrl
|
|
//----------------------------------------------------------------------------
|
|
|
|
BEGIN_EVENT_TABLE(NyqTextCtrl, wxTextCtrl)
|
|
#if defined(__WXMAC__)
|
|
EVT_KEY_DOWN(NyqTextCtrl::OnKeyDown)
|
|
#endif
|
|
EVT_KEY_UP(NyqTextCtrl::OnKeyUp)
|
|
EVT_CHAR(NyqTextCtrl::OnChar)
|
|
EVT_UPDATE_UI(wxID_ANY, NyqTextCtrl::OnUpdate)
|
|
END_EVENT_TABLE()
|
|
|
|
NyqTextCtrl::NyqTextCtrl(wxWindow *parent,
|
|
wxWindowID id,
|
|
const wxString &value,
|
|
const wxPoint & pos,
|
|
const wxSize & size,
|
|
int style)
|
|
: wxTextCtrl(parent, id, value, pos, size, style)
|
|
{
|
|
mLastCaretPos = -1;
|
|
mLeftParen = -1;
|
|
mRightParen = -1;
|
|
|
|
mOn.SetTextColour(*wxRED);
|
|
mOff.SetTextColour(*wxBLACK);
|
|
}
|
|
|
|
void NyqTextCtrl::SetFocusFromKbd()
|
|
{
|
|
#if defined(__WXMSW__)
|
|
// We do this to prevent wxMSW from selecting all text when the
|
|
// user tabs into the text controls.
|
|
wxWindowBase::SetFocusFromKbd();
|
|
#else
|
|
wxTextCtrl::SetFocusFromKbd();
|
|
#endif
|
|
}
|
|
|
|
void NyqTextCtrl::MarkDirty()
|
|
{
|
|
wxTextCtrl::MarkDirty();
|
|
FindParens();
|
|
}
|
|
|
|
void NyqTextCtrl::OnChar(wxKeyEvent & e)
|
|
{
|
|
e.Skip();
|
|
|
|
// Hide any previously highlighted parens
|
|
if (mLeftParen >= 0) {
|
|
#if defined(__WXMSW__)
|
|
Freeze(); // Prevents selection flashing on Windows
|
|
#endif
|
|
|
|
SetStyle(mLeftParen, mLeftParen + 1, mOff);
|
|
SetStyle(mLeftParens[mLeftParen], mLeftParens[mLeftParen] + 1, mOff);
|
|
mLeftParen = -1;
|
|
mRightParen = -1;
|
|
|
|
#if defined(__WXMSW__)
|
|
Thaw(); // Prevents selection flashing on Windows
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#if defined(__WXMAC__)
|
|
#include <wx/mac/uma.h>
|
|
|
|
// This is hackage to correct a problem on Leopard where the
|
|
// caret jumps up two lines when the up arrow is pressed and
|
|
// the caret is at the beginning of the line.
|
|
void NyqTextCtrl::OnKeyDown(wxKeyEvent & e)
|
|
{
|
|
e.Skip();
|
|
if (UMAGetSystemVersion() >= 0x1050) {
|
|
if (e.GetKeyCode() == WXK_UP && e.GetModifiers() == 0) {
|
|
long x;
|
|
long y;
|
|
|
|
PositionToXY(GetInsertionPoint(), &x, &y);
|
|
if (x == 0 && y > 1) {
|
|
y--;
|
|
SetInsertionPoint(XYToPosition(x, y) - 1);
|
|
e.Skip(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void NyqTextCtrl::OnKeyUp(wxKeyEvent & e)
|
|
{
|
|
e.Skip();
|
|
|
|
int pos = GetInsertionPoint();
|
|
int lpos = wxMax(0, pos - 1);
|
|
|
|
wxString text = GetRange(lpos, pos);
|
|
|
|
if (text[0] == wxT('(')) {
|
|
wxLongToLongHashMap::const_iterator left = mLeftParens.find(lpos);
|
|
if (left != mLeftParens.end()) {
|
|
Colorize(lpos, left->second);
|
|
}
|
|
}
|
|
else if (text[0] == wxT(')')) {
|
|
wxLongToLongHashMap::const_iterator right = mRightParens.find(lpos);
|
|
if (right != mRightParens.end()) {
|
|
Colorize(right->second, lpos);
|
|
}
|
|
}
|
|
}
|
|
|
|
void NyqTextCtrl::OnUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
int pos = GetInsertionPoint();
|
|
|
|
if (pos != mLastCaretPos) {
|
|
int lpos = wxMax(0, pos - 1);
|
|
|
|
wxString text = GetRange(lpos, pos);
|
|
|
|
if (text[0] == wxT('(')) {
|
|
wxLongToLongHashMap::const_iterator left = mLeftParens.find(lpos);
|
|
if (left != mLeftParens.end()) {
|
|
Colorize(lpos, left->second);
|
|
}
|
|
}
|
|
else if (text[0] == wxT(')')) {
|
|
wxLongToLongHashMap::const_iterator right = mRightParens.find(lpos);
|
|
if (right != mRightParens.end()) {
|
|
Colorize(right->second, lpos);
|
|
}
|
|
}
|
|
|
|
mLastCaretPos = pos;
|
|
}
|
|
}
|
|
|
|
void NyqTextCtrl::GoMatch()
|
|
{
|
|
MoveCursor(mRightParen, mLeftParen);
|
|
}
|
|
|
|
void NyqTextCtrl::GoTop()
|
|
{
|
|
wxLongToLongHashMap::const_iterator it;
|
|
long first = -1;
|
|
long second = -1;
|
|
|
|
if (mLeftParen != -1) {
|
|
for (it = mLeftParens.begin(); it != mLeftParens.end(); it++) {
|
|
if (mLeftParen > it->first && mLeftParen < it->second) {
|
|
if (first == -1 || it->first < first) {
|
|
first = it->first;
|
|
second = it->second;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (first != -1) {
|
|
MoveCursor(first, second);
|
|
}
|
|
}
|
|
|
|
void NyqTextCtrl::GoUp()
|
|
{
|
|
wxLongToLongHashMap::const_iterator it;
|
|
long first = -1;
|
|
long second = -1;
|
|
|
|
if (mLeftParen != -1) {
|
|
for (it = mLeftParens.begin(); it != mLeftParens.end(); it++) {
|
|
if (mLeftParen > it->first && mLeftParen < it->second) {
|
|
if (first == -1 || it->first > first) {
|
|
first = it->first;
|
|
second = it->second;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (first != -1) {
|
|
MoveCursor(first, second);
|
|
}
|
|
}
|
|
|
|
void NyqTextCtrl::GoPrev()
|
|
{
|
|
wxLongToLongHashMap::const_iterator it;
|
|
long first = -1;
|
|
long second = -1;
|
|
|
|
if (mLeftParen != -1) {
|
|
for (it = mLeftParens.begin(); it != mLeftParens.end(); it++) {
|
|
if (it->first < mLeftParen && it->first >= first) {
|
|
first = it->first;
|
|
second = it->second;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (first != -1) {
|
|
MoveCursor(first, second);
|
|
}
|
|
}
|
|
|
|
void NyqTextCtrl::GoNext()
|
|
{
|
|
wxLongToLongHashMap::const_iterator it;
|
|
long first = -1;
|
|
long second = -1;
|
|
|
|
if (mLeftParen != -1) {
|
|
for (it = mLeftParens.begin(); it != mLeftParens.end(); it++) {
|
|
if (it->first > mLeftParen && (first == -1 || it->first < first)) {
|
|
first = it->first;
|
|
second = it->second;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (first != -1) {
|
|
MoveCursor(first, second);
|
|
}
|
|
}
|
|
|
|
void NyqTextCtrl::MoveCursor(long first, long second)
|
|
{
|
|
int pos = GetInsertionPoint();
|
|
int lpos = wxMax(0, pos - 1);
|
|
|
|
wxString text = GetRange(lpos, pos);
|
|
|
|
if (text[0] == wxT('(')) {
|
|
SetInsertionPoint(first + 1);
|
|
Colorize(first, second);
|
|
}
|
|
else if (text[0] == wxT(')')) {
|
|
SetInsertionPoint(second + 1);
|
|
Colorize(first, second);
|
|
}
|
|
}
|
|
|
|
void NyqTextCtrl::Colorize(long left, long right)
|
|
{
|
|
// Hide any previously highlighted parens
|
|
if (mLeftParen >= 0) {
|
|
#if defined(__WXMSW__)
|
|
Freeze(); // Prevents selection flashing on Windows
|
|
#endif
|
|
|
|
SetStyle(mLeftParen, mLeftParen + 1, mOff);
|
|
SetStyle(mLeftParens[mLeftParen], mLeftParens[mLeftParen] + 1, mOff);
|
|
mLeftParen = -1;
|
|
mRightParen = -1;
|
|
|
|
#if defined(__WXMSW__)
|
|
Thaw(); // Prevents selection flashing on Windows
|
|
#endif
|
|
}
|
|
|
|
mLeftParen = left;
|
|
mRightParen = right;
|
|
|
|
if (mLeftParen != -1) {
|
|
SetStyle(mLeftParen, mLeftParen + 1, mOn);
|
|
SetStyle(mRightParen, mRightParen + 1, mOn);
|
|
|
|
SetStyle(mLeftParen + 1, mLeftParen + 1, mOff);
|
|
SetStyle(mRightParen + 1, mRightParen + 1, mOff);
|
|
}
|
|
}
|
|
|
|
void NyqTextCtrl::FindParens()
|
|
{
|
|
wxString text = GetValue();
|
|
bool inquotes = false;
|
|
wxArrayInt stack;
|
|
long len = (long) text.Length();
|
|
long pos;
|
|
|
|
mLeftParens.clear();
|
|
mRightParens.clear();
|
|
|
|
for (pos = 0; pos < len; pos++) {
|
|
switch (text[(int)pos])
|
|
{
|
|
case wxT('"'):
|
|
inquotes = !inquotes;
|
|
break;
|
|
|
|
case wxT(';'):
|
|
if (!inquotes) {
|
|
pos = (long)text.find(wxT('\n'), pos);
|
|
if (pos == (long)wxString::npos) {
|
|
pos = len;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case wxT('#'):
|
|
if (!inquotes) {
|
|
long ndx = pos + 1;
|
|
if (ndx < len && text[(int)ndx] == wxT('|')) {
|
|
// Shamelessly stolen from xlread.c/pcomment()
|
|
wxChar lastch = -1;
|
|
int n = 1;
|
|
|
|
/* look for the matching delimiter (and handle nesting) */
|
|
while (n > 0 && ++pos < len) {
|
|
wxChar ch = text[(int)pos];
|
|
if (lastch == '|' && ch == '#') {
|
|
--n;
|
|
ch = -1;
|
|
}
|
|
else if (lastch == '#' && ch == '|') {
|
|
++n;
|
|
ch = -1;
|
|
}
|
|
lastch = ch;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case wxT('('):
|
|
if (!inquotes) {
|
|
stack.Add(pos);
|
|
}
|
|
break;
|
|
|
|
case wxT(')'):
|
|
if (!inquotes) {
|
|
if (stack.GetCount() > 0) {
|
|
int left = stack.Last();
|
|
stack.RemoveAt(stack.GetCount() - 1);
|
|
|
|
mLeftParens[left] = pos;
|
|
mRightParens[pos] = left;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// NyqRedirector
|
|
//----------------------------------------------------------------------------
|
|
|
|
NyqRedirector::NyqRedirector(NyqTextCtrl *text)
|
|
: mText(text)
|
|
{
|
|
mOld = std::cout.rdbuf(this);
|
|
}
|
|
|
|
NyqRedirector::~NyqRedirector()
|
|
{
|
|
std::cout.flush();
|
|
std::cout.rdbuf(mOld);
|
|
if (s.length() > 0) {
|
|
AppendText();
|
|
}
|
|
}
|
|
|
|
int NyqRedirector::overflow(int c)
|
|
{
|
|
s += (char)c;
|
|
if (c == '\n') {
|
|
AppendText();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void NyqRedirector::AppendText()
|
|
{
|
|
mText->AppendText(wxString(s.c_str(), wxConvISO8859_1));
|
|
s.clear();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// ModNyqBenchCommandFunctor
|
|
// Connects Audacity menu item to an action in this dll.
|
|
// Only one action implemented so far.
|
|
//----------------------------------------------------------------------------
|
|
void ModNyqBenchCommandFunctor::operator()(int index, const wxEvent *e)
|
|
{
|
|
if (gBench) {
|
|
gBench->Show();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// NyqBench
|
|
//----------------------------------------------------------------------------
|
|
|
|
enum
|
|
{
|
|
ID_AUTOLOAD = 20000,
|
|
|
|
ID_AUTOWRAP,
|
|
|
|
ID_FONT,
|
|
ID_SPLITV,
|
|
ID_SPLITH,
|
|
ID_TOGGLECODE,
|
|
ID_TOGGLEOUTPUT,
|
|
ID_SMALLICONS,
|
|
ID_LARGEICONS,
|
|
ID_MATCH,
|
|
ID_TOP,
|
|
ID_UP,
|
|
ID_PREVIOUS,
|
|
ID_NEXT,
|
|
|
|
ID_GO,
|
|
ID_STOP,
|
|
|
|
ID_SCRIPT,
|
|
ID_OUTPUT
|
|
};
|
|
|
|
BEGIN_EVENT_TABLE(NyqBench, wxFrame)
|
|
EVT_CLOSE(NyqBench::OnClose)
|
|
EVT_MOVE(NyqBench::OnMove)
|
|
EVT_SIZE(NyqBench::OnSize)
|
|
|
|
EVT_MENU(wxID_NEW, NyqBench::OnNew)
|
|
EVT_MENU(wxID_OPEN, NyqBench::OnOpen)
|
|
EVT_MENU(wxID_SAVE, NyqBench::OnSave)
|
|
EVT_MENU(wxID_SAVEAS, NyqBench::OnSaveAs)
|
|
EVT_MENU(wxID_REVERT_TO_SAVED, NyqBench::OnRevert)
|
|
EVT_MENU(ID_AUTOLOAD, NyqBench::OnAutoLoad)
|
|
EVT_MENU(wxID_CLOSE, NyqBench::OnCloseWindow)
|
|
|
|
EVT_MENU(wxID_UNDO, NyqBench::OnUndo)
|
|
EVT_MENU(wxID_REDO, NyqBench::OnRedo)
|
|
EVT_MENU(wxID_CUT, NyqBench::OnCut)
|
|
EVT_MENU(wxID_COPY, NyqBench::OnCopy)
|
|
EVT_MENU(wxID_PASTE, NyqBench::OnPaste)
|
|
EVT_MENU(wxID_CLEAR, NyqBench::OnClear)
|
|
EVT_MENU(wxID_SELECTALL, NyqBench::OnSelectAll)
|
|
EVT_MENU(wxID_FIND, NyqBench::OnFind)
|
|
EVT_MENU(ID_MATCH, NyqBench::OnGoMatch)
|
|
EVT_MENU(ID_TOP, NyqBench::OnGoTop)
|
|
EVT_MENU(ID_UP, NyqBench::OnGoUp)
|
|
EVT_MENU(ID_PREVIOUS, NyqBench::OnGoPrev)
|
|
EVT_MENU(ID_NEXT, NyqBench::OnGoNext)
|
|
EVT_MENU(ID_AUTOWRAP, NyqBench::OnAutoWrap)
|
|
|
|
EVT_MENU(ID_FONT, NyqBench::OnFont)
|
|
EVT_MENU(ID_SPLITV, NyqBench::OnSplitV)
|
|
EVT_MENU(ID_SPLITH, NyqBench::OnSplitH)
|
|
EVT_MENU(ID_TOGGLECODE, NyqBench::OnToggleCode)
|
|
EVT_MENU(ID_TOGGLEOUTPUT, NyqBench::OnToggleOutput)
|
|
EVT_MENU(ID_SMALLICONS, NyqBench::OnSmallIcons)
|
|
EVT_MENU(ID_LARGEICONS, NyqBench::OnLargeIcons)
|
|
|
|
EVT_MENU(ID_GO, NyqBench::OnGo)
|
|
EVT_MENU(ID_STOP, NyqBench::OnStop)
|
|
|
|
EVT_MENU(wxID_ABOUT, NyqBench::OnAbout)
|
|
|
|
EVT_FIND(wxID_ANY, NyqBench::OnFindDialog)
|
|
EVT_FIND_NEXT(wxID_ANY, NyqBench::OnFindDialog)
|
|
EVT_FIND_REPLACE(wxID_ANY, NyqBench::OnFindDialog)
|
|
EVT_FIND_REPLACE_ALL(wxID_ANY, NyqBench::OnFindDialog)
|
|
EVT_FIND_CLOSE(wxID_ANY, NyqBench::OnFindDialog)
|
|
|
|
EVT_TEXT(ID_SCRIPT, NyqBench::OnTextUpdate)
|
|
|
|
EVT_UPDATE_UI(wxID_SAVE, NyqBench::OnMenuUpdate)
|
|
EVT_UPDATE_UI(wxID_SAVEAS, NyqBench::OnMenuUpdate)
|
|
EVT_UPDATE_UI(wxID_REVERT_TO_SAVED, NyqBench::OnMenuUpdate)
|
|
|
|
EVT_UPDATE_UI(wxID_UNDO, NyqBench::OnUndoUpdate)
|
|
EVT_UPDATE_UI(wxID_REDO, NyqBench::OnRedoUpdate)
|
|
EVT_UPDATE_UI(wxID_CUT, NyqBench::OnCutUpdate)
|
|
EVT_UPDATE_UI(wxID_COPY, NyqBench::OnCopyUpdate)
|
|
EVT_UPDATE_UI(wxID_PASTE, NyqBench::OnPasteUpdate)
|
|
EVT_UPDATE_UI(wxID_CLEAR, NyqBench::OnClearUpdate)
|
|
|
|
EVT_UPDATE_UI(ID_SPLITH, NyqBench::OnViewUpdate)
|
|
EVT_UPDATE_UI(ID_SPLITV, NyqBench::OnViewUpdate)
|
|
EVT_UPDATE_UI(ID_TOGGLECODE, NyqBench::OnViewUpdate)
|
|
EVT_UPDATE_UI(ID_TOGGLEOUTPUT, NyqBench::OnViewUpdate)
|
|
|
|
EVT_UPDATE_UI(ID_GO, NyqBench::OnRunUpdate)
|
|
|
|
EVT_UPDATE_UI(ID_SCRIPT, NyqBench::OnScriptUpdate)
|
|
EVT_UPDATE_UI(ID_OUTPUT, NyqBench::OnOutputUpdate)
|
|
END_EVENT_TABLE()
|
|
|
|
NyqBench::NyqBench(wxWindow * parent)
|
|
: wxFrame(NULL,
|
|
wxID_ANY,
|
|
wxEmptyString,
|
|
wxDefaultPosition,
|
|
wxDefaultSize,
|
|
wxDEFAULT_FRAME_STYLE |
|
|
wxMINIMIZE_BOX |
|
|
wxMAXIMIZE_BOX |
|
|
wxRESIZE_BORDER)
|
|
{
|
|
mFindDlg = NULL;
|
|
mRunning = false;
|
|
mScriptBox = NULL;
|
|
mOutputBox = NULL;
|
|
mScript = NULL;
|
|
mOutput = NULL;
|
|
|
|
// No need to delete...EffectManager will do it
|
|
mEffect = new NyquistEffect(wxT("===nyquistworker==="));
|
|
EffectManager::Get().RegisterEffect(mEffect);
|
|
|
|
mPath = gPrefs->Read(wxT("NyqBench/Path"), wxEmptyString);
|
|
mAutoLoad = (gPrefs->Read(wxT("NyqBench/AutoLoad"), 0L) != 0);
|
|
mAutoWrap = (gPrefs->Read(wxT("NyqBench/AutoWrap"), true) != 0);
|
|
mLargeIcons = (gPrefs->Read(wxT("NyqBench/LargeIcons"), 0L) != 0);
|
|
mSplitMode = gPrefs->Read(wxT("NyqBench/SplitMode"), wxSPLIT_VERTICAL);
|
|
mShowCode = (gPrefs->Read(wxT("NyqBench/ShowScript"), true) != 0);
|
|
mShowOutput = (gPrefs->Read(wxT("NyqBench/ShowOutput"), true) != 0);
|
|
|
|
SetIcon(wxICON(AudacityLogo));
|
|
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
|
|
ShuttleGui S(this, eIsCreating);
|
|
PopulateOrExchange(S);
|
|
wxMenuBar *bar = new wxMenuBar();
|
|
|
|
wxMenu *menu = new wxMenu();
|
|
menu->Append(wxID_NEW, wxT("&New\tCtrl+N"));
|
|
menu->Append(wxID_OPEN, wxT("&Open...\tCtrl+O"));
|
|
menu->Append(wxID_SAVE, wxT("&Save...\tCtrl+S"));
|
|
menu->Append(wxID_SAVEAS, wxT("Save &As...\tCtrl+Shift+S"));
|
|
menu->AppendSeparator();
|
|
menu->Append(wxID_REVERT_TO_SAVED, _T("&Revert to Saved"));
|
|
menu->AppendSeparator();
|
|
menu->AppendCheckItem(ID_AUTOLOAD, _T("Auto &Load Last File"))->Check(mAutoLoad);
|
|
menu->AppendSeparator();
|
|
menu->Append(wxID_CLOSE, wxT("&Close Window\tCtrl+W"));
|
|
bar->Append(menu, wxT("&File"));
|
|
|
|
menu = new wxMenu();
|
|
menu->Append(wxID_UNDO, _("&Undo\tCtrl+Z"));
|
|
menu->Append(wxID_REDO, _("&Redo\tCtrl+Y"));
|
|
menu->AppendSeparator();
|
|
menu->Append(wxID_CUT, _("Cu&t\tCtrl+X"));
|
|
menu->Append(wxID_COPY, _("&Copy\tCtrl+C"));
|
|
menu->Append(wxID_PASTE, _("&Paste\tCtrl+V"));
|
|
menu->Append(wxID_CLEAR, _("Cle&ar\tCtrl+L"));
|
|
menu->AppendSeparator();
|
|
menu->Append(wxID_SELECTALL, _("Select A&ll\tCtrl+A"));
|
|
menu->AppendSeparator();
|
|
menu->Append(wxID_FIND, _("&Find...\tCtrl+F"));
|
|
menu->AppendSeparator();
|
|
wxMenu *sub = new wxMenu();
|
|
sub->Append(ID_MATCH, _("&Matching Paren\tF8"));
|
|
sub->Append(ID_TOP, _("&Top S-expr\tF9"));
|
|
sub->Append(ID_UP, _("&Higher S-expr\tF10"));
|
|
sub->Append(ID_PREVIOUS, _("&Previous S-expr\tF11"));
|
|
sub->Append(ID_NEXT, _("&Next S-expr\tF12"));
|
|
menu->AppendSubMenu(sub, _("&Go to"));
|
|
menu->AppendSeparator();
|
|
menu->AppendCheckItem(ID_AUTOWRAP, _T("Auto &Wrap"))->Check(mAutoWrap);
|
|
bar->Append(menu, wxT("&Edit"));
|
|
|
|
menu = new wxMenu();
|
|
menu->Append(ID_FONT, _("Select &Font..."));
|
|
menu->AppendSeparator();
|
|
menu->Append(ID_SPLITV, _("Split &Vertically"));
|
|
menu->Append(ID_SPLITH, _("Split &Horizontally"));
|
|
menu->AppendSeparator();
|
|
menu->AppendCheckItem(ID_TOGGLECODE, _("Show S&cript"));
|
|
menu->AppendCheckItem(ID_TOGGLEOUTPUT, _("Show &Output"));
|
|
menu->AppendSeparator();
|
|
sub = new wxMenu();
|
|
sub->AppendRadioItem(ID_LARGEICONS, _("&Large Icons"));
|
|
sub->AppendRadioItem(ID_SMALLICONS, _("&Small Icons"));
|
|
menu->AppendSubMenu(sub, _("Toolbar"));
|
|
bar->Append(menu, wxT("&View"));
|
|
|
|
menu = new wxMenu();
|
|
menu->Append(ID_GO, _("&Go\tF5"));
|
|
menu->Append(ID_STOP, _("&Stop\tF6"));
|
|
bar->Append(menu, wxT("&Run"));
|
|
|
|
#if defined(__WXMAC__)
|
|
menu->Append(wxID_ABOUT, _("&About"));
|
|
#else
|
|
menu = new wxMenu();
|
|
menu->Append(wxID_ABOUT, _("&About"));
|
|
bar->Append(menu, wxT("Help"));
|
|
#endif
|
|
|
|
SetMenuBar(bar);
|
|
|
|
RecreateToolbar(mLargeIcons);
|
|
|
|
wxRect r;
|
|
r.SetX(gPrefs->Read(wxT("NyqBench/Window/X"), -1));
|
|
r.SetY(gPrefs->Read(wxT("NyqBench/Window/Y"), -1));
|
|
r.SetWidth(gPrefs->Read(wxT("NyqBench/Window/Width"), -1));
|
|
r.SetHeight(gPrefs->Read(wxT("NyqBench/Window/Height"), -1));
|
|
if (r == wxRect(-1, -1, -1, -1)) {
|
|
Center();
|
|
}
|
|
else {
|
|
SetSize(r);
|
|
}
|
|
|
|
bool maximized = false;
|
|
gPrefs->Read(wxT("NyqBench/Window/Maximized"), maximized);
|
|
if (maximized) {
|
|
Maximize();
|
|
}
|
|
|
|
long sashpos;
|
|
sashpos = gPrefs->Read(wxT("NyqBench/SplitX"), 0l);
|
|
if (sashpos > 0) {
|
|
mSplitter->SetSashPosition(sashpos);
|
|
}
|
|
|
|
wxString dflt = wxSystemSettings::GetFont(wxSYS_SYSTEM_FONT).GetNativeFontInfoDesc();
|
|
wxString desc;
|
|
wxTextAttr attr;
|
|
|
|
desc = gPrefs->Read(wxT("NyqBench/ScriptFont"), dflt);
|
|
mScriptFont.SetNativeFontInfo(desc);
|
|
#if defined(__WXMSW__)
|
|
// Force SYSTEM encoding to prevent conversion to Unicode in wxTextCtrl::DoWriteText().
|
|
// I don't know if this is something I'm doing wrong, but I'll have to look at this
|
|
// later if I get bored.
|
|
mScriptFont.SetEncoding(wxFONTENCODING_SYSTEM);
|
|
#endif
|
|
attr.SetFont(mScriptFont);
|
|
mScript->SetDefaultStyle(attr);
|
|
|
|
desc = gPrefs->Read(wxT("NyqBench/OutputFont"), dflt);
|
|
mOutputFont.SetNativeFontInfo(desc);
|
|
#if defined(__WXMSW__)
|
|
// Force SYSTEM encoding to prevent conversion to Unicode in wxTextCtrl::DoWriteText().
|
|
// I don't know if this is something I'm doing wrong, but I'll have to look at this
|
|
// later if I get bored.
|
|
mOutputFont.SetEncoding(wxFONTENCODING_SYSTEM);
|
|
#endif
|
|
attr.SetFont(mOutputFont);
|
|
mOutput->SetDefaultStyle(attr);
|
|
|
|
if (mAutoLoad && !mPath.GetFullPath().IsEmpty()) {
|
|
LoadFile();
|
|
}
|
|
|
|
SetWindowTitle();
|
|
}
|
|
|
|
NyqBench::~NyqBench()
|
|
{
|
|
gPrefs->Write(wxT("NyqBench/Window/Maximized"), IsMaximized());
|
|
if (!IsMaximized()) {
|
|
wxRect r = GetRect();
|
|
|
|
#if !defined(__WXMAC__)
|
|
if (IsIconized()) {
|
|
r = mLastSize;
|
|
}
|
|
#endif
|
|
|
|
gPrefs->Write(wxT("NyqBench/Window/X"), r.GetX());
|
|
gPrefs->Write(wxT("NyqBench/Window/Y"), r.GetY());
|
|
gPrefs->Write(wxT("NyqBench/Window/Width"), r.GetWidth());
|
|
gPrefs->Write(wxT("NyqBench/Window/Height"), r.GetHeight());
|
|
}
|
|
|
|
gPrefs->Write(wxT("NyqBench/AutoLoad"), mAutoLoad);
|
|
gPrefs->Write(wxT("NyqBench/AutoWrap"), mAutoWrap);
|
|
gPrefs->Write(wxT("NyqBench/ScriptFont"), mScriptFont.GetNativeFontInfoDesc());
|
|
gPrefs->Write(wxT("NyqBench/OutputFont"), mOutputFont.GetNativeFontInfoDesc());
|
|
gPrefs->Write(wxT("NyqBench/LargeIcons"), mLargeIcons);
|
|
gPrefs->Write(wxT("NyqBench/SplitX"), mSplitter->IsSplit() ? mSplitter->GetSashPosition() : 0);
|
|
gPrefs->Write(wxT("NyqBench/SplitMode"), mSplitter->IsSplit() ? mSplitter->GetSplitMode() : 0);
|
|
gPrefs->Write(wxT("NyqBench/ShowCode"), mScript->IsShown());
|
|
gPrefs->Write(wxT("NyqBench/ShowOutput"), mOutput->IsShown());
|
|
}
|
|
|
|
void NyqBench::PopulateOrExchange(ShuttleGui & S)
|
|
{
|
|
S.StartHorizontalLay(wxEXPAND, true);
|
|
{
|
|
wxPanel *scriptp;
|
|
wxPanel *outputp;
|
|
wxStaticBoxSizer *scripts;
|
|
wxStaticBoxSizer *outputs;
|
|
wxBoxSizer *bs;
|
|
|
|
mSplitter = new wxSplitterWindow(this,
|
|
wxID_ANY,
|
|
wxDefaultPosition,
|
|
wxDefaultSize,
|
|
wxSP_LIVE_UPDATE |
|
|
wxSP_3DSASH |
|
|
wxSP_NOBORDER);
|
|
|
|
scriptp = new wxPanel(mSplitter,
|
|
wxID_ANY,
|
|
wxDefaultPosition,
|
|
wxDefaultSize,
|
|
wxNO_FULL_REPAINT_ON_RESIZE |
|
|
wxCLIP_CHILDREN);
|
|
bs = new wxBoxSizer(wxVERTICAL);
|
|
scriptp->SetSizer(bs);
|
|
|
|
mScriptBox = new wxStaticBox(scriptp,
|
|
wxID_ANY,
|
|
_("Script"));
|
|
|
|
scripts = new wxStaticBoxSizer(mScriptBox,
|
|
wxVERTICAL);
|
|
bs->Add(scripts, true, wxEXPAND);
|
|
|
|
mScript = new NyqTextCtrl(scriptp,
|
|
ID_SCRIPT,
|
|
wxEmptyString,
|
|
wxDefaultPosition,
|
|
wxDefaultSize,
|
|
wxTE_RICH2 | wxTE_RICH |
|
|
(mAutoWrap ? wxTE_BESTWRAP : wxTE_DONTWRAP) |
|
|
wxTE_NOHIDESEL |
|
|
wxTE_MULTILINE);
|
|
scripts->Add(mScript, true, wxEXPAND);
|
|
|
|
outputp = new wxPanel(mSplitter,
|
|
wxID_ANY,
|
|
wxDefaultPosition,
|
|
wxDefaultSize,
|
|
wxNO_FULL_REPAINT_ON_RESIZE |
|
|
wxCLIP_CHILDREN);
|
|
bs = new wxBoxSizer(wxVERTICAL);
|
|
outputp->SetSizer(bs);
|
|
|
|
mOutputBox = new wxStaticBox(outputp,
|
|
wxID_ANY,
|
|
_("Output"));
|
|
outputs = new wxStaticBoxSizer(mOutputBox,
|
|
wxVERTICAL);
|
|
bs->Add(outputs, true, wxEXPAND);
|
|
|
|
mOutput = new NyqTextCtrl(outputp,
|
|
ID_OUTPUT,
|
|
wxEmptyString,
|
|
wxDefaultPosition,
|
|
wxDefaultSize,
|
|
wxTE_READONLY |
|
|
#if !defined(__WXMAC__)
|
|
// I could not get the bloody horizontal scroll bar to appear on
|
|
// wxMac, so we can't use wxTE_DONTWRAP as you can't easily scroll
|
|
// left and right.
|
|
wxTE_DONTWRAP |
|
|
#endif
|
|
wxTE_NOHIDESEL |
|
|
wxTE_MULTILINE);
|
|
outputs->Add(mOutput, true, wxEXPAND);
|
|
|
|
switch (mSplitMode)
|
|
{
|
|
case wxSPLIT_VERTICAL:
|
|
mSplitter->SplitVertically(scriptp, outputp, 300);
|
|
break;
|
|
|
|
case wxSPLIT_HORIZONTAL:
|
|
mSplitter->SplitHorizontally(scriptp, outputp, 300);
|
|
break;
|
|
|
|
default:
|
|
mSplitter->Initialize((mShowCode ? scriptp : outputp));
|
|
break;
|
|
}
|
|
|
|
mSplitter->SetMinimumPaneSize(50);
|
|
|
|
S.AddSpace(5, 1);
|
|
S.Prop(true);
|
|
S.AddWindow(mSplitter, wxEXPAND);
|
|
S.AddSpace(5, 1);
|
|
|
|
mSplitter->SetMinSize(wxSize(600, 400));
|
|
}
|
|
S.EndHorizontalLay();
|
|
|
|
S.AddSpace(1, 5);
|
|
|
|
return;
|
|
}
|
|
|
|
void NyqBench::OnClose(wxCloseEvent & e)
|
|
{
|
|
if (!Validate()) {
|
|
e.Veto();
|
|
}
|
|
else {
|
|
Show(false);
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnMove(wxMoveEvent & e)
|
|
{
|
|
e.Skip();
|
|
if (!IsIconized() && !IsMaximized()) {
|
|
mLastSize.SetPosition(e.GetPosition());
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnSize(wxSizeEvent & e)
|
|
{
|
|
e.Skip();
|
|
if (!IsIconized() && !IsMaximized()) {
|
|
mLastSize.SetSize(e.GetSize());
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnCloseWindow(wxCommandEvent & e)
|
|
{
|
|
Close();
|
|
}
|
|
|
|
void NyqBench::OnNew(wxCommandEvent & e)
|
|
{
|
|
if (!Validate()) {
|
|
return;
|
|
}
|
|
|
|
mPath.SetFullName(wxEmptyString);
|
|
|
|
while (mScript->CanUndo()) {
|
|
mScript->Undo();
|
|
}
|
|
|
|
mScript->Clear();
|
|
mScript->DiscardEdits();
|
|
|
|
SetWindowTitle();
|
|
}
|
|
|
|
void NyqBench::OnOpen(wxCommandEvent & e)
|
|
{
|
|
if (mScript->IsModified() && !Validate()) {
|
|
return;
|
|
}
|
|
|
|
wxFileDialog dlog(this,
|
|
_("Load Nyquist script"),
|
|
mPath.GetPath(),
|
|
wxEmptyString,
|
|
_("Nyquist scripts (*.ny)|*.ny|Lisp scripts (*.lsp)|*.lsp|All files|*"),
|
|
wxFD_OPEN | wxRESIZE_BORDER);
|
|
|
|
if (dlog.ShowModal() != wxID_OK) {
|
|
return;
|
|
}
|
|
|
|
mPath = dlog.GetPath();
|
|
gPrefs->Write(wxT("NyqBench/Path"), mPath.GetFullPath());
|
|
|
|
LoadFile();
|
|
|
|
SetWindowTitle();
|
|
}
|
|
|
|
void NyqBench::OnSave(wxCommandEvent & e)
|
|
{
|
|
if (mScript->GetLastPosition() == 0) {
|
|
return;
|
|
}
|
|
|
|
if (mPath.GetFullPath().IsEmpty()) {
|
|
OnSaveAs(e);
|
|
return;
|
|
}
|
|
|
|
if (!mScript->SaveFile(mPath.GetFullPath()))
|
|
{
|
|
wxMessageBox(_("Script was not saved."),
|
|
_("Warning"),
|
|
wxICON_EXCLAMATION,
|
|
this);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnSaveAs(wxCommandEvent & e)
|
|
{
|
|
if (mScript->GetLastPosition() == 0) {
|
|
return;
|
|
}
|
|
|
|
wxFileDialog dlog(this,
|
|
_("Save Nyquist script"),
|
|
mPath.GetFullPath(),
|
|
wxEmptyString,
|
|
_("Nyquist scripts (*.ny)|*.ny|Lisp scripts (*.lsp)|*.lsp|All files|*"),
|
|
wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER);
|
|
|
|
if (dlog.ShowModal() != wxID_OK) {
|
|
return;
|
|
}
|
|
|
|
mPath = dlog.GetPath();
|
|
gPrefs->Write(wxT("NyqBench/Path"), mPath.GetFullPath());
|
|
|
|
if (!mScript->SaveFile(mPath.GetFullPath()))
|
|
{
|
|
wxMessageBox(_("Script was not saved."),
|
|
_("Warning"),
|
|
wxICON_EXCLAMATION,
|
|
this);
|
|
return;
|
|
}
|
|
|
|
SetWindowTitle();
|
|
}
|
|
|
|
void NyqBench::OnAutoLoad(wxCommandEvent & e)
|
|
{
|
|
mAutoLoad = e.IsChecked();
|
|
}
|
|
|
|
void NyqBench::OnRevert(wxCommandEvent & e)
|
|
{
|
|
if (mPath.GetFullPath().IsEmpty()) {
|
|
return;
|
|
}
|
|
|
|
if (!Validate()) {
|
|
return;
|
|
}
|
|
|
|
LoadFile();
|
|
}
|
|
|
|
void NyqBench::OnUndo(wxCommandEvent & e)
|
|
{
|
|
(FindFocus() == mScript ? mScript : mOutput)->Undo();
|
|
}
|
|
|
|
void NyqBench::OnRedo(wxCommandEvent & e)
|
|
{
|
|
(FindFocus() == mScript ? mScript : mOutput)->Redo();
|
|
}
|
|
|
|
void NyqBench::OnCut(wxCommandEvent & e)
|
|
{
|
|
(FindFocus() == mScript ? mScript : mOutput)->Cut();
|
|
}
|
|
|
|
void NyqBench::OnCopy(wxCommandEvent & e)
|
|
{
|
|
(FindFocus() == mScript ? mScript : mOutput)->Copy();
|
|
}
|
|
|
|
void NyqBench::OnPaste(wxCommandEvent & e)
|
|
{
|
|
(FindFocus() == mScript ? mScript : mOutput)->Paste();
|
|
}
|
|
|
|
void NyqBench::OnClear(wxCommandEvent & e)
|
|
{
|
|
(FindFocus() == mScript ? mScript : mOutput)->Clear();
|
|
}
|
|
|
|
void NyqBench::OnSelectAll(wxCommandEvent & e)
|
|
{
|
|
(FindFocus() == mScript ? mScript : mOutput)->SetSelection(-1, -1);
|
|
}
|
|
|
|
void NyqBench::OnFind(wxCommandEvent & e)
|
|
{
|
|
if (mFindDlg ) {
|
|
delete mFindDlg;
|
|
mFindDlg = NULL;
|
|
}
|
|
else {
|
|
NyqTextCtrl *w = (NyqTextCtrl *) FindFocus();
|
|
if (w == mScript || w == mOutput) {
|
|
mFindText = w;
|
|
|
|
int flags = 0;
|
|
|
|
flags |= (gPrefs->Read(wxT("NyqBench/Find/Down"), 0L) ? wxFR_DOWN : 0);
|
|
flags |= (gPrefs->Read(wxT("NyqBench/Find/Word"), 0L) ? wxFR_WHOLEWORD : 0);
|
|
flags |= (gPrefs->Read(wxT("NyqBench/Find/Case"), 0L) ? wxFR_MATCHCASE : 0);
|
|
|
|
mFindData.SetFlags(flags);
|
|
|
|
mFindDlg = new wxFindReplaceDialog(this,
|
|
&mFindData,
|
|
_("Find dialog"),
|
|
wxFR_NOWHOLEWORD);
|
|
mFindDlg->Show(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnGoMatch(wxCommandEvent & e)
|
|
{
|
|
mScript->GoMatch();
|
|
}
|
|
|
|
void NyqBench::OnGoTop(wxCommandEvent & e)
|
|
{
|
|
mScript->GoTop();
|
|
}
|
|
|
|
void NyqBench::OnGoUp(wxCommandEvent & e)
|
|
{
|
|
mScript->GoUp();
|
|
}
|
|
|
|
void NyqBench::OnGoPrev(wxCommandEvent & e)
|
|
{
|
|
mScript->GoPrev();
|
|
}
|
|
|
|
void NyqBench::OnGoNext(wxCommandEvent & e)
|
|
{
|
|
mScript->GoNext();
|
|
}
|
|
|
|
void NyqBench::OnAutoWrap(wxCommandEvent & e)
|
|
{
|
|
mAutoWrap = e.IsChecked();
|
|
|
|
wxWindow *parent = mScript->GetParent();
|
|
wxString text = mScript->GetValue();
|
|
bool focused = wxWindow::FindFocus() == mScript;
|
|
long pos = mScript->GetInsertionPoint();
|
|
long from;
|
|
long to;
|
|
mScript->GetSelection(&from, &to);
|
|
|
|
wxSizer *s = mScript->GetContainingSizer();
|
|
s->Detach(mScript);
|
|
delete mScript;
|
|
|
|
mScript = new NyqTextCtrl(parent,
|
|
ID_SCRIPT,
|
|
wxEmptyString,
|
|
wxDefaultPosition,
|
|
wxDefaultSize,
|
|
(mAutoWrap ? wxTE_BESTWRAP : wxTE_DONTWRAP) |
|
|
wxTE_NOHIDESEL | wxTE_RICH2 |
|
|
wxTE_MULTILINE);
|
|
s->Add(mScript, 1, wxEXPAND);
|
|
s->Layout();
|
|
|
|
mScript->ChangeValue(text);
|
|
mScript->SetInsertionPoint(pos);
|
|
mScript->SetSelection(from, to);
|
|
|
|
if (focused) {
|
|
mScript->SetFocus();
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnFont(wxCommandEvent & e)
|
|
{
|
|
wxWindow *w = FindFocus();
|
|
wxFontData data;
|
|
wxFontDialog dlg(this, data);
|
|
|
|
if (w != mScript && w != mOutput) {
|
|
return;
|
|
}
|
|
|
|
data.SetInitialFont(w == mScript ? mScriptFont : mOutputFont);
|
|
|
|
if (dlg.ShowModal() == wxID_OK) {
|
|
wxFontData retData = dlg.GetFontData();
|
|
wxFont font = retData.GetChosenFont();
|
|
wxTextAttr attr;
|
|
attr.SetFont(font);
|
|
|
|
if (w == mScript) {
|
|
mScriptFont = font;
|
|
}
|
|
else {
|
|
mOutputFont = font;
|
|
}
|
|
|
|
((wxTextCtrl *)w)->SetDefaultStyle(attr);
|
|
((wxTextCtrl *)w)->SetStyle(0, ((wxTextCtrl *)w)->GetLastPosition(), attr);
|
|
w->Refresh();
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnSplitV(wxCommandEvent & e)
|
|
{
|
|
if (mSplitter->IsSplit()) {
|
|
mSplitter->Unsplit();
|
|
}
|
|
|
|
mSplitter->SplitVertically(mScript->GetParent(), mOutput->GetParent());
|
|
}
|
|
|
|
void NyqBench::OnSplitH(wxCommandEvent & e)
|
|
{
|
|
if (mSplitter->IsSplit()) {
|
|
mSplitter->Unsplit();
|
|
}
|
|
|
|
mSplitter->SplitHorizontally(mScript->GetParent(), mOutput->GetParent());
|
|
}
|
|
|
|
void NyqBench::OnToggleCode(wxCommandEvent & e)
|
|
{
|
|
if (e.IsChecked()) {
|
|
if (mSplitter->IsSplit()) {
|
|
// Should never happen
|
|
return;
|
|
}
|
|
|
|
if (mSplitMode == wxSPLIT_VERTICAL) {
|
|
mSplitter->SplitVertically(mScript->GetParent(), mOutput->GetParent());
|
|
}
|
|
else {
|
|
mSplitter->SplitHorizontally(mScript->GetParent(), mOutput->GetParent());
|
|
}
|
|
}
|
|
else {
|
|
if (!mSplitter->IsSplit()) {
|
|
// Should never happen
|
|
return;
|
|
}
|
|
|
|
mSplitMode = mSplitter->GetSplitMode();
|
|
mSplitter->Unsplit(mScript->GetParent());
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnToggleOutput(wxCommandEvent & e)
|
|
{
|
|
if (e.IsChecked()) {
|
|
if (mSplitter->IsSplit()) {
|
|
// Should never happen
|
|
return;
|
|
}
|
|
|
|
if (mSplitMode == wxSPLIT_VERTICAL) {
|
|
mSplitter->SplitVertically(mScript->GetParent(), mOutput->GetParent());
|
|
}
|
|
else {
|
|
mSplitter->SplitHorizontally(mScript->GetParent(), mOutput->GetParent());
|
|
}
|
|
}
|
|
else {
|
|
if (!mSplitter->IsSplit()) {
|
|
// Should never happen
|
|
return;
|
|
}
|
|
|
|
mSplitMode = mSplitter->GetSplitMode();
|
|
mSplitter->Unsplit(mOutput->GetParent());
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnSmallIcons(wxCommandEvent & e)
|
|
{
|
|
RecreateToolbar(false);
|
|
}
|
|
|
|
void NyqBench::OnLargeIcons(wxCommandEvent & e)
|
|
{
|
|
RecreateToolbar(true);
|
|
}
|
|
|
|
void NyqBench::OnGo(wxCommandEvent & e)
|
|
{
|
|
mEffect->SetCommand(mScript->GetValue());
|
|
|
|
AudacityProject *p = GetActiveProject();
|
|
wxASSERT(p != NULL);
|
|
|
|
if (p) {
|
|
wxWindowDisabler disable(this);
|
|
NyqRedirector redir((NyqTextCtrl *)mOutput);
|
|
|
|
mRunning = true;
|
|
UpdateWindowUI();
|
|
|
|
const PluginID & id = EffectManager::Get().GetEffectByIdentifier(mEffect->GetSymbol());
|
|
p->OnEffect(id);
|
|
|
|
mRunning = false;
|
|
UpdateWindowUI();
|
|
}
|
|
|
|
Raise();
|
|
}
|
|
|
|
void NyqBench::OnStop(wxCommandEvent & e)
|
|
{
|
|
mRunning = false;
|
|
mEffect->Stop();
|
|
}
|
|
|
|
void NyqBench::OnAbout(wxCommandEvent & e)
|
|
{
|
|
wxAboutDialogInfo i;
|
|
|
|
i.AddArtist(_("Harvey Lubin (logo)"));
|
|
i.AddArtist(_("Tango Icon Gallery (toolbar icons)"));
|
|
i.AddDeveloper(_("Leland Lucius"));
|
|
i.SetCopyright(_("(C) 2009 by Leland Lucius"));
|
|
i.SetDescription(_("External Audacity module which provides a simple IDE for writing effects."));
|
|
i.SetName(_("Nyquist Effect Workbench"));
|
|
i.SetVersion(__TDATE__);
|
|
|
|
wxAboutBox(i);
|
|
}
|
|
|
|
void NyqBench::OnFindDialog(wxFindDialogEvent & e)
|
|
{
|
|
wxEventType type = e.GetEventType();
|
|
|
|
if (type == wxEVT_COMMAND_FIND_CLOSE) {
|
|
wxFindReplaceDialog *dlg = e.GetDialog();
|
|
|
|
dlg->Destroy();
|
|
|
|
int flags = mFindData.GetFlags();
|
|
|
|
gPrefs->Write(wxT("NyqBench/Find/Down"), (flags & wxFR_DOWN) != 0);
|
|
gPrefs->Write(wxT("NyqBench/Find/Word"), (flags & wxFR_WHOLEWORD) != 0);
|
|
gPrefs->Write(wxT("NyqBench/Find/Case"), (flags & wxFR_MATCHCASE) != 0);
|
|
|
|
mFindDlg = NULL;
|
|
mFindText = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
wxString text = mFindText->GetValue();
|
|
|
|
#if defined(__WXMSW__)
|
|
// We cheat on Windows. We know that the Windows text control
|
|
// uses CRLF for line endings and if we don't account for that,
|
|
// the selection positions will be off.
|
|
//
|
|
// Not sure why I thought I needed this, but it appears not to
|
|
// be. Leaving just in case.
|
|
//
|
|
// text.Replace(wxT("\n"), wxT("\r\n"));
|
|
#endif
|
|
|
|
size_t startpos = mFindText->GetInsertionPoint();
|
|
size_t len = mFindText->GetLastPosition();
|
|
size_t pos;
|
|
|
|
wxString find = e.GetFindString();
|
|
bool down = (e.GetFlags() & wxFR_DOWN) != 0;
|
|
bool mixed = (e.GetFlags() & wxFR_MATCHCASE) != 0;
|
|
|
|
if (!mixed) {
|
|
text.MakeUpper();
|
|
find.MakeUpper();
|
|
}
|
|
|
|
if (down) {
|
|
pos = text.find(find, startpos);
|
|
if (type == wxEVT_COMMAND_FIND_NEXT && pos == startpos && pos < len) {
|
|
pos = text.find(find, startpos + 1);
|
|
}
|
|
}
|
|
else {
|
|
pos = text.rfind(find, startpos);
|
|
if (type == wxEVT_COMMAND_FIND_NEXT && pos == startpos && pos > 0) {
|
|
pos = text.rfind(find, startpos - 1);
|
|
}
|
|
}
|
|
|
|
if (pos == wxString::npos) {
|
|
wxMessageBox(_("No matches found"),
|
|
_("Nyquist Effect Workbench"),
|
|
wxOK | wxCENTER,
|
|
e.GetDialog());
|
|
|
|
return;
|
|
}
|
|
|
|
mFindText->SetInsertionPoint((long)pos);
|
|
|
|
#if defined(__WXGTK__)
|
|
// GTK's selection and intertion pointer interact where the insertion
|
|
// pointer winds up after the second parameter, so we reverse them to
|
|
// force the pointer at the beginning of the selection. Doing so
|
|
// allows reverse find to work properly.
|
|
mFindText->SetSelection((long)(pos + find.Length()), (long)pos);
|
|
#else
|
|
mFindText->SetSelection((long)pos, (long)(pos + find.Length()));
|
|
#endif
|
|
|
|
#if defined(__WXMAC__)
|
|
// Doing this coaxes the text control to update the selection. Without
|
|
// it the selection doesn't appear to change if the found string is within
|
|
// the currently displayed text, i.e., no reposition is needed.
|
|
mFindText->Show(false);
|
|
mFindText->Show(true);
|
|
#endif
|
|
}
|
|
|
|
void NyqBench::OnTextUpdate(wxCommandEvent & e)
|
|
{
|
|
// This really shouldn't be necessary, but Paste()ing doesn't mark the
|
|
// control as dirty...at least on the Mac.
|
|
((NyqTextCtrl *) e.GetEventObject())->MarkDirty();
|
|
}
|
|
|
|
void NyqBench::OnMenuUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
if (e.GetId() != wxID_REVERT_TO_SAVED) {
|
|
e.Enable((mScript->GetLastPosition() > 0) || mScript->IsModified());
|
|
}
|
|
else {
|
|
e.Enable(mScript->IsModified());
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnUndoUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
e.Enable((FindFocus() == mScript ? mScript : mOutput)->CanUndo());
|
|
}
|
|
|
|
void NyqBench::OnRedoUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
e.Enable((FindFocus() == mScript ? mScript : mOutput)->CanRedo());
|
|
}
|
|
|
|
void NyqBench::OnCutUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
e.Enable((FindFocus() == mScript ? mScript : mOutput)->CanCut());
|
|
}
|
|
|
|
void NyqBench::OnCopyUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
e.Enable((FindFocus() == mScript ? mScript : mOutput)->CanCopy());
|
|
}
|
|
|
|
void NyqBench::OnPasteUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
e.Enable((FindFocus() == mScript ? mScript : mOutput)->CanPaste());
|
|
}
|
|
|
|
void NyqBench::OnClearUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
e.Enable(FindFocus() == mOutput ? true : false);
|
|
}
|
|
|
|
void NyqBench::OnViewUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
wxMenuBar *bar = GetMenuBar();
|
|
bar->Enable(ID_SPLITV, !mSplitter->IsSplit() || mSplitter->GetSplitMode() != wxSPLIT_VERTICAL);
|
|
bar->Enable(ID_SPLITH, !mSplitter->IsSplit() || mSplitter->GetSplitMode() != wxSPLIT_HORIZONTAL);
|
|
bar->Check(ID_TOGGLECODE, mScript->GetParent()->IsShown());
|
|
bar->Check(ID_TOGGLEOUTPUT, mOutput->GetParent()->IsShown());
|
|
bar->Check(ID_LARGEICONS, mLargeIcons);
|
|
bar->Check(ID_SMALLICONS, !mLargeIcons);
|
|
}
|
|
|
|
void NyqBench::OnRunUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
AudacityProject *p = GetActiveProject();
|
|
wxToolBar *tbar = GetToolBar();
|
|
wxMenuBar *mbar = GetMenuBar();
|
|
|
|
if (p && gAudioIO->IsBusy()) {
|
|
mbar->Enable(ID_GO, false);
|
|
mbar->Enable(ID_STOP, false);
|
|
|
|
tbar->EnableTool(ID_GO, false);
|
|
tbar->EnableTool(ID_STOP, false);
|
|
}
|
|
else {
|
|
mbar->Enable(ID_GO, (mScript->GetLastPosition() > 0) && !mRunning);
|
|
mbar->Enable(ID_STOP, (mScript->GetLastPosition() > 0) && mRunning);
|
|
|
|
tbar->EnableTool(ID_GO, (mScript->GetLastPosition() > 0) && !mRunning);
|
|
tbar->EnableTool(ID_STOP, (mScript->GetLastPosition() > 0) && mRunning);
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnScriptUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
if (mScriptBox && mScript && FindFocus() == mScript) {
|
|
wxString label = mScriptBox->GetLabel();
|
|
if (label == _("Script")) {
|
|
label += wxT("*");
|
|
mScriptBox->SetLabel(label);
|
|
mOutputBox->SetLabel(_("Output"));
|
|
}
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnOutputUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
if (mOutputBox && mOutput && FindFocus() == mOutput) {
|
|
wxString label = mOutputBox->GetLabel();
|
|
if (label == _("Output")) {
|
|
label += wxT("*");
|
|
mOutputBox->SetLabel(label);
|
|
mScriptBox->SetLabel(_("Script"));
|
|
}
|
|
}
|
|
}
|
|
|
|
bool NyqBench::Validate()
|
|
{
|
|
if (mScript->GetLastPosition() > 0 && mScript->IsModified()) {
|
|
int ans;
|
|
ans = wxMessageBox(_("Code has been modified. Are you sure?"),
|
|
_("Warning"),
|
|
wxYES_NO | wxICON_QUESTION,
|
|
this);
|
|
if (ans == wxNO) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void NyqBench::SetWindowTitle()
|
|
{
|
|
wxString name = _("Untitled");
|
|
|
|
if (!mPath.GetFullPath().IsEmpty()) {
|
|
name = mPath.GetFullName();
|
|
}
|
|
|
|
SetTitle(_("Nyquist Effect Workbench - ") + name);
|
|
}
|
|
|
|
void NyqBench::RecreateToolbar(bool large)
|
|
{
|
|
mLargeIcons = large;
|
|
|
|
wxToolBar *tb = GetToolBar();
|
|
if (tb) {
|
|
delete tb;
|
|
}
|
|
tb = CreateToolBar();
|
|
|
|
wxSize sz;
|
|
|
|
if (!mLargeIcons) {
|
|
tb->SetToolBitmapSize(wxSize(16, 16));
|
|
mPics[0] = wxBitmap(document_new_small);
|
|
mPics[1] = wxBitmap(document_open_small);
|
|
mPics[2] = wxBitmap(document_save_as_small);
|
|
mPics[3] = wxBitmap(document_save_small);
|
|
mPics[4] = wxBitmap(edit_copy_small);
|
|
mPics[5] = wxBitmap(edit_cut_small);
|
|
mPics[6] = wxBitmap(edit_paste_small);
|
|
mPics[7] = wxBitmap(edit_clear_small);
|
|
mPics[8] = wxBitmap(edit_delete_small);
|
|
mPics[9] = wxBitmap(edit_select_all_small);
|
|
mPics[10] = wxBitmap(edit_undo_small);
|
|
mPics[11] = wxBitmap(edit_redo_small);
|
|
mPics[12] = wxBitmap(edit_find_small);
|
|
mPics[13] = wxBitmap(system_search_small);
|
|
mPics[14] = wxBitmap(go_top_small);
|
|
mPics[15] = wxBitmap(go_up_small);
|
|
mPics[16] = wxBitmap(go_previous_small);
|
|
mPics[17] = wxBitmap(go_next_small);
|
|
mPics[18] = wxBitmap(media_playback_start_small);
|
|
mPics[19] = wxBitmap(media_playback_stop_small);
|
|
}
|
|
else {
|
|
tb->SetToolBitmapSize(wxSize(32, 32));
|
|
mPics[0] = wxBitmap(document_new_large);
|
|
mPics[1] = wxBitmap(document_open_large);
|
|
mPics[2] = wxBitmap(document_save_as_large);
|
|
mPics[3] = wxBitmap(document_save_large);
|
|
mPics[4] = wxBitmap(edit_copy_large);
|
|
mPics[5] = wxBitmap(edit_cut_large);
|
|
mPics[6] = wxBitmap(edit_paste_large);
|
|
mPics[7] = wxBitmap(edit_clear_large);
|
|
mPics[8] = wxBitmap(edit_delete_large);
|
|
mPics[9] = wxBitmap(edit_select_all_large);
|
|
mPics[10] = wxBitmap(edit_undo_large);
|
|
mPics[11] = wxBitmap(edit_redo_large);
|
|
mPics[12] = wxBitmap(edit_find_large);
|
|
mPics[13] = wxBitmap(system_search_large);
|
|
mPics[14] = wxBitmap(go_top_large);
|
|
mPics[15] = wxBitmap(go_up_large);
|
|
mPics[16] = wxBitmap(go_previous_large);
|
|
mPics[17] = wxBitmap(go_next_large);
|
|
mPics[18] = wxBitmap(media_playback_start_large);
|
|
mPics[19] = wxBitmap(media_playback_stop_large);
|
|
}
|
|
|
|
tb->SetMargins(2, 2);
|
|
|
|
tb->AddTool(wxID_NEW, _("New"), mPics[0], _("New script"));
|
|
tb->AddTool(wxID_OPEN, _("Open"), mPics[1], _("Open script"));
|
|
tb->AddTool(wxID_SAVE, _("Save"), mPics[2], _("Save script"));
|
|
tb->AddTool(wxID_SAVEAS, _("Save As"), mPics[3], _("Save script as..."));
|
|
tb->AddSeparator();
|
|
tb->AddTool(wxID_COPY, _("Copy"), mPics[4], _("Copy to clipboard"));
|
|
tb->AddTool(wxID_CUT, _("Cut"), mPics[5], _("Cut to clipboard"));
|
|
tb->AddTool(wxID_PASTE, _("Paste"), mPics[6], _("Paste from clipboard"));
|
|
tb->AddTool(wxID_CLEAR, _("Clear"), mPics[7], _("Clear selection"));
|
|
tb->AddTool(wxID_SELECTALL, _("Select All"), mPics[9], _("Select all text"));
|
|
tb->AddSeparator();
|
|
tb->AddTool(wxID_UNDO, _("Undo"), mPics[10], _("Undo last change"));
|
|
tb->AddTool(wxID_REDO, _("Redo"), mPics[11], _("Redo previous change"));
|
|
tb->AddSeparator();
|
|
tb->AddTool(wxID_FIND, _("Find"), mPics[12], _("Find text"));
|
|
tb->AddSeparator();
|
|
tb->AddTool(ID_MATCH, _("Match"), mPics[13], _("Go to matching paren"));
|
|
tb->AddTool(ID_TOP, _("Top"), mPics[14], _("Go to top S-expr"));
|
|
tb->AddTool(ID_UP, _("Up"), mPics[15], _("Go to higher S-expr"));
|
|
tb->AddTool(ID_PREVIOUS, _("Previous"), mPics[16], _("Go to previous S-expr"));
|
|
tb->AddTool(ID_NEXT, _("Next"), mPics[17], _("Go to next S-expr"));
|
|
tb->AddSeparator();
|
|
tb->AddTool(ID_GO, _("Start"), mPics[18], _("Start script"));
|
|
tb->AddTool(ID_STOP, _("Stop"), mPics[19], _("Stop script"));
|
|
|
|
tb->Realize();
|
|
|
|
Layout();
|
|
Fit();
|
|
SetMinSize(GetSize());
|
|
}
|
|
|
|
void NyqBench::LoadFile()
|
|
{
|
|
wxString path = mPath.GetFullPath();
|
|
|
|
if (path.IsEmpty()) {
|
|
return;
|
|
}
|
|
|
|
wxFFile f(path);
|
|
if (f.IsOpened()) {
|
|
wxString t;
|
|
if (f.ReadAll(&t)) {
|
|
//#if defined(__WXGTK__) || defined(__WXMAC__)
|
|
t.Replace(wxT("\r\n"), wxT("\n"));
|
|
t.Replace(wxT("\r"), wxT("\n"));
|
|
//#elif defined(__WXMSW__)
|
|
// t.Replace("\r\n", "\n");
|
|
//#endif
|
|
mScript->SetValue(t);
|
|
mScript->DiscardEdits();
|
|
}
|
|
}
|
|
|
|
// mScript->LoadFile(mPath.GetFullPath());
|
|
}
|