Welcome to SMCore documentation

by Sylvain Machefert

Table of contents

  1. What is SMCore?
  2. About the documentation
    1. Types
    2. Navigate the doc
  3. How to use SMCore in your scripts?
  4. Quick start
    1. Collection
    2. Map
    3. CSV
    4. SMDialog
  5. Version history
  6. About the author

What is SMCore?

SMCore is a set of functions and classes written in Lua 4.0 / MyrScript, the scripting language embedded in Harmony Assistant, music software created by Myriad Software,

Current version is: 20250501.

Update announcements are published in this topic on Myriad forum.
Use this topic for bug report, suggestions, questions.

Special thanks go to Danièl Frouvelle who published a lot of scripts, helped me to start in MyrScript dev, and whose source code is old-school hard-coded but efficient.
This gives me idea of "industrialize" button creation in dialog interface, an then I could go further into more complex componants such as Slider, Spinner and Grid.

SM are my initials, and Core means that these libraries are usable in all my scripts, and shared here for others scripts creators.

Here is the list of .mys files that will be installed into Scripts/Includes directory.
You don't have to modify them, unless you are crazy developper and want to help me fix a bug.

  • SMUtils.mys: Probably the first and only one you need to include. It includes: MSDefine, SMJavaCollections, SMLogger, SMStrings, SMTables and SMTheory.
    It contains unsorted but essential functions for manipulating MyrScript objects such as Target or Dynamic, start play from a bar...
    Also essential, all assertions functions to protect your scripts, see Assertions section.
    And more!
  • SMCore.mys: run once after SMCore update, performs unit tests (ensure that new version won't break old results). Tests can print a lot in console.
  • SMCore-Updater.mys: check and update SMCore.
  • SMCSV.mys: read and write CSV files, use table, Collection and Map.
  • SMDialog.mys:- create user interface like Danièl, but easier, and add complex components. Assist you in translating the user interface.
  • SMGraph.mys: simplify picture and text drawings and polygon creation for Graph, Surface operations...
  • SMInstruments.mys: instrument or sound picker (selector), instrument properties.
    Visit the online instrument database to explore informations you can obtain in this file.
    Note that it's still under development.
  • SMJavaCollections.mys: a rewrite of Java's Collection and Map, with essential features.
    • Collection is a table that can perform sort, search, insert and delete, unique. They are browsable in ascending or descending order.
    • Map is an association between key and value. Key is guaranteed to be unique, and is backed by a Collection. One key has one value, they can't be nil.
  • SMLexicon.mys: extends Dialog.Translate.
  • SMLogger.mys: allow you to print debug, info, warning or error message into Console or into a log file. By default, debug is only printed when writing your script, info, warn and error are always.
    Don't worry anymore of left print("debugging message") when your scripts are published!
  • SMMenu.mys: create menus in your script, for a multiple or single choice, or fully customized multi-level menu with switches and functio calls.
  • SMStrings.mys: useful string manipulation functions.
  • SMStructureReader.mys: read (a bit in a wild manner) some textual .cfg files of Harmony, e.g. keyboards (.kbd files)
  • SMTheory.mys: Chord and Interval objects that understand chords, calculate notes of an interval... All about solfege goes here.
  • other files are:
    • interfaces (.myc) used by some functions,
    • Translations (*lex*.txt)
    • Internal use for new version download, unit tests.

About the documentation

This documentation is generated from the source code by a home made program, inspired by luadoc syntax. Even for me, it's easier to read and navigate this HTML version than open all my files and read the comments! 😊

Types

Lua native types are nil, string, number, table and function. In the documentation, I added int when a number is expected to be an integer. This is not Lua standard, but may help you in reading. Integer are often used by constants, such as FACE_BOLD, ALIGN_RIGHT, INSTR_VIOLIN, or can refer to a table index, a char in a string (e.g. strsub("my string", a, b), a MIDI note pitch...
number reflects a possible decimal value like a frequency (in Hz), a percentile...

Lua has no real boolean, true = 1 and false = 0, they are numbers, but when an argument is expected to be a boolean, his type is: boolean.

MyrScript objects have a small Harmony Assistant icon, e.g.: Dialog, Score, Staff.

SMCore Objects have a "C" icon, for Class: CSV, Interval, SMDialog, Collection.

SMCore table structures have their own icon too: Dialog.UserTable, Component, Grid.

Navigate the documentation

Left navigation pane

  • Files show the content of each file: constants, classes, global functions.
  • Classes and Tables show their fields and functions.
  • Sections are convenient indexes that group together functions related to the same item, MyrScript object, or feature, e.g. Staves, Play, Strings, Tables..., even if they are not in the same file.
    A function can be present in more than one section

How to use SMCore in your scripts?

Copy/past this code at the beginning of your script, or in the function Init(dialog) of floatting window or interface composer file

-- download/update SMCore
Include "SMCore-Updater"
SMCoreRequireVersion(20250501)

SMCoreRequireVersion(20250501) download all SMCore files if needed (never downloaded or outdated) and then performs unit tests that may print a lot in Console.

It's done only once per version released. If you see error message in the Console, please report the issue in this forum topic.

When I'll submit updates and bugfix, the version number 20250501 to write as argument will change, you'll see it on top of this page and in the forum topic.
Other scripts that require an older version of SMCore don't need this light change, I'll do my best to keep compatibility.

After this, your script continues.
Include files you need. You can include first SMUtils add an IncludeOnce(...) function that optimize including of file, avoid double inclusion that may consume CPU if included file perform heavy tasks..
Example:

Include "SMUtils"
IncludeOnce("SMDialog")

Notes:

  • the parenthesis required for IncludeOnce(...) and not for Include "SMUtils".
  • When you Include "SMUtils", MSDefine, SMJavaCollection, SMLogger, SMLexicon, SMStrings and SMTheory are also included. These are quite light, and massively used everywhere in the library.
  • SMMenu, SMDialog and the heavy SMInstruments are not included, as most of your scripts won't require them.
  • SMInstruments is so heavy that it takes 40 seconds in debug mode to load, displaying a progress bar, plus 20 secondes to build a cache. Next loads in debug mode take 10 seconds. Cache is rebuild if you change language settings and at SMCore updates.
    In Run mode, first load is about 1 second, and cache load is around 50 milliseconds.

Quick start

Collection

Unsorted collection

-- create an unsorted Collection.
-- Elements are stored in the insertion order
local fruits = Collection:new()
fruits:add("banana")
fruits:add("apple")
print(fruits:contains("apricot")) --> nil or false
print(fruits:indexOf("apple")) --> 2
fruits:insert("banana") -- allow multiple bananas
print(fruits:lastIndexOf("banana")) --> 3
print(fruits:remove("cherry")) --> 0, there were no cherry in Collection
-- Browse 
fruits:iterator()
while fruits:hasNext() do print(fruits:next()) end
--> banana, apple, banana

Set: a collection of unique elements

local set = Collection:new("string", true)

Sorted set: unique elements are sorted

local sortedSet = Collection:new("string", true, SORT_ASCENDING)

Elements are typed

Like in Java, I appreciate to have typed element, i.e. if I expect strings, it throws an error when inserting something else, else it's a nightmare to debug. A special value "mixed" is available, but here it's intentional and you have to check the type of each item before performing string functions, number for arithmetics...
Here is a sorted set of numbers:

local numbers = Collection:new("number", true, SORT_ASCENDING)
--numbers:add(3.14); numbers:add(1); numbers:add(-1.234)
numbers:add(3.14, 1, -1.234) -- equivalent to above commented line
numbers:debug()
--> print a nice structure showing that the collection is sorted

Map

A Map of number keys associated with string values

local numbers = Map:new("number", "string", SORT_ASCENDING)
numbers:put(3.14, "pi")
numbers:put(1.41, "sqrt(2)")
numbers:put(-3.14, "-pi")
numbers:put(12, "carbone")
numbers:put(14, "carbone")
 
print(numbers:containsKey(1.41)) --> true
print(numbers:containsKey(13) --> nil or false
numbers:containsValue("pi") --> true
print(numbers:get(12)) --> "carbone"
print(numbers:firstKey()) --> -3.14, the lowest number
 
-- iterate over the keys
local ks = numbers:keySet()
ks:iterator()
while ks:hasNext() do print(ks:next()) end
--> -3.14, 1,41, 3.14, 12, 14
 
-- iterate over values, in the same order of the keys
local v = numbers:values()
v:iterator()
while v:hasNext() do print(v:next()) end
--> -pi, sqrt(2), pi, carbone, carbone

-- iterate over entries (key,value) 
numbers:iterator()
while numbers:hasNext()
	local k,v = numbers:next()
	-- print or whatever you want
end

numbers:remove(12)

CSV file read and write

Only write and read strings. Number can be converted using tonumber(...) if needed.

local csv = CSV:new("file.csv", "w")
csv:writeHeader("ID"); csv:writeHeader("Name")
-- write using a standard table
csv:writeLine({"42","Sylvain"})
 
-- write using a Collection
local data = Collection:new("string")
data:add("123"); data:add("Didier")
csv:writeLine(data)
 
-- write using a Map
data = Map:new("string", "string")
data:put("ID", "456"); data:put("Name", "Olivier")
csv:writeLine(data)
 
csv:close() -- important!

-- And now, read!
local csv2 = CSV:new("file.csv", "r")
-- Reading row by row
data = csv2:readLine()
while data~=nil do
      data:print()
      local id,name = data:get("ID"), data:get("Name")
      data = csv2:readLine()
end
csv2:close()

SMDialog

See SMDialog for minimal code to copy/past in your floatting window or interface composer

Version history

2025-05-01 (HA v9.9.9e):

  • Functions for Targets (rehearsal marks).
  • CopyOrnaments: portamento wasn't copied.
  • MidiGetEventFiltered function optimization for Midi.GetEvent
  • SMDialog: Midi navigation and value change using pitch bend and controllers from hardware
  • SMDialog and menu: minor accessibility fixes.
  • Stopwatch class
  • TableToElements(table) replacement for bogus MSLibrary PushAllTableElts(table),
    and its counterpart ElementsToTable(...)
  • Reflection functions.
  • BinNot(...) bitwise NOT operation, and conversions to/from hexadecimal and binary numbers greater than 32-bit.
  • INI file read and write
  • Bars utility functions for global bar settings, splitting, bar numberings

2025-01-24 (HA v9.9.9):

  • SMCore is now included at Harmony Assistant v9.9.9 install.
  • Collection and Map:
    • code optimizations and more precise type-protection,
    • plain text search and regexp search
    • Map:removeAll(...)
  • 540+ instruments in database
  • SMDialog components:
    • OnInit(...) and OnExit(...) events to open and close resources.
    • new Switchable component: checkbox, radio or switch
    • new Knob component: resizable and accessible knobs
  • Lexicon:addEntries(...) for simple script with few entries that won't require small lex_*.txt files.
  • Free objets functions: CopyFreeObjects(...), InsertReservedPages(...), DeleteReservedPages(...)
  • Serialization/Deserialization (kind of JSON for Lua) and class introspection,
  • Batch processing mechanism

2024-09-14

  • Menu: a switch change can be stopped (e.g. by a confirmation rejected).
  • Ternary IF(expr, a, b) and table_insert_multi(myArray, data1, data2) function.
  • Function for StavesGroup: GetStavesGroup(score[, staff]), ChooseStavesGroup(...).
  • JumpAndSelectBar: a better replacement to score.JumpToBar(...).
  • Lexicon: a default language can be forced to French e.g. if a script is not translated in Spanish when HA interface is in Spanish, when French is more understood than English.
  • Score appearance (display setup): load and save settings
  • GetFilesInfolder(...): a fixed and simplified version of BrowseFolder(...).
  • XYSlider: improved value rounding, fixed axis position and keyboard interactions.
  • XYSlider: added a mask to display values with unit or other words instead of raw x, y values.

2024-08-25

  • SMInstruments: bug fix when Gold Base II is not the current sound base.
  • SMInstruments: database improvement, string courses, ranges, and more instruments.
  • SMGraph: CropSurface(...).
  • SMDialog: XYSlider, 'buttons' renamed to 'components' in docs and function names.
  • SMMenu.
  • Various Inputs: ChooseFont(...), ChooseStaves(...)...
  • SMUtils: boolean operations, flags.

2023-11-30: major release

  • IncludeOnce(...) avoid CPU comsuptions when Include(...) multiple time a heavy script.
  • Durations conversions: 256th of quarter to milliseconds, milliseconds to % of a note, etc...
  • GetDynamicsThatApplyToStaff: dynamics may apply to merged staves, group, or whole score. So which ones apply to a specified staff?
  • Collection now accept sorting function for table, but still can't guarantee unicity.
  • SMGraph: DrawPicture(...) (demo script)
  • SMGraph: DrawText(...)
  • SMDialog: Grid is now functionnal (demo script)
  • SMDialog: Spinner, a component that act like a menu or a list, but use less space, display 2 arrows for previous/next value, and accept mouse scroll
  • SMInstruments: Beta version of a database about instruments, classifications (orchestra, midi, alphabetic...) and their related sound
  • SMInstruments: Beta version of a picker to choose an instrument or a sound
  • SMTheory: music theory (solfege), Chord and Interval objects
  • SMUtils: assertion functions: easily protect argument and throw understable standadirzed error messages
  • SMLogger: old logs (more than 30 days) are removed from log files

2022-11-10

  • Documentation has been moved here and improved.
  • SMDialog: keyboard navigation
  • SMDialog: added Slider and preview of Grid

2022-06-16

  • First version of SMDialog
  • Added switch case functions, more for educational purpose than real use
  • Collection and Map simultaneous (concurrent) iterators

2022-05-26

  • First documentation
  • argument checks
  • Removed debugs in Collection:retainsAll(...)

2022-05-16: initial version

About the author

I have more than 20 years in Java programming. This influences the way I program: I discovered the object-oriented light but real capabilities of Lua and I exploited them to translate Java popular classes Collection and Map.

I discovered Harmony Assistant in 2000, contributed in beta-testing and features suggestions. I offer training services on Myriad products.
Since 2024, I also offer reharsal score and audio for choirs, professional quality prints, musical Braille transcription.

As musician, I play chromatic accordion, piano, keyboard, organ, flutes, drums and try sometimes other instruments.
I love traditional and world music, I specialized in Balkan and Eastern Europe music.
With my bands, I play klezmer music, French variety, South American and Angolan music.
I also played in reggae backing band and "morrocan spicy" rock.

Links