Welcome to SMCore documentation
by Sylvain MachefertTable of contents
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: 20231130.
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.
- 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.
- SMInstruments.mys: instrument or sound picker (selector), instrument properties.
- 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 leftprint("debugging message")
when your scripts are published! - 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)
- SMTables.mys: some useful table functions.
- SMTheory.mys: Chord and Interval objects that understand chords, calculate notes of an interval... All about solfege goes here.
- SMUtils.mys:
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. - other files are non-significant for your scripts, they are use for download and unit tests once updated.
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 core local coreUpdater = GetSystemSettingsPathName("Scripts/Includes").."SMCore-Updater.mys" local downloadCore = false if FileExist(coreUpdater)==false then coreUpdater = GetUserSettingsPathName("Scripts/Includes").."SMCore-Updater.mys" if FileExist(coreUpdater)==false then downloadCore = true; end end if downloadCore==true then print("SMCore libraries not found.") print("Downloading SMCore-Updater.mys...") local errorCode = Internet.DownloadFile( "sylvain-machefert.myriad-users.com", "archive/scripts/SMCore/SMCore-Updater.mys", coreUpdater) assert(errorCode==0, "Error occured while downloading. Error code: "..tostring(errorCode)) local file,errorMsg = OpenFile(coreUpdater, "r", UNKNOWN_STR_ENCODING, UNKNOWN_CR) if file then local line = file.Read("l") while line do assert(strfind(line,"404 Not Found ",1,1)==nil,"404 Not Found"); line=file.Read("l"); end file.Close() else error(errorMsg); end end Include "SMCore-Updater" SMCoreRequireVersion(20231130)
This code checks if SMCore-Update.mys exist, or download it.
Then it includes it.
SMCoreRequireVersion(20231130)
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. 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 20231130
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("SMStrings")
Note the parenthesis required for IncludeOnce(...)
and not for Include "SMUtils"
.
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
ike in Java, I appreciate to have typed element, i.e. my collection must contain only string, or number, but not a mix!
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: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
2023-11-30: major release
IncludeOnce(...)
avoid CPU comsuptions whenInclude(...)
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.
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.