Welcome to SMCore documentation

by Sylvain Machefert

Table of contents

  1. What is SMCore?
  2. How to use SMCore in your scripts?
  3. Quick start
  4. Version history
  5. 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: 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.

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

2022-11-10

2022-06-16

2022-05-26

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.

Links