Conventions for Nyquist Plug-ins

Steve and I discussed off Forum about having a Wiki page (probably linked to off Nyquist Audio Programming ) that listed the GUI and code conventions expected in plug-ins listed on Download Nyquist Plug-ins and in Nyquist plug-ins distributed inside Audacity.

Although we want to be most strict with plug-ins distributed in Audacity, we don’t want to discourage plug-in writers by being overly prescriptive, after all if a plug-in is “elevated” to distribution in Audacity, changes can be made at the time by the person committing the plug-in.

Anyway, I just started this thread in case we want to keep together any comments here before we start a Wiki page about “conventions”. One thing I noticed in recent commits is that Vaughan is standardising capitalisation of titles of effect controls so that nouns are capitalised. I think we weren’t quite sure if we should do this in Nyquist plug-ins, but I would suggest it would be good practice to do so from now on. So for example in Paraic’s 78 rpm Curve Generator (which will at least be officially linked to) the final control would be “XML File Output Path” (if we kept that wording for it).

A lot of Nyquist plug-ins already distributed in Audacity don’t follow this capitalisation convention, but that can be changed when they are modified.




Gale

Providing help

Here are some suggested ideas about “providing help”.

Help text on the ;info line should be reasonably limited; generally if it exceeds five lines, it may be too verbose.

If the plug-in is to be added to those distributed in Audacity releases, any ;info line text which explains the plug-in should be minimal, to accord with practice in built-in plug-ins.

More extensive help can be provided in a text file to be included with the plug-in file, or in “Help Screens” which can be selected via a control in the plug-in. Help Screens (where necessary) should be used if a plug-in is to be distributed inside Audacity. Text for each help screen should have a forced newline (n or hit ENTER) at 50 characters. A new paragraph should be created by nn or ENTER twice. The maximum number of lines per screen is 25 lines, including empty lines. These conventions keep formatting as neat as possible at both 800 x 600 and very high resolutions where Nyquist message boxes may extend to 260 characters wide (See https://forum.audacityteam.org/t/searching-for-an-effect/192/1).

Plug-ins for distribution inside Audacity will be documented in the Manual. The extent of this documentation depends on the extent of help provided in the Help Screens. The Manual is a reference rather than a “how-to”, so if short descriptions of controls are the only help needed, consider putting this documentation in the Manual and not including Help Screens. If the plug-in needs extensive examples of how to use the plug-in to achieve the desired result, that would require Help Screens.





Gale

The user’s home directory is the appropriate place to write output data from Nyquist, for example a text file.

On all operating systems supported by Audacity, get-env can be used

(or (get-env "HOME") (get-env "UserProfile"))

to return the user’s home directory.

See https://forum.audacityteam.org/t/disabled-features/201/1 for details and the discussions that led up to it.

Note that Nyquist in Audacity currently cannot read environment variables containing non-ASCII characters. Therefore it may not return the correct directory in localised operating systems where the home directory contains non-ASCII characters.

The full format for the header information is as follows:

;nyquist plug-in
;version version
;type type
;name "name"
;action "text"
;categories "text"
;info "text"
;control parameters
;codetype type
;debugflags flags

Of these, the first four are obligatory, so the minimum header must contain:

;nyquist plug-in
;version version
;type type
;name "name"

I propose that the convention for “general release” plug-ins should also include “action” and “categories”.

“action” is the text that is displayed while the plug-in is processing. If the processing is very quick then this is not displayed, though I would suggest that it is still a useful convention as (a) all current plug-ins use it, so it IS the current convention, (b) it may give a useful clue at to what the plug-in does for anyone examining the code, (c) if for any reason processing takes longer than expected, the process indicator will be displayed.

“categories” is not currently used in Audacity, though I believe that the intention is to reintroduce categories in the future, therefore I propose that the categories text should be included as a matter of convention.

“codetype” MUST be included if the plug-in is written in SAL.
If the “codetype” is missing, Lisp is assumed by default. Most currently available plug-ins are written in Lisp and do not have the “codetype” line.

I’m unclear about the “;debugflag” line, in plug-ins it does not appear to do anything :confused:

Full documentation of the plug-in header can be found here: http://www.audacity-forum.de/download/edgar/nyquist/nyquist-doc/devel/audacity-nyquist-en.htm

Agreed. I think this is the link to LV2 category types which are recognised by Audacity’s built-in plug-ins and by Nyquist and LADSPA plug-ins.

Plug-ins are not currently sorted unless you compile Audacity with EFFECT_CATEGORIES defined.

Is this in SVN HEAD? If you recall this was discussed with Roger last month after he committed r10785. That fixed the problem that once you clicked the Debug button in a Nyquist effect, it would then always run in Debug in that session even if the user clicked OK.

However the fix means that “debugflags” now has no effect if there is a dialogue box for the effect - “OK” will always run the effect without debug and “Debug” will always show the Debug window. Although Roger said this was the “most unsurprising” behaviour, I think if a plug-in author has chosen to use “debugflags” that should be respected even if there is a dialogue (meaning that pressing “OK” or “Debug” gives you debug). Of course, I would expect the plug-in author to note the behaviour in the plug-in.

If we both agree, I think Roger would be amenable to have debugflags force debug even if user clicked OK.



Gale

Yes, and that is a subset of Missing Page
(subcategories of “plugin” in LV2 only. So, for example, “lv2:Template” is not used in Audacity)

Thanks, I missed that one (extremely busy at work) - I’ll look it up and investigate.

The first two sentences in the ;info line should be the primary authorship of the plug-in, followed by “Released under” to provide the licensing. The licence must be GPL v2 ( or compatible with GPL v2) to be distributed in Audacity and to be hosted on this Forum or on other Audacity sites.

For example:

   
;info "By Steve Daulton and Bill Wharrie. Released under GPL v2."

If the plug-in is a significant derivation from some other primary author’s work, consider attributing that person by using “after” in the first sentence:

   
;info "By Steve Daulton, after [plug-in] or [type of work] by David Sky". Released under GPL v2."

In the comments in the .ny file, give fuller authorship, date and licensing details as in this example:

;; notch.ny by Steve Daulton and Bill Wharrie, September 2010
;; Released under terms of the GNU General Public License version 2
;; http://www.gnu.org/licenses/old-licenses/gpl-2.0.html

Full details of credits and changelogs can be also be added here.




Gale

One plug-in that immediately comes to mind is “apropos.ny” Audacity and Nyquist
setting “;debugflags trace” seems to work in Audacity 1.3.12 on XP, but only partially works in Audacity 1.3.12 on Linux (shows debug window only the first time it is run), and does not work at all in Audacity 1.3.13 on Linux.

OK, I’ve asked Roger (Cc’d to you) if he can make ;debugflags trace force debug in GUI plugins even when you hit OK.



Gale

To accommodate the minimum Audacity-supported resolution of 800x600, the plug-in interface should have a maximum of 12 controls assuming there was only a single line of ;info text. For two or three lines of ;info text, maximum number of controls is 11, for four or five lines, maximum controls is 10 and so on.



Gale

If possible, there should be a comment near the top of the plug-in code to indicate the minimum Audacity version required.

A suitable location could be directly below the copyright notice.

Plug-in comment block.

It will be generally useful if the following information can be included within the plug-in header section:

;; <Plug-in name> by <author> <date>
;; <additional credits>
;; Released under terms of the GNU General Public License version 2
;; http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 
;; <additional notes>
;; <release notes>
;; Audacity version requirements.

It is recommended that the license terms are also briefly mentioned in the ;info line of the header.
For example:

;info "By <author's name>nReleased under GPL v2

If the license terms are not GNU General Public License version 2, then it is highly recommended that the plug-in notes this in the plug-in interface as well as in the comment block.

A typical Nyquist plug-in header might look something like this:

;nyquist plug-in
;version 3
;type process
;name “My Effect”
;action “Processing…”
;info "By A.Person > http://mydomain.comnReleased > under GPL v2

;; my-effect.ny by A.Person April 2011
;; Pre-process function by A.N.Other
;; Released under terms of the GNU General Public License version 2
;; > GNU General Public License v2.0 - GNU Project - Free Software Foundation >
;; Thanks to J.Doe for writing the help file.
;; v 0.1 January 2011
;; v 0.2 February 2011: Includes stereo track support.
;; v 1.0 April 2011: Add compatibility for Audacity 1.3.4
;; Requires Audacity 1.3.4 or later

;control …
;control …

;categories
This optional line turns on plug-in categories. Categories are only experimentally implemented, so not available in builds currently released by Audacity. Users who can compile Audacity can turn on categories by uncommenting #define EFFECT_CATEGORIES in src/Experimental.h, but the feature may be subject to change in the future.

If you include the ;categories line, it should be in the form:

;categories "<URI>"

where is one of the LV2 or Additional Audacity-Specific categories listed inside quotation marks on
Missing features - Audacity Support .

;control variables:

As it is likely that Nyquist plug-ins will be available in Chains in the very near future, the variables used in the ;control widgets will be exposed to users.
It is therefore recommended that the ;control variable names should be humanly readable.

For example:
Select Command_002.png
Select Command_003.png

Indentation:

It is recommended that code indentation is applied using spaces rather than tabs. When viewed in a text editor, tabs will be displayed according to the tab setting in the editor, which may be set very differently from the settings in the editor that was used to write the code, so the layout may be very different from what was intended.

Indentation is very important for the readability of Lisp code. There is a concise guide to the proper way to indent Lisp code here: Indenting Common Lisp

As of Audacity 2.0.1 Nyquist “process” effects are available in Chains.

For effects that are likely to be used on a single file it is often helpful, in the event of invalid user input, to cancel processing and return an error message so that the user can see what they have done wrong. However, for batch processing a large number of files this could be inconvenient, so when designing plug-ins that are likely to be useful for batch processing it may be worth considering how best to handle error messages. One possibility would be to provide a user control to select whether or not to show errors, for example:

;control messages "Show messages" choice "Yes,Errors Only,None" 0

And then, handle the error message with something like:

(if (and (> (length error-message) 0)
         (= messages 2))
  (s-rest 0)
  (if (> (length error-message) 0)
      (format nil "Error.~%~a" error-message)))

What this does is to check the length of ‘error-message’ [which would be initialised to 0 to indicate no errors], and to check the status of ‘messages’.
If (length error-messages) is greater than 0 [there are errors] and ‘messages’ is set to 2 [don’t show error messages] then a null sound is returned, thus suppressing any error messages and not processing the sound.
If ‘messages’ is not set to 2 and there are errors, they will be displayed.

A few, hopefully useful, examples:

;; Line up the bindings in LET special form
(let* ((symbols (mapcar #'compute-symbol l))
       (spaces (mapcar #'compute-space symbols (cdr symbols))))
  (when (verify-spacing symbols spaces)
    (make-spacing permanent spaces)))



;;; Three semicolons often used to explain a function.
(defun f (x)
  (when (< (g x) 3)
    (h x 2)))



;; Line up the bindings in DO special form
;; and line up the test expression with the first binding
(do ((i 1 (1+ i))               ; first binding
     (j (length l) (/ j 2)))    ; second binding
    ((= j 0) i)                 ; test expression and result value
  (iterate i j)                 ; body of DO loop
  (when (= (f x) 4)
    (setf *level-number* 0)))   ; end of DO loop



;; Put test expression on same line as WHEN or UNLESS special forms.
;; If multiple expressions, indent and align.
(when (= (f x) 4)
  (setf *level-number* 0)
  (unless *do-not-reinitialize*
    (reinitialize-global-information x)
    (reinitialize-local-information))
  (top-level x))



;; Indenting and commenting an IF statement.
(if (< (g x) 2)       ; is it sufficiently small?
    (top-level x)     ; if so, abandon everything
    (h y))            ; otherwise try again

I write my code in the common-or-garden Notepad text editor. Notepad ++would of course be a better choice, but a lot of functions are not accessible for visual impaired people and a lot of times the screen reader skips over some lines.
OK, so the editor is my choice for programming.
What is really annoying: when I open a Plug-in from the Audacity distribution or from this Web page, all line breaks are discarded by the editor. I always have to copy the content to word and copy it back again into the editor. Would it be a draw-back for the other platforms to use the Windows Standard for line-breaks? Besides, Notepad++ knows such a menu point for this conversion.
I do not use indentations, when I am writing code, for the simple reason that the navigation is much easier for me in this way. I am fully aware that other people could profit from a proper indenting when reading the code.
I wonder if not a plug-in could be written, that inspects and corrects a user-written plug-in. It could execute such tasks as:

  • control the header for the right order and if a line is missing.
  • examine the number of characters in a quoted string from the header (< 50)
  • look for the ratio of info-lines and controls.
  • write all keywords (like those found with Edgar’s Apropos plug-in) in upper case.
  • setting the right number of semicolons.
  • apply indentation for Defun let do if etc.
    How do you think about this proposal? Any suggestions?
    Best regards

NotePad is a very primitive text editor.
Wikipedia states “most modern editors can read and write files using at least the different ASCII CR/LF conventions. The standard Windows editor Notepad is not one of them.”

Personally I don’t think that plug-in authors should be required to convert their plug-ins into Windows format simply because the default Windows text editor can’t handle CR or LF.

On Windows XP, a simple way to convert the new lines to CR+LF (Windows format) is to open the file in WordPad then save it. I’ve not tested in later versions of Windows.

Alternatively, new lines may be converted to Windows format from the command line using:

TYPE unix-file-name | FIND "" /V > dos-file-name

There is also a program called CrLf by Joachim Gehweiler that can convert the new line format http://audionyq.com/?p=182 This is a JAVA program that requires JAVA to be installed on the computer.

Of these, opening in WordPad and then saving is probably the easiest and quickest.

That’s completely understandable. Good indentation helps readability for sighted users but clearly of no help at all for visually impaired users. David Sky (who was blind) never used indentation in any of his plug-ins.

I think that would be very difficult to implement.
Nyquist is not very good at manipulating text - that’s not what the language was designed for. Checking the syntax for every function and macro would require a huge amount of code and in my opinion would not be worth the effort.

Keywords are generally best written in lower case as editors that provide LISP syntax highlighting usually require lower case keywords.

That works fine in Windows 7 (and so presumably would also work in Vista as well)

@Peter (PGA) - I deleted your post as requested where the quote added “word rejected”. How did you add the quote? It looked as if that message just became corrupted somehow.


Gale