<?xml version="1.0" encoding="UTF-8"?>

<panel name="Reface Mastertune" panelShowDialogs="1" panelMessageTime="10000"
       panelAuthorName="Martin Tarenskeen" panelAuthorEmail="m.tarenskeen@kpnmail.nl"
       panelAuthorUrl="http://ctrlr.martintarenskeen.nl" panelAuthorDesc=""
       panelVersionMajor="1" panelVersionMinor="0" panelVersionName="20210407"
       panelVendor="Yamaha" panelDevice="Reface CP YC DX CS" panelMidiSnapshotAfterLoad="0"
       panelMidiSnapshotAfterProgramChange="0" panelMidiSnapshotDelay="10"
       panelMidiSnapshotShowProgress="0" panelMidiInputChannelDevice="1"
       panelMidiInputDevice="reface DX" panelMidiControllerChannelDevice="1"
       panelMidiControllerDevice="-- None" panelMidiOutputChannelDevice="1"
       panelMidiOutputDevice="reface DX" panelMidiInputFromHost="0"
       panelMidiInputChannelHost="1" panelMidiOutputToHost="0" panelMidiOutputChannelHost="1"
       panelMidiThruH2H="0" panelMidiThruH2HChannelize="0" panelMidiThruH2D="0"
       panelMidiThruH2DChannelize="0" panelMidiThruD2D="0" panelMidiThruD2DChannelize="0"
       panelMidiThruD2H="0" panelMidiThruD2HChannelize="0" panelMidiRealtimeIgnore="1"
       panelMidiInputThreadPriority="7" panelMidiProgram="0" panelMidiBankLsb="0"
       panelMidiBankMsb="0" panelMidiSendProgramChangeOnLoad="0" panelMidiProgramCalloutOnprogramChange="0"
       panelMidiMatchCacheSize="32" panelMidiGlobalDelay="0" panelMidiPauseOut="0"
       panelMidiPauseIn="0" panelOSCEnabled="0" panelOSCPort="-1" panelOSCProtocol="0"
       luaPanelMidiChannelChanged="-- None" luaPanelMidiReceived="-- None"
       luaPanelMidiMultiReceived="-- None" luaPanelLoaded="-- None"
       luaPanelBeforeLoad="-- None" luaPanelSaved="-- None" luaPanelResourcesLoaded="-- None"
       luaPanelProgramChanged="-- None" luaPanelGlobalChanged="-- None"
       luaPanelMessageHandler="-- None" luaPanelModulatorValueChanged="-- None"
       luaPanelSaveState="-- None" luaPanelRestoreState="-- None" luaPanelMidiSnapshotPost="-- None"
       luaPanelMidiSnapshotPre="-- None" luaAudioProcessBlock="-- None"
       luaPanelOSCReceived="-- None" panelFilePath="/home/m.tarenskeen/Muziek/SysEx/Ctrlr/Panels/Reface-Mastertune.panel"
       panelUID="8.EecAS5vix5N" panelInstanceUID="aiRr" panelInstanceManufacturerID="V41m"
       panelModulatorListColumns="-- None" panelModulatorListCsvDelimiter=","
       panelModulatorListXmlRoot="ctrlrModulatorList" panelModulatorListXmlModulator="ctrlrModulator"
       panelModulatorListSortOption="1" panelGlobalVariables="-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1:-1"
       panelResources="-- None" panelPropertyDisplayIDs="0" ctrlrMenuItemBackgroundColour="ffffffff"
       ctrlrMenuItemTextColour="ff000000" ctrlrMenuItemHighlightedTextColour="ffffffff"
       ctrlrMenuItemHighlightColour="ff4364ff" ctrlrMenuItemFont="&lt;Sans-Serif&gt;;18;0;0;0;0;1;3"
       ctrlrMenuItemSeparatorColour="44000000" ctrlrMenuItemHeaderColour="ff000000"
       ctrlrMenuBarBackgroundColour1="fff7f7f7" ctrlrMenuBarBackgroundColour2="ffcccccc"
       ctrlrMenuBarTextColour="ff000000" ctrlrMenuBarHighlightedTextColour="ffffffff"
       ctrlrMenuBarHighlightColour="ff4364ff" ctrlrMenuBarFont="&lt;Sans-Serif&gt;;18;0;0;0;0;1;3"
       ctrlrUseEditorWrapper="0" panelIndex="0">
  <uiWindowManager>
    <uiChildWindow uiChildWindowName="LuaMethodEditor" uiChildWindowState="123 143 1221 625">
      <uiChildWindowContentState luaMethodEditor="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#13;&#10;&#13;&#10;&lt;OPEN id=&quot;LUA&quot; scrollPos=&quot;0&quot;&gt;&#13;&#10;  &lt;OPEN id=&quot;Built-In&quot;/&gt;&#13;&#10;  &lt;SELECTED id=&quot;/LUA/mastertune2&quot;/&gt;&#13;&#10;&lt;/OPEN&gt;&#13;&#10;;ca022d6ea9de43b6bd177639722e5373:46bcd7efb55a4a90a65d54ac745c33a9:789b14d90e3b4db0ab75ec90d36641a4:9d32e6b009e246069043e78df8f19043:4306037335a64d619c5ad84e1b2de70a"/>
    </uiChildWindow>
    <uiChildWindow uiChildWindowName="LuaConsole" uiChildWindowState="283 208 800 500">
      <uiChildWindowContentState/>
    </uiChildWindow>
  </uiWindowManager>
  <midiLibrary uuid="0fa0ddd43d8e44e9b141ac91d4bf4e92" luaTransInfo="-- None"
               midiLibraryParameterIndexProperty="modulatorCustomIndex" midiLibraryMidiProgramChangeControl="0"
               midiLibrarySendSnapAfterPChg="0" midiLibraryDefaultBankName="New Bank - %H:%M:%S"
               midiLibraryDefaultProgramName="New Program - %H:%M:%S" midiLibraryDefaultSnapshotName="Snapshot - %H:%M:%S"
               midiLibraryCustomRequests="">
    <midiLibrarySnapshots name="Snapshots"/>
    <midiLibraryFirmware name="Firmware"/>
    <midiLibraryEditBuffer name="Edit buffer"/>
    <midiLibraryTransactions name="Transactions"/>
  </midiLibrary>
  <luaManager>
    <luaManagerMethods>
      <luaMethodGroup name="Built-In" uuid="8c32707d457040b1908e98d3e40068e0">
        <luaMethod luaMethodName="table_dump" luaMethodCode="-- @1.1&#10;--&#10;-- Print table contents&#10;--&#10;function table_dump(table)&#10;&#9;for key,value in ipairs(table) do&#10;&#9;&#9;_DBG (&quot;KEY= [&quot;..key..&quot;]&quot;)&#10;&#10;&#9;&#9;if (type(value) == &quot;table&quot;) then&#10;&#9;&#9;&#9;table_dump(value)&#10;&#9;&#9;elseif (type(value) == &quot;nil&quot;) then&#10;&#9;&#9;&#9;_DBG (&quot; = NIL&quot;)&#10;&#9;&#9;else&#10;&#9;&#9;&#9;what (value)&#10;&#9;&#9;end&#10;&#9;end&#10;end"
                   luaMethodLinkedProperty="" luaMethodSource="0" uuid="00000000000000000000000000000001"
                   luaMethodValid="1"/>
        <luaMethod luaMethodName="what" luaMethodCode="-- @1.1&#10;--&#10;-- Print methods for an object&#10;--&#10;function what(o)&#10;&#9;info = class_info(o)&#10;&#9;if info ~= nil then&#10;&#9;&#9;ret = &quot;Object type [&quot; .. info.name .. &quot;]\n-----------------------------------------------------------------\n\n&quot;..&quot;Members:\n&quot;&#10;&#10;&#9;&#9;if info.name == &quot;table&quot; then&#10;&#9;&#9;&#9;table_dump(o)&#10;&#9;&#9;end&#10;&#10;&#9;&#9;for k, v in pairs(info.methods) do&#10;&#9;&#9;&#9;ret = ret .. string.format (&quot;\t%30s:\t%5s\n&quot;, k, type(v))&#10;&#9;&#9;end&#10;&#9;&#9;ret = ret .. &quot;\n\nAttributes:\n&quot;&#10;&#9;&#9;for k, v in pairs(info.attributes) do&#10;&#9;&#9;&#9;ret = ret .. string.format (&quot;\t%30s:\t%5s\n&quot;, k, type(v))&#10;&#9;&#9;end&#10;&#9;&#9;ret = ret .. &quot;\n-----------------------------------------------------------------&quot;&#10;&#9;end&#10;&#10;&#9;console (ret)&#10;&#9;return ret&#10;end"
                   luaMethodLinkedProperty="" luaMethodSource="0" uuid="00000000000000000000000000000002"
                   luaMethodValid="1"/>
        <luaMethod luaMethodName="how" luaMethodCode="-- @1.1&#10;--&#10;-- Print all available classes&#10;--&#10;function how()&#10;&#9;ret = &quot;Available classes:\n&quot;&#10;&#9;ret = ret .. &quot;\n-----------------------------------------------------------------&quot;&#10;&#9;for i,v in ipairs(class_names()) do&#10;&#9;&#9;ret = ret .. &quot;\t&quot;.. v .. &quot;\n&quot;&#10;&#9;end&#10;&#9;ret = ret .. &quot;\n-----------------------------------------------------------------&quot;&#10;&#9;console (J(ret))&#10;&#9;return ret&#10;end"
                   luaMethodLinkedProperty="" luaMethodSource="0" uuid="00000000000000000000000000000003"
                   luaMethodValid="1"/>
        <luaMethod luaMethodName="json4lua" luaMethodCode="-----------------------------------------------------------------------------&#13;&#10;-- JSON4Lua: JSON encoding / decoding support for the Lua language.&#13;&#10;-- json Module.&#13;&#10;-- Author: Craig Mason-Jones&#13;&#10;-- Homepage: http://json.luaforge.net/&#13;&#10;-- Version: 0.9.40&#13;&#10;-- This module is released under the MIT License (MIT).&#13;&#10;-- Please see LICENCE.txt for details.&#13;&#10;--&#13;&#10;-- USAGE:&#13;&#10;-- This module exposes two functions:&#13;&#10;--   encode(o)&#13;&#10;--     Returns the table / string / boolean / number / nil / json.null value as a JSON-encoded string.&#13;&#10;--   decode(json_string)&#13;&#10;--     Returns a Lua object populated with the data encoded in the JSON string json_string.&#13;&#10;--&#13;&#10;-- REQUIREMENTS:&#13;&#10;--   compat-5.1 if using Lua 5.0&#13;&#10;--&#13;&#10;-- CHANGELOG&#13;&#10;--   0.9.20 Introduction of local Lua functions for private functions (removed _ function prefix). &#13;&#10;--          Fixed Lua 5.1 compatibility issues.&#13;&#10;--   &#9;&#9;Introduced json.null to have null values in associative arrays.&#13;&#10;--          encode() performance improvement (more than 50%) through table.concat rather than ..&#13;&#10;--          Introduced decode ability to ignore /**/ comments in the JSON string.&#13;&#10;--   0.9.10 Fix to array encoding / decoding to correctly manage nil/null values in arrays.&#13;&#10;-----------------------------------------------------------------------------&#13;&#10;&#13;&#10;-----------------------------------------------------------------------------&#13;&#10;-- Imports and dependencies&#13;&#10;-----------------------------------------------------------------------------&#13;&#10;local math = require('math')&#13;&#10;local string = require(&quot;string&quot;)&#13;&#10;local table = require(&quot;table&quot;)&#13;&#10;&#13;&#10;local base = _G&#13;&#10;&#13;&#10;-----------------------------------------------------------------------------&#13;&#10;-- Module declaration&#13;&#10;-----------------------------------------------------------------------------&#13;&#10;module(&quot;json&quot;)&#13;&#10;&#13;&#10;-- Public functions&#13;&#10;&#13;&#10;-- Private functions&#13;&#10;local decode_scanArray&#13;&#10;local decode_scanComment&#13;&#10;local decode_scanConstant&#13;&#10;local decode_scanNumber&#13;&#10;local decode_scanObject&#13;&#10;local decode_scanString&#13;&#10;local decode_scanWhitespace&#13;&#10;local encodeString&#13;&#10;local isArray&#13;&#10;local isEncodable&#13;&#10;&#13;&#10;-----------------------------------------------------------------------------&#13;&#10;-- PUBLIC FUNCTIONS&#13;&#10;-----------------------------------------------------------------------------&#13;&#10;--- Encodes an arbitrary Lua object / variable.&#13;&#10;-- @param v The Lua object / variable to be JSON encoded.&#13;&#10;-- @return String containing the JSON encoding in internal Lua string format (i.e. not unicode)&#13;&#10;function encode (v)&#13;&#10;  -- Handle nil values&#13;&#10;  if v==nil then&#13;&#10;    return &quot;null&quot;&#13;&#10;  end&#13;&#10;  &#13;&#10;  local vtype = base.type(v)  &#13;&#10;&#13;&#10;  -- Handle strings&#13;&#10;  if vtype=='string' then    &#13;&#10;    return '&quot;' .. encodeString(v) .. '&quot;'&#9;    -- Need to handle encoding in string&#13;&#10;  end&#13;&#10;  &#13;&#10;  -- Handle booleans&#13;&#10;  if vtype=='number' or vtype=='boolean' then&#13;&#10;    return base.tostring(v)&#13;&#10;  end&#13;&#10;  &#13;&#10;  -- Handle tables&#13;&#10;  if vtype=='table' then&#13;&#10;    local rval = {}&#13;&#10;    -- Consider arrays separately&#13;&#10;    local bArray, maxCount = isArray(v)&#13;&#10;    if bArray then&#13;&#10;      for i = 1,maxCount do&#13;&#10;        table.insert(rval, encode(v[i]))&#13;&#10;      end&#13;&#10;    else&#9;-- An object, not an array&#13;&#10;      for i,j in base.pairs(v) do&#13;&#10;        if isEncodable(i) and isEncodable(j) then&#13;&#10;          table.insert(rval, '&quot;' .. encodeString(i) .. '&quot;:' .. encode(j))&#13;&#10;        end&#13;&#10;      end&#13;&#10;    end&#13;&#10;    if bArray then&#13;&#10;      return '[' .. table.concat(rval,',') ..']'&#13;&#10;    else&#13;&#10;      return '{' .. table.concat(rval,',') .. '}'&#13;&#10;    end&#13;&#10;  end&#13;&#10;  &#13;&#10;  -- Handle null values&#13;&#10;  if vtype=='function' and v==null then&#13;&#10;    return 'null'&#13;&#10;  end&#13;&#10;  &#13;&#10;  base.assert(false,'encode attempt to encode unsupported type ' .. vtype .. ':' .. base.tostring(v))&#13;&#10;end&#13;&#10;&#13;&#10;&#13;&#10;--- Decodes a JSON string and returns the decoded value as a Lua data structure / value.&#13;&#10;-- @param s The string to scan.&#13;&#10;-- @param [startPos] Optional starting position where the JSON string is located. Defaults to 1.&#13;&#10;-- @param Lua object, number The object that was scanned, as a Lua table / string / number / boolean or nil,&#13;&#10;-- and the position of the first character after&#13;&#10;-- the scanned JSON object.&#13;&#10;function decode(s, startPos)&#13;&#10;  startPos = startPos and startPos or 1&#13;&#10;  startPos = decode_scanWhitespace(s,startPos)&#13;&#10;  base.assert(startPos&lt;=string.len(s), 'Unterminated JSON encoded object found at position in [' .. s .. ']')&#13;&#10;  local curChar = string.sub(s,startPos,startPos)&#13;&#10;  -- Object&#13;&#10;  if curChar=='{' then&#13;&#10;    return decode_scanObject(s,startPos)&#13;&#10;  end&#13;&#10;  -- Array&#13;&#10;  if curChar=='[' then&#13;&#10;    return decode_scanArray(s,startPos)&#13;&#10;  end&#13;&#10;  -- Number&#13;&#10;  if string.find(&quot;+-0123456789.e&quot;, curChar, 1, true) then&#13;&#10;    return decode_scanNumber(s,startPos)&#13;&#10;  end&#13;&#10;  -- String&#13;&#10;  if curChar==[[&quot;]] or curChar==[[']] then&#13;&#10;    return decode_scanString(s,startPos)&#13;&#10;  end&#13;&#10;  if string.sub(s,startPos,startPos+1)=='/*' then&#13;&#10;    return decode(s, decode_scanComment(s,startPos))&#13;&#10;  end&#13;&#10;  -- Otherwise, it must be a constant&#13;&#10;  return decode_scanConstant(s,startPos)&#13;&#10;end&#13;&#10;&#13;&#10;--- The null function allows one to specify a null value in an associative array (which is otherwise&#13;&#10;-- discarded if you set the value with 'nil' in Lua. Simply set t = { first=json.null }&#13;&#10;function null()&#13;&#10;  return null -- so json.null() will also return null ;-)&#13;&#10;end&#13;&#10;-----------------------------------------------------------------------------&#13;&#10;-- Internal, PRIVATE functions.&#13;&#10;-- Following a Python-like convention, I have prefixed all these 'PRIVATE'&#13;&#10;-- functions with an underscore.&#13;&#10;-----------------------------------------------------------------------------&#13;&#10;&#13;&#10;--- Scans an array from JSON into a Lua object&#13;&#10;-- startPos begins at the start of the array.&#13;&#10;-- Returns the array and the next starting position&#13;&#10;-- @param s The string being scanned.&#13;&#10;-- @param startPos The starting position for the scan.&#13;&#10;-- @return table, int The scanned array as a table, and the position of the next character to scan.&#13;&#10;function decode_scanArray(s,startPos)&#13;&#10;  local array = {}&#9;-- The return value&#13;&#10;  local stringLen = string.len(s)&#13;&#10;  base.assert(string.sub(s,startPos,startPos)=='[','decode_scanArray called but array does not start at position ' .. startPos .. ' in string:\n'..s )&#13;&#10;  startPos = startPos + 1&#13;&#10;  -- Infinite loop for array elements&#13;&#10;  repeat&#13;&#10;    startPos = decode_scanWhitespace(s,startPos)&#13;&#10;    base.assert(startPos&lt;=stringLen,'JSON String ended unexpectedly scanning array.')&#13;&#10;    local curChar = string.sub(s,startPos,startPos)&#13;&#10;    if (curChar==']') then&#13;&#10;      return array, startPos+1&#13;&#10;    end&#13;&#10;    if (curChar==',') then&#13;&#10;      startPos = decode_scanWhitespace(s,startPos+1)&#13;&#10;    end&#13;&#10;    base.assert(startPos&lt;=stringLen, 'JSON String ended unexpectedly scanning array.')&#13;&#10;    object, startPos = decode(s,startPos)&#13;&#10;    table.insert(array,object)&#13;&#10;  until false&#13;&#10;end&#13;&#10;&#13;&#10;--- Scans a comment and discards the comment.&#13;&#10;-- Returns the position of the next character following the comment.&#13;&#10;-- @param string s The JSON string to scan.&#13;&#10;-- @param int startPos The starting position of the comment&#13;&#10;function decode_scanComment(s, startPos)&#13;&#10;  base.assert( string.sub(s,startPos,startPos+1)=='/*', &quot;decode_scanComment called but comment does not start at position &quot; .. startPos)&#13;&#10;  local endPos = string.find(s,'*/',startPos+2)&#13;&#10;  base.assert(endPos~=nil, &quot;Unterminated comment in string at &quot; .. startPos)&#13;&#10;  return endPos+2  &#13;&#10;end&#13;&#10;&#13;&#10;--- Scans for given constants: true, false or null&#13;&#10;-- Returns the appropriate Lua type, and the position of the next character to read.&#13;&#10;-- @param s The string being scanned.&#13;&#10;-- @param startPos The position in the string at which to start scanning.&#13;&#10;-- @return object, int The object (true, false or nil) and the position at which the next character should be &#13;&#10;-- scanned.&#13;&#10;function decode_scanConstant(s, startPos)&#13;&#10;  local consts = { [&quot;true&quot;] = true, [&quot;false&quot;] = false, [&quot;null&quot;] = nil }&#13;&#10;  local constNames = {&quot;true&quot;,&quot;false&quot;,&quot;null&quot;}&#13;&#10;&#13;&#10;  for i,k in base.pairs(constNames) do&#13;&#10;    --print (&quot;[&quot; .. string.sub(s,startPos, startPos + string.len(k) -1) ..&quot;]&quot;, k)&#13;&#10;    if string.sub(s,startPos, startPos + string.len(k) -1 )==k then&#13;&#10;      return consts[k], startPos + string.len(k)&#13;&#10;    end&#13;&#10;  end&#13;&#10;  base.assert(nil, 'Failed to scan constant from string ' .. s .. ' at starting position ' .. startPos)&#13;&#10;end&#13;&#10;&#13;&#10;--- Scans a number from the JSON encoded string.&#13;&#10;-- (in fact, also is able to scan numeric +- eqns, which is not&#13;&#10;-- in the JSON spec.)&#13;&#10;-- Returns the number, and the position of the next character&#13;&#10;-- after the number.&#13;&#10;-- @param s The string being scanned.&#13;&#10;-- @param startPos The position at which to start scanning.&#13;&#10;-- @return number, int The extracted number and the position of the next character to scan.&#13;&#10;function decode_scanNumber(s,startPos)&#13;&#10;  local endPos = startPos+1&#13;&#10;  local stringLen = string.len(s)&#13;&#10;  local acceptableChars = &quot;+-0123456789.e&quot;&#13;&#10;  while (string.find(acceptableChars, string.sub(s,endPos,endPos), 1, true)&#13;&#10;&#9;and endPos&lt;=stringLen&#13;&#10;&#9;) do&#13;&#10;    endPos = endPos + 1&#13;&#10;  end&#13;&#10;  local stringValue = 'return ' .. string.sub(s,startPos, endPos-1)&#13;&#10;  local stringEval = base.loadstring(stringValue)&#13;&#10;  base.assert(stringEval, 'Failed to scan number [ ' .. stringValue .. '] in JSON string at position ' .. startPos .. ' : ' .. endPos)&#13;&#10;  return stringEval(), endPos&#13;&#10;end&#13;&#10;&#13;&#10;--- Scans a JSON object into a Lua object.&#13;&#10;-- startPos begins at the start of the object.&#13;&#10;-- Returns the object and the next starting position.&#13;&#10;-- @param s The string being scanned.&#13;&#10;-- @param startPos The starting position of the scan.&#13;&#10;-- @return table, int The scanned object as a table and the position of the next character to scan.&#13;&#10;function decode_scanObject(s,startPos)&#13;&#10;  local object = {}&#13;&#10;  local stringLen = string.len(s)&#13;&#10;  local key, value&#13;&#10;  base.assert(string.sub(s,startPos,startPos)=='{','decode_scanObject called but object does not start at position ' .. startPos .. ' in string:\n' .. s)&#13;&#10;  startPos = startPos + 1&#13;&#10;  repeat&#13;&#10;    startPos = decode_scanWhitespace(s,startPos)&#13;&#10;    base.assert(startPos&lt;=stringLen, 'JSON string ended unexpectedly while scanning object.')&#13;&#10;    local curChar = string.sub(s,startPos,startPos)&#13;&#10;    if (curChar=='}') then&#13;&#10;      return object,startPos+1&#13;&#10;    end&#13;&#10;    if (curChar==',') then&#13;&#10;      startPos = decode_scanWhitespace(s,startPos+1)&#13;&#10;    end&#13;&#10;    base.assert(startPos&lt;=stringLen, 'JSON string ended unexpectedly scanning object.')&#13;&#10;    -- Scan the key&#13;&#10;    key, startPos = decode(s,startPos)&#13;&#10;    base.assert(startPos&lt;=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)&#13;&#10;    startPos = decode_scanWhitespace(s,startPos)&#13;&#10;    base.assert(startPos&lt;=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)&#13;&#10;    base.assert(string.sub(s,startPos,startPos)==':','JSON object key-value assignment mal-formed at ' .. startPos)&#13;&#10;    startPos = decode_scanWhitespace(s,startPos+1)&#13;&#10;    base.assert(startPos&lt;=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)&#13;&#10;    value, startPos = decode(s,startPos)&#13;&#10;    object[key]=value&#13;&#10;  until false&#9;-- infinite loop while key-value pairs are found&#13;&#10;end&#13;&#10;&#13;&#10;-- START SoniEx2&#13;&#10;-- Initialize some things used by decode_scanString&#13;&#10;-- You know, for efficiency&#13;&#10;local escapeSequences = {&#13;&#10;  [&quot;\\t&quot;] = &quot;\t&quot;,&#13;&#10;  [&quot;\\f&quot;] = &quot;\f&quot;,&#13;&#10;  [&quot;\\r&quot;] = &quot;\r&quot;,&#13;&#10;  [&quot;\\n&quot;] = &quot;\n&quot;,&#13;&#10;  [&quot;\\b&quot;] = &quot;\b&quot;&#13;&#10;}&#13;&#10;base.setmetatable(escapeSequences, {__index = function(t,k)&#13;&#10;  -- skip &quot;\&quot; aka strip escape&#13;&#10;  return string.sub(k,2)&#13;&#10;end})&#13;&#10;-- END SoniEx2&#13;&#10;&#13;&#10;--- Scans a JSON string from the opening inverted comma or single quote to the&#13;&#10;-- end of the string.&#13;&#10;-- Returns the string extracted as a Lua string,&#13;&#10;-- and the position of the next non-string character&#13;&#10;-- (after the closing inverted comma or single quote).&#13;&#10;-- @param s The string being scanned.&#13;&#10;-- @param startPos The starting position of the scan.&#13;&#10;-- @return string, int The extracted string as a Lua string, and the next character to parse.&#13;&#10;function decode_scanString(s,startPos)&#13;&#10;  base.assert(startPos, 'decode_scanString(..) called without start position')&#13;&#10;  local startChar = string.sub(s,startPos,startPos)&#13;&#10;  -- START SoniEx2&#13;&#10;  -- PS: I don't think single quotes are valid JSON&#13;&#10;  base.assert(startChar == [[&quot;]] or startChar == [[']],'decode_scanString called for a non-string')&#13;&#10;  --base.assert(startPos, &quot;String decoding failed: missing closing &quot; .. startChar .. &quot; for string at position &quot; .. oldStart)&#13;&#10;  local t = {}&#13;&#10;  local i,j = startPos,startPos&#13;&#10;  while string.find(s, startChar, j+1) ~= j+1 do&#13;&#10;    local oldj = j&#13;&#10;    i,j = string.find(s, &quot;\\.&quot;, j+1)&#13;&#10;    local x,y = string.find(s, startChar, oldj+1)&#13;&#10;    if not i or x &lt; i then&#13;&#10;      base.print(s, startPos, string.sub(s,startPos,oldj))&#13;&#10;      i,j = x,y-1&#13;&#10;      if not x then base.print(s, startPos, string.sub(s,startPos,oldj)) end&#13;&#10;    end&#13;&#10;    table.insert(t, string.sub(s, oldj+1, i-1))&#13;&#10;    if string.sub(s, i, j) == &quot;\\u&quot; then&#13;&#10;      local a = string.sub(s,j+1,j+4)&#13;&#10;      j = j + 4&#13;&#10;      local n = base.tonumber(a, 16)&#13;&#10;      base.assert(n, &quot;String decoding failed: bad Unicode escape &quot; .. a .. &quot; at position &quot; .. i .. &quot; : &quot; .. j)&#13;&#10;      -- math.floor(x/2&#94;y) == lazy right shift&#13;&#10;      -- a % 2&#94;b == bitwise_and(a, (2&#94;b)-1)&#13;&#10;      -- 64 = 2&#94;6&#13;&#10;      -- 4096 = 2&#94;12 (or 2&#94;6 * 2&#94;6)&#13;&#10;      local x&#13;&#10;      if n &lt; 0x80 then&#13;&#10;        x = string.char(n % 0x80)&#13;&#10;      elseif n &lt; 0x800 then&#13;&#10;        -- [110x xxxx] [10xx xxxx]&#13;&#10;        x = string.char(0xC0 + (math.floor(n/64) % 0x20), 0x80 + (n % 0x40))&#13;&#10;      else&#13;&#10;        -- [1110 xxxx] [10xx xxxx] [10xx xxxx]&#13;&#10;        x = string.char(0xE0 + (math.floor(n/4096) % 0x10), 0x80 + (math.floor(n/64) % 0x40), 0x80 + (n % 0x40))&#13;&#10;      end&#13;&#10;      table.insert(t, x)&#13;&#10;    else&#13;&#10;      table.insert(t, escapeSequences[string.sub(s, i, j)])&#13;&#10;    end&#13;&#10;  end&#13;&#10;  table.insert(t,string.sub(j, j+1))&#13;&#10;  base.assert(string.find(s, startChar, j+1), &quot;String decoding failed: missing closing &quot; .. startChar .. &quot; at position &quot; .. j .. &quot;(for string at position &quot; .. startPos .. &quot;)&quot;)&#13;&#10;  return table.concat(t,&quot;&quot;), j+2&#13;&#10;  -- END SoniEx2&#13;&#10;end&#13;&#10;&#13;&#10;--- Scans a JSON string skipping all whitespace from the current start position.&#13;&#10;-- Returns the position of the first non-whitespace character, or nil if the whole end of string is reached.&#13;&#10;-- @param s The string being scanned&#13;&#10;-- @param startPos The starting position where we should begin removing whitespace.&#13;&#10;-- @return int The first position where non-whitespace was encountered, or string.len(s)+1 if the end of string&#13;&#10;-- was reached.&#13;&#10;function decode_scanWhitespace(s,startPos)&#13;&#10;  local whitespace=&quot; \n\r\t&quot;&#13;&#10;  local stringLen = string.len(s)&#13;&#10;  while ( string.find(whitespace, string.sub(s,startPos,startPos), 1, true)  and startPos &lt;= stringLen) do&#13;&#10;    startPos = startPos + 1&#13;&#10;  end&#13;&#10;  return startPos&#13;&#10;end&#13;&#10;&#13;&#10;--- Encodes a string to be JSON-compatible.&#13;&#10;-- This just involves back-quoting inverted commas, back-quotes and newlines, I think ;-)&#13;&#10;-- @param s The string to return as a JSON encoded (i.e. backquoted string)&#13;&#10;-- @return The string appropriately escaped.&#13;&#10;&#13;&#10;local escapeList = {&#13;&#10;    ['&quot;']  = '\\&quot;',&#13;&#10;    ['\\'] = '\\\\',&#13;&#10;    ['/']  = '\\/', &#13;&#10;    ['\b'] = '\\b',&#13;&#10;    ['\f'] = '\\f',&#13;&#10;    ['\n'] = '\\n',&#13;&#10;    ['\r'] = '\\r',&#13;&#10;    ['\t'] = '\\t'&#13;&#10;}&#13;&#10;&#13;&#10;function encodeString(s)&#13;&#10; return s:gsub(&quot;.&quot;, function(c) return escapeList[c] end) -- SoniEx2: 5.0 compat&#13;&#10;end&#13;&#10;&#13;&#10;-- Determines whether the given Lua type is an array or a table / dictionary.&#13;&#10;-- We consider any table an array if it has indexes 1..n for its n items, and no&#13;&#10;-- other data in the table.&#13;&#10;-- I think this method is currently a little 'flaky', but can't think of a good way around it yet...&#13;&#10;-- @param t The table to evaluate as an array&#13;&#10;-- @return boolean, number True if the table can be represented as an array, false otherwise. If true,&#13;&#10;-- the second returned value is the maximum&#13;&#10;-- number of indexed elements in the array. &#13;&#10;function isArray(t)&#13;&#10;  -- Next we count all the elements, ensuring that any non-indexed elements are not-encodable &#13;&#10;  -- (with the possible exception of 'n')&#13;&#10;  local maxIndex = 0&#13;&#10;  for k,v in base.pairs(t) do&#13;&#10;    if (base.type(k)=='number' and math.floor(k)==k and 1&lt;=k) then&#9;-- k,v is an indexed pair&#13;&#10;      if (not isEncodable(v)) then return false end&#9;-- All array elements must be encodable&#13;&#10;      maxIndex = math.max(maxIndex,k)&#13;&#10;    else&#13;&#10;      if (k=='n') then&#13;&#10;        if v ~= table.getn(t) then return false end  -- False if n does not hold the number of elements&#13;&#10;      else -- Else of (k=='n')&#13;&#10;        if isEncodable(v) then return false end&#13;&#10;      end  -- End of (k~='n')&#13;&#10;    end -- End of k,v not an indexed pair&#13;&#10;  end  -- End of loop across all pairs&#13;&#10;  return true, maxIndex&#13;&#10;end&#13;&#10;&#13;&#10;--- Determines whether the given Lua object / table / variable can be JSON encoded. The only&#13;&#10;-- types that are JSON encodable are: string, boolean, number, nil, table and json.null.&#13;&#10;-- In this implementation, all other types are ignored.&#13;&#10;-- @param o The object to examine.&#13;&#10;-- @return boolean True if the object should be JSON encoded, false if it should be ignored.&#13;&#10;function isEncodable(o)&#13;&#10;  local t = base.type(o)&#13;&#10;  return (t=='string' or t=='boolean' or t=='number' or t=='nil' or t=='table') or (t=='function' and o==null) &#13;&#10;end"
                   luaMethodLinkedProperty="" luaMethodSource="0" uuid="00000000000000000000000000000004"
                   luaMethodValid="1"/>
        <luaMethod luaMethodName="debugger.lua" luaMethodCode="--{{{  history&#10;&#10;--15/03/06 DCN Created based on RemDebug&#10;--28/04/06 DCN Update for Lua 5.1&#10;--01/06/06 DCN Fix command argument parsing&#10;--             Add step/over N facility&#10;--             Add trace lines facility&#10;--05/06/06 DCN Add trace call/return facility&#10;--06/06/06 DCN Make it behave when stepping through the creation of a coroutine&#10;--06/06/06 DCN Integrate the simple debugger into the main one&#10;--07/06/06 DCN Provide facility to step into coroutines&#10;--13/06/06 DCN Fix bug that caused the function environment to get corrupted with the global one&#10;--14/06/06 DCN Allow 'sloppy' file names when setting breakpoints&#10;--04/08/06 DCN Allow for no space after command name&#10;--11/08/06 DCN Use io.write not print&#10;--30/08/06 DCN Allow access to array elements in 'dump'&#10;--10/10/06 DCN Default to breakfile for all commands that require a filename and give '-'&#10;--06/12/06 DCN Allow for punctuation characters in DUMP variable names&#10;--03/01/07 DCN Add pause on/off facility&#10;--19/06/07 DCN Allow for duff commands being typed in the debugger (thanks to Michael.Bringmann@lsi.com)&#10;--             Allow for case sensitive file systems               (thanks to Michael.Bringmann@lsi.com)&#10;--04/08/09 DCN Add optional line count param to pause&#10;--05/08/09 DCN Reset the debug hook in Pause() even if we think we're started&#10;--30/09/09 DCN Re-jig to not use co-routines (makes debugging co-routines awkward)&#10;--01/10/09 DCN Add ability to break on reaching any line in a file&#10;--24/07/13 TWW Added code for emulating setfenv/getfenv in Lua 5.2 as per&#10;--             http://lua-users.org/lists/lua-l/2010-06/msg00313.html&#10;--25/07/13 TWW Copied Alex Parrill's fix for errors when tracing back across a C frame&#10;--             (https://github.com/ColonelThirtyTwo/clidebugger, 26/01/12)&#10;--25/07/13 DCN Allow for windows and unix file name conventions in has_breakpoint&#10;--26/07/13 DCN Allow for \ being interpreted as an escape inside a [] pattern in 5.2&#10;&#10;--}}}&#10;--{{{  description&#10;&#10;--A simple command line debug system for Lua written by Dave Nichols of&#10;--Match-IT Limited. Its public domain software. Do with it as you wish.&#10;&#10;--This debugger was inspired by:&#10;-- RemDebug 1.0 Beta&#10;-- Copyright Kepler Project 2005 (http://www.keplerproject.org/remdebug)&#10;&#10;--Usage:&#10;--  require('debugger')        --load the debug library&#10;--  pause(message)             --start/resume a debug session&#10;&#10;--An assert() failure will also invoke the debugger.&#10;&#10;--}}}&#10;&#10;local IsWindows = string.find(string.lower(os.getenv('OS') or ''),'&#94;windows')&#10;&#10;local coro_debugger&#10;local events = { BREAK = 1, WATCH = 2, STEP = 3, SET = 4 }&#10;breakpoints = {}&#10;local watches = {}&#10;local step_into   = false&#10;local step_over   = false&#10;local step_lines  = 0&#10;local step_level  = {main=0}&#10;local stack_level = {main=0}&#10;local trace_level = {main=0}&#10;local trace_calls = false&#10;local trace_returns = false&#10;local trace_lines = false&#10;local ret_file, ret_line, ret_name&#10;local current_thread = 'main'&#10;local started = false&#10;local pause_off = false&#10;local _g      = _G&#10;local cocreate, cowrap = coroutine.create, coroutine.wrap&#10;local pausemsg = 'pause'&#10;&#10;--{{{  make Lua 5.2 compatible&#10;&#10;if not setfenv then -- Lua 5.2&#10;  --[[&#10;  As far as I can see, the only missing detail of these functions (except&#10;  for occasional bugs) to achieve 100% compatibility is the case of&#10;  'getfenv' over a function that does not have an _ENV variable (that is,&#10;  it uses no globals).&#10;&#10;  We could use a weak table to keep the environments of these functions&#10;  when set by setfenv, but that still misses the case of a function&#10;  without _ENV that was not subjected to setfenv.&#10;&#10;  -- Roberto&#10;  ]]--&#10;&#10;  setfenv = setfenv or function(f, t)&#10;    f = (type(f) == 'function' and f or debug.getinfo(f + 1, 'f').func)&#10;    local name&#10;    local up = 0&#10;    repeat&#10;      up = up + 1&#10;      name = debug.getupvalue(f, up)&#10;    until name == '_ENV' or name == nil&#10;    if name then&#10;      debug.upvaluejoin(f, up, function() return name end, 1) -- use unique upvalue&#10;      debug.setupvalue(f, up, t)&#10;    end&#10;  end&#10;&#10;  getfenv = getfenv or function(f)&#10;    f = (type(f) == 'function' and f or debug.getinfo(f + 1, 'f').func)&#10;    local name, val&#10;    local up = 0&#10;    repeat&#10;      up = up + 1&#10;      name, val = debug.getupvalue(f, up)&#10;    until name == '_ENV' or name == nil&#10;    return val&#10;  end&#10;&#10;end&#10;&#10;--}}}&#10;&#10;--{{{  local hints -- command help&#10;--The format in here is name=summary|description&#10;local hints = {&#10;&#10;pause =   [[&#10;pause(msg[,lines][,force]) -- start/resume a debugger session|&#10;&#10;This can only be used in your code or from the console as a means to&#10;start/resume a debug session.&#10;If msg is given that is shown when the session starts/resumes. Useful to&#10;give a context if you've instrumented your code with pause() statements.&#10;&#10;If lines is given, the script pauses after that many lines, else it pauses&#10;immediately.&#10;&#10;If force is true, the pause function is honoured even if poff has been used.&#10;This is useful when in an interactive console session to regain debugger&#10;control.&#10;]],&#10;&#10;poff =    [[&#10;poff                -- turn off pause() command|&#10;&#10;This causes all pause() commands to be ignored. This is useful if you have&#10;instrumented your code in a busy loop and want to continue normal execution&#10;with no further interruption.&#10;]],&#10;&#10;pon =     [[&#10;pon                 -- turn on pause() command|&#10;&#10;This re-instates honouring the pause() commands you may have instrumented&#10;your code with.&#10;]],&#10;&#10;setb =    [[&#10;setb [line file]    -- set a breakpoint to line/file|, line 0 means 'any'&#10;&#10;If file is omitted or is &quot;-&quot; the breakpoint is set at the file for the&#10;currently set level (see &quot;set&quot;). Execution pauses when this line is about&#10;to be executed and the debugger session is re-activated.&#10;&#10;The file can be given as the fully qualified name, partially qualified or&#10;just the file name. E.g. if file is set as &quot;myfile.lua&quot;, then whenever&#10;execution reaches any file that ends with &quot;myfile.lua&quot; it will pause. If&#10;no extension is given, any extension will do.&#10;&#10;If the line is given as 0, then reaching any line in the file will do.&#10;]],&#10;&#10;delb =    [[&#10;delb [line file]    -- removes a breakpoint|&#10;&#10;If file is omitted or is &quot;-&quot; the breakpoint is removed for the file of the&#10;currently set level (see &quot;set&quot;).&#10;]],&#10;&#10;delallb = [[&#10;delallb             -- removes all breakpoints|&#10;]],&#10;&#10;setw =    [[&#10;setw &lt;exp&gt;          -- adds a new watch expression|&#10;&#10;The expression is evaluated before each line is executed. If the expression&#10;yields true then execution is paused and the debugger session re-activated.&#10;The expression is executed in the context of the line about to be executed.&#10;]],&#10;&#10;delw =    [[&#10;delw &lt;index&gt;        -- removes the watch expression at index|&#10;&#10;The index is that returned when the watch expression was set by setw.&#10;]],&#10;&#10;delallw = [[&#10;delallw             -- removes all watch expressions|&#10;]],&#10;&#10;run     = [[&#10;run                 -- run until next breakpoint or watch expression|&#10;]],&#10;&#10;step    = [[&#10;step [N]            -- run next N lines, stepping into function calls|&#10;&#10;If N is omitted, use 1.&#10;]],&#10;&#10;over    = [[&#10;over [N]            -- run next N lines, stepping over function calls|&#10;&#10;If N is omitted, use 1.&#10;]],&#10;&#10;out     = [[&#10;out [N]             -- run lines until stepped out of N functions|&#10;&#10;If N is omitted, use 1.&#10;If you are inside a function, using &quot;out 1&quot; will run until you return&#10;from that function to the caller.&#10;]],&#10;&#10;gotoo   = [[&#10;gotoo [line file]    -- step to line in file|&#10;&#10;This is equivalent to 'setb line file', followed by 'run', followed&#10;by 'delb line file'.&#10;]],&#10;&#10;listb   = [[&#10;listb               -- lists breakpoints|&#10;]],&#10;&#10;listw   = [[&#10;listw               -- lists watch expressions|&#10;]],&#10;&#10;set     = [[&#10;set [level]         -- set context to stack level, omitted=show|&#10;&#10;If level is omitted it just prints the current level set.&#10;This sets the current context to the level given. This affects the&#10;context used for several other functions (e.g. vars). The possible&#10;levels are those shown by trace.&#10;]],&#10;&#10;vars    = [[&#10;vars [depth]        -- list context locals to depth, omitted=1|&#10;&#10;If depth is omitted then uses 1.&#10;Use a depth of 0 for the maximum.&#10;Lists all non-nil local variables and all non-nil upvalues in the&#10;currently set context. For variables that are tables, lists all fields&#10;to the given depth.&#10;]],&#10;&#10;fenv    = [[&#10;fenv [depth]        -- list context function env to depth, omitted=1|&#10;&#10;If depth is omitted then uses 1.&#10;Use a depth of 0 for the maximum.&#10;Lists all function environment variables in the currently set context.&#10;For variables that are tables, lists all fields to the given depth.&#10;]],&#10;&#10;glob    = [[&#10;glob [depth]        -- list globals to depth, omitted=1|&#10;&#10;If depth is omitted then uses 1.&#10;Use a depth of 0 for the maximum.&#10;Lists all global variables.&#10;For variables that are tables, lists all fields to the given depth.&#10;]],&#10;&#10;ups     = [[&#10;ups                 -- list all the upvalue names|&#10;&#10;These names will also be in the &quot;vars&quot; list unless their value is nil.&#10;This provides a means to identify which vars are upvalues and which are&#10;locals. If a name is both an upvalue and a local, the local value takes&#10;precedance.&#10;]],&#10;&#10;locs    = [[&#10;locs                -- list all the locals names|&#10;&#10;These names will also be in the &quot;vars&quot; list unless their value is nil.&#10;This provides a means to identify which vars are upvalues and which are&#10;locals. If a name is both an upvalue and a local, the local value takes&#10;precedance.&#10;]],&#10;&#10;dump    = [[&#10;dump &lt;var&gt; [depth]  -- dump all fields of variable to depth|&#10;&#10;If depth is omitted then uses 1.&#10;Use a depth of 0 for the maximum.&#10;Prints the value of &lt;var&gt; in the currently set context level. If &lt;var&gt;&#10;is a table, lists all fields to the given depth. &lt;var&gt; can be just a&#10;name, or name.field or name.# to any depth, e.g. t.1.f accesses field&#10;'f' in array element 1 in table 't'.&#10;&#10;Can also be called from a script as dump(var,depth).&#10;]],&#10;&#10;tron    = [[&#10;tron [crl]          -- turn trace on for (c)alls, (r)etuns, (l)lines|&#10;&#10;If no parameter is given then tracing is turned off.&#10;When tracing is turned on a line is printed to the console for each&#10;debug 'event' selected. c=function calls, r=function returns, l=lines.&#10;]],&#10;&#10;trace   = [[&#10;trace               -- dumps a stack trace|&#10;&#10;Format is [level] = file,line,name&#10;The level is a candidate for use by the 'set' command.&#10;]],&#10;&#10;info    = [[&#10;info                -- dumps the complete debug info captured|&#10;&#10;Only useful as a diagnostic aid for the debugger itself. This information&#10;can be HUGE as it dumps all variables to the maximum depth, so be careful.&#10;]],&#10;&#10;show    = [[&#10;show line file X Y  -- show X lines before and Y after line in file|&#10;&#10;If line is omitted or is '-' then the current set context line is used.&#10;If file is omitted or is '-' then the current set context file is used.&#10;If file is not fully qualified and cannot be opened as specified, then&#10;a search for the file in the package[path] is performed using the usual&#10;&quot;require&quot; searching rules. If no file extension is given, .lua is used.&#10;Prints the lines from the source file around the given line.&#10;]],&#10;&#10;exit    = [[&#10;exit                -- exits debugger, re-start it using pause()|&#10;]],&#10;&#10;help    = [[&#10;help [command]      -- show this list or help for command|&#10;]],&#10;&#10;[&quot;&lt;statement&gt;&quot;] = [[&#10;&lt;statement&gt;         -- execute a statement in the current context|&#10;&#10;The statement can be anything that is legal in the context, including&#10;assignments. Such assignments affect the context and will be in force&#10;immediately. Any results returned are printed. Use '=' as a short-hand&#10;for 'return', e.g. &quot;=func(arg)&quot; will call 'func' with 'arg' and print&#10;the results, and &quot;=var&quot; will just print the value of 'var'.&#10;]],&#10;&#10;what    = [[&#10;what &lt;func&gt;         -- show where &lt;func&gt; is defined (if known)|&#10;]],&#10;&#10;}&#10;--}}}&#10;&#10;--{{{ Local function to get table size&#10;local function tsize(t)&#10;    local count=0&#10;&#10;    for k,v in pairs(t) do&#10;        count = count + 1&#10;    end&#10;&#10;    return count&#10;end&#10;---}}}&#10;&#10;---{{{ Global utility function to set breakpoints, used inside Ctrlr&#10;function setBreakpoint(line, file, shouldBeSet)&#10;    if not breakpoints[line] then&#10;        breakpoints[line] = {}&#10;    end&#10;&#10;    if shouldBeSet then&#10;        breakpoints[line][file] = true&#10;    else&#10;        breakpoints[line] = nil&#10;    end&#10;end&#10;---}}}&#10;&#10;&#10;--{{{  local function getinfo(level,field)&#10;&#10;--like debug.getinfo but copes with no activation record at the given level&#10;--and knows how to get 'field'. 'field' can be the name of any of the&#10;--activation record fields or any of the 'what' names or nil for everything.&#10;--only valid when using the stack level to get info, not a function name.&#10;&#10;local function getinfo(level,field)&#10;  level = level + 1  --to get to the same relative level as the caller&#10;  if not field then return debug.getinfo(level) end&#10;  local what&#10;  if field == 'name' or field == 'namewhat' then&#10;    what = 'n'&#10;  elseif field == 'what' or field == 'source' or field == 'linedefined' or field == 'lastlinedefined' or field == 'short_src' then&#10;    what = 'S'&#10;  elseif field == 'currentline' then&#10;    what = 'l'&#10;  elseif field == 'nups' then&#10;    what = 'u'&#10;  elseif field == 'func' then&#10;    what = 'f'&#10;  else&#10;    return debug.getinfo(level,field)&#10;  end&#10;  local ar = debug.getinfo(level,what)&#10;  if ar then return ar[field] else return nil end&#10;end&#10;&#10;--}}}&#10;--{{{  local function indented( level, ... )&#10;&#10;local function indented( level, ... )&#10;  ctrlrDebugger:write( string.format (&quot;%s%s\n&quot;, string.rep('  ',level), table.concat({...}) ))&#10;end&#10;&#10;--}}}&#10;--{{{  local function dumpval( level, name, value, limit )&#10;&#10;local dumpvisited&#10;&#10;local function dumpval( level, name, value, limit )&#10;    local index&#10;&#10;    if type(name) == 'number' then&#10;        index = string.format(&quot;%q,&quot;,name)&#10;    elseif type(name) == 'string' and (name == '__VARSLEVEL__' or name == '__ENVIRONMENT__' or name == '__GLOBALS__' or name == '__UPVALUES__' or name == '__LOCALS__') then&#10;        --ignore these, they are debugger generated&#10;        return&#10;    elseif type(name) == 'string' and string.find(name,'&#94;[_%a][_.%w]*$') then&#10;        index = string.format (&quot;%q: &quot;, name);&#10;    else&#10;        index = string.format (&quot;%q,&quot;, tostring(name))&#10;    end&#10;&#10;    if type(value) == 'table' then&#10;        if dumpvisited[value] then&#10;            indented (level, index, string.format(&quot;%q&quot;, dumpvisited[value]))&#10;        else&#10;            dumpvisited[value] = string.format (&quot;\&quot;table\&quot;: \&quot;%d\&quot;,&quot;, tsize (value))&#10;            if (limit or 0) &gt; 0 and level+1 &gt;= limit then&#10;                indented (level, index, string.format (&quot;{%s&quot;, string.gsub(dumpvisited[value], &quot;,&quot;, &quot;},&quot;)))&#10;            else&#10;                indented (level, index, &quot;{\n&quot;, dumpvisited[value])&#10;&#10;                for n,v in pairs(value) do&#10;                    dumpval (level+1, n, v, limit)&#10;                end&#10;&#10;                indented (level, &quot;}&quot;)&#10;            end&#10;        end&#10;    else&#10;        if type(value) == 'string' then&#10;            indented (level, index, string.format(&quot;{\&quot;string\&quot;: %q}&quot;,value), ',')&#10;        end&#10;&#10;        if type(value) == 'userdata' then&#10;            info = class_info (value)&#10;            indented (level, index, string.format (&quot;{\&quot;userdata\&quot;: %q}&quot;, info.name) , ',')&#10;        end&#10;&#10;        if type(value) == 'number' then&#10;            indented (level, index, string.format (&quot;{\&quot;number\&quot;: %q}&quot;,tostring(value)), ',')&#10;        end&#10;    end&#10;end&#10;&#10;--}}}&#10;--{{{  local function dumpvar( value, limit, name )&#10;&#10;local function dumpvar( value, limit, name )&#10;  ctrlrDebugger:write (&quot;\n::start dumpvar\n&quot;)&#10;  dumpvisited = {}&#10;  dumpval( 0, name or tostring(value), value, limit )&#10;  ctrlrDebugger:write (&quot;::end\n&quot;)&#10;end&#10;&#10;--}}}&#10;--{{{  local function show(file,line,before,after)&#10;&#10;--show +/-N lines of a file around line M&#10;&#10;local function show(file,line,before,after)&#10;&#10;  line   = tonumber(line   or 1)&#10;  before = tonumber(before or 10)&#10;  after  = tonumber(after  or before)&#10;&#10;  if not string.find(file,'%.') then file = file..'.lua' end&#10;&#10;  local f = io.open(file,'r')&#10;  if not f then&#10;    --{{{  try to find the file in the path&#10;&#10;    --&#10;    -- looks for a file in the package path&#10;    --&#10;    local path = package.path or LUA_PATH or ''&#10;    for c in string.gmatch (path, &quot;[&#94;;]+&quot;) do&#10;      local c = string.gsub (c, &quot;%?%.lua&quot;, file)&#10;      f = io.open (c,'r')&#10;      if f then&#10;        break&#10;      end&#10;    end&#10;&#10;    --}}}&#10;    if not f then&#10;      ctrlrDebugger:write('Cannot find '..file..'\n')&#10;      return&#10;    end&#10;  end&#10;&#10;  local i = 0&#10;  for l in f:lines() do&#10;    i = i + 1&#10;    if i &gt;= (line-before) then&#10;      if i &gt; (line+after) then break end&#10;      if i == line then&#10;        ctrlrDebugger:write(i..'***\t'..l..'\n')&#10;      else&#10;        ctrlrDebugger:write(i..'\t'..l..'\n')&#10;      end&#10;    end&#10;  end&#10;&#10;  f:close()&#10;&#10;end&#10;&#10;--}}}&#10;--{{{  local function tracestack(l)&#10;&#10;local function gi( i )&#10;  return function() i=i+1 return debug.getinfo(i),i end&#10;end&#10;&#10;local function gl( level, j )&#10;  return function() j=j+1 return debug.getlocal( level, j ) end&#10;end&#10;&#10;local function gu( func, k )&#10;  return function() k=k+1 return debug.getupvalue( func, k ) end&#10;end&#10;&#10;local  traceinfo&#10;&#10;local function tracestack(l)&#10;  local l = l + 1                        --NB: +1 to get level relative to caller&#10;  traceinfo = {}&#10;  traceinfo.pausemsg = pausemsg&#10;  for ar,i in gi(l) do&#10;    table.insert( traceinfo, ar )&#10;    if ar.what ~= 'C' then&#10;      local names  = {}&#10;      local values = {}&#10;      for n,v in gl(i,0) do&#10;        if string.sub(n,1,1) ~= '(' then   --ignore internal control variables&#10;          table.insert( names, n )&#10;          table.insert( values, v )&#10;        end&#10;      end&#10;      if #names &gt; 0 then&#10;        ar.lnames  = names&#10;        ar.lvalues = values&#10;      end&#10;    end&#10;    if ar.func then&#10;      local names  = {}&#10;      local values = {}&#10;      for n,v in gu(ar.func,0) do&#10;        if string.sub(n,1,1) ~= '(' then   --ignore internal control variables&#10;          table.insert( names, n )&#10;          table.insert( values, v )&#10;        end&#10;      end&#10;      if #names &gt; 0 then&#10;        ar.unames  = names&#10;        ar.uvalues = values&#10;      end&#10;    end&#10;  end&#10;end&#10;&#10;--}}}&#10;--{{{  local function trace()&#10;&#10;local function trace(set)&#10;  ctrlrDebugger:write (&quot;\n::start trace\n&quot;)&#10;  local mark&#10;  for level,ar in ipairs(traceinfo) do&#10;    if level == set then&#10;      mark = '***'&#10;    else&#10;      mark = ''&#10;    end&#10;    ctrlrDebugger:write('['..level..']'..mark..'\t'..(ar.name or ar.what)..' in '..ar.short_src..':'..ar.currentline..'\n')&#10;  end&#10;&#10;  ctrlrDebugger:write (&quot;::end\n&quot;)&#10;end&#10;&#10;--}}}&#10;--{{{  local function info()&#10;&#10;local function info()&#10;    dumpvar( traceinfo, 0, 'traceinfo' )&#10;end&#10;&#10;--}}}&#10;&#10;--{{{  local function set_breakpoint(file, line, once)&#10;&#10;local function set_breakpoint(file, line, once)&#10;  if not breakpoints[line] then&#10;    breakpoints[line] = {}&#10;  end&#10;  if once then&#10;    breakpoints[line][file] = 1&#10;  else&#10;    breakpoints[line][file] = true&#10;  end&#10;end&#10;&#10;--}}}&#10;--{{{  local function remove_breakpoint(file, line)&#10;&#10;local function remove_breakpoint(file, line)&#10;  if breakpoints[line] then&#10;    breakpoints[line][file] = nil&#10;  end&#10;end&#10;&#10;--}}}&#10;--{{{  local function has_breakpoint(file, line)&#10;&#10;--allow for 'sloppy' file names&#10;--search for file and all variations walking up its directory hierachy&#10;--ditto for the file with no extension&#10;--a breakpoint can be permenant or once only, if once only its removed&#10;--after detection here, these are used for temporary breakpoints in the&#10;--debugger loop when executing the 'gotoo' command&#10;--a breakpoint on line 0 of a file means any line in that file&#10;&#10;local function has_breakpoint(file, line)&#10;  local isLine = breakpoints[line]&#10;  local isZero = breakpoints[0]&#10;  if not isLine and not isZero then return false end&#10;  local noext = string.gsub(file,&quot;(%..-)$&quot;,'',1)&#10;  if noext == file then noext = nil end&#10;  while file do&#10;    if isLine and isLine[file] then&#10;      if isLine[file] == 1 then isLine[file] = nil end&#10;      return true&#10;    end&#10;    if isZero and isZero[file] then&#10;      if isZero[file] == 1 then isZero[file] = nil end&#10;      return true&#10;    end&#10;    if IsWindows then&#10;      file = string.match(file,&quot;[:/\\](.+)$&quot;)&#10;    else&#10;      file = string.match(file,&quot;[:/](.+)$&quot;)&#10;    end&#10;  end&#10;  while noext do&#10;    if isLine and isLine[noext] then&#10;      if isLine[noext] == 1 then isLine[noext] = nil end&#10;      return true&#10;    end&#10;    if isZero and isZero[noext] then&#10;      if isZero[noext] == 1 then isZero[noext] = nil end&#10;      return true&#10;    end&#10;    if IsWindows then&#10;      noext = string.match(noext,&quot;[:/\\](.+)$&quot;)&#10;    else&#10;      noext = string.match(noext,&quot;[:/](.+)$&quot;)&#10;    end&#10;  end&#10;  return false&#10;end&#10;&#10;--}}}&#10;--{{{  local function capture_vars(ref,level,line)&#10;&#10;local function capture_vars(ref,level,line)&#10;  --get vars, file and line for the given level relative to debug_hook offset by ref&#10;&#10;  local lvl = ref + level                --NB: This includes an offset of +1 for the call to here&#10;&#10;  --{{{  capture variables&#10;&#10;  local ar = debug.getinfo(lvl, &quot;f&quot;)&#10;  if not ar then return {},'?',0 end&#10;&#10;  local vars = {__UPVALUES__={}, __LOCALS__={}}&#10;  local i&#10;&#10;  local func = ar.func&#10;  if func then&#10;    i = 1&#10;    while true do&#10;      local name, value = debug.getupvalue(func, i)&#10;      if not name then break end&#10;      if string.sub(name,1,1) ~= '(' then  --NB: ignoring internal control variables&#10;        vars[name] = value&#10;        vars.__UPVALUES__[i] = name&#10;      end&#10;      i = i + 1&#10;    end&#10;    vars.__ENVIRONMENT__ = getfenv(func)&#10;  end&#10;&#10;  vars.__GLOBALS__ = getfenv(0)&#10;&#10;  i = 1&#10;  while true do&#10;    local name, value = debug.getlocal(lvl, i)&#10;    if not name then break end&#10;    if string.sub(name,1,1) ~= '(' then    --NB: ignoring internal control variables&#10;      vars[name] = value&#10;      vars.__LOCALS__[i] = name&#10;    end&#10;    i = i + 1&#10;  end&#10;&#10;  vars.__VARSLEVEL__ = level&#10;&#10;  if func then&#10;    --NB: Do not do this until finished filling the vars table&#10;    setmetatable(vars, { __index = getfenv(func), __newindex = getfenv(func) })&#10;  end&#10;&#10;  --NB: Do not read or write the vars table anymore else the metatable functions will get invoked!&#10;&#10;  --}}}&#10;&#10;  local file = getinfo(lvl, &quot;source&quot;)&#10;  if string.find(file, &quot;@&quot;) == 1 then&#10;    file = string.sub(file, 2)&#10;  end&#10;  if IsWindows then file = string.lower(file) end&#10;&#10;  if not line then&#10;    line = getinfo(lvl, &quot;currentline&quot;)&#10;  end&#10;&#10;  return vars,file,line&#10;&#10;end&#10;&#10;--}}}&#10;--{{{  local function restore_vars(ref,vars)&#10;&#10;local function restore_vars(ref,vars)&#10;&#10;  if type(vars) ~= 'table' then return end&#10;&#10;  local level = vars.__VARSLEVEL__       --NB: This level is relative to debug_hook offset by ref&#10;  if not level then return end&#10;&#10;  level = level + ref                    --NB: This includes an offset of +1 for the call to here&#10;&#10;  local i&#10;  local written_vars = {}&#10;&#10;  i = 1&#10;  while true do&#10;    local name, value = debug.getlocal(level, i)&#10;    if not name then break end&#10;    if vars[name] and string.sub(name,1,1) ~= '(' then     --NB: ignoring internal control variables&#10;      debug.setlocal(level, i, vars[name])&#10;      written_vars[name] = true&#10;    end&#10;    i = i + 1&#10;  end&#10;&#10;  local ar = debug.getinfo(level, &quot;f&quot;)&#10;  if not ar then return end&#10;&#10;  local func = ar.func&#10;  if func then&#10;&#10;    i = 1&#10;    while true do&#10;      local name, value = debug.getupvalue(func, i)&#10;      if not name then break end&#10;      if vars[name] and string.sub(name,1,1) ~= '(' then   --NB: ignoring internal control variables&#10;        if not written_vars[name] then&#10;          debug.setupvalue(func, i, vars[name])&#10;        end&#10;        written_vars[name] = true&#10;      end&#10;      i = i + 1&#10;    end&#10;&#10;  end&#10;&#10;end&#10;&#10;--}}}&#10;--{{{  local function trace_event(event, line, level)&#10;&#10;local function print_trace(level,depth,event,file,line,name)&#10;&#10;  --NB: level here is relative to the caller of trace_event, so offset by 2 to get to there&#10;  level = level + 2&#10;&#10;  local file = file or getinfo(level,'short_src')&#10;  local line = line or getinfo(level,'currentline')&#10;  local name = name or getinfo(level,'name')&#10;&#10;  local prefix = ''&#10;  if current_thread ~= 'main' then prefix = '['..tostring(current_thread)..'] ' end&#10;&#10;  ctrlrDebugger:write(prefix..&#10;           string.format('%08.2f:%02i.',os.clock(),depth)..&#10;           string.rep('.',depth%32)..&#10;           (file or '')..' ('..(line or '')..') '..&#10;           (name or '')..&#10;           ' ('..event..')\n')&#10;&#10;end&#10;&#10;local function trace_event(event, line, level)&#10;&#10;  if event == 'return' and trace_returns then&#10;    --note the line info for later&#10;    ret_file = getinfo(level+1,'short_src')&#10;    ret_line = getinfo(level+1,'currentline')&#10;    ret_name = getinfo(level+1,'name')&#10;  end&#10;&#10;  if event ~= 'line' then return end&#10;&#10;  local slevel = stack_level[current_thread]&#10;  local tlevel = trace_level[current_thread]&#10;&#10;  if trace_calls and slevel &gt; tlevel then&#10;    --we are now in the function called, so look back 1 level further to find the calling file and line&#10;    print_trace(level+1,slevel-1,'c',nil,nil,getinfo(level+1,'name'))&#10;  end&#10;&#10;  if trace_returns and slevel &lt; tlevel then&#10;    print_trace(level,slevel,'r',ret_file,ret_line,ret_name)&#10;  end&#10;&#10;  if trace_lines then&#10;    print_trace(level,slevel,'l')&#10;  end&#10;&#10;  trace_level[current_thread] = stack_level[current_thread]&#10;&#10;end&#10;&#10;--}}}&#10;--{{{  local function report(ev, vars, file, line, idx_watch)&#10;&#10;local function report(ev, vars, file, line, idx_watch)&#10;  local vars = vars or {}&#10;  local file = file or '?'&#10;  local line = line or 0&#10;  local prefix = ''&#10;  if current_thread ~= 'main' then prefix = '['..tostring(current_thread)..'] ' end&#10;  if ev == events.STEP then&#10;    ctrlrDebugger:write(prefix..&quot;Paused at file &quot;..file..&quot; line &quot;..line..' ('..stack_level[current_thread]..')\n')&#10;  elseif ev == events.BREAK then&#10;    ctrlrDebugger:write(prefix..&quot;Paused at file &quot;..file..&quot; line &quot;..line..' ('..stack_level[current_thread]..') (breakpoint)\n')&#10;  elseif ev == events.WATCH then&#10;    ctrlrDebugger:write(prefix..&quot;Paused at file &quot;..file..&quot; line &quot;..line..' ('..stack_level[current_thread]..')'..&quot; (watch expression &quot;..idx_watch.. &quot;: [&quot;..watches[idx_watch].exp..&quot;])\n&quot;)&#10;  elseif ev == events.SET then&#10;    --do nothing&#10;  else&#10;    ctrlrDebugger:write(prefix..&quot;Error in application: &quot;..file..&quot; line &quot;..line..&quot;\n&quot;)&#10;  end&#10;  if ev ~= events.SET then&#10;    if pausemsg and pausemsg ~= '' then ctrlrDebugger:write('Message: '..pausemsg..'\n') end&#10;    pausemsg = ''&#10;  end&#10;  return vars, file, line&#10;end&#10;&#10;--}}}&#10;&#10;--{{{  local function debugger_loop(ev, vars, file, line, idx_watch)&#10;&#10;local function debugger_loop(ev, vars, file, line, idx_watch)&#10;&#10;  local eval_env  = vars or {}&#10;  local breakfile = file or '?'&#10;  local breakline = line or 0&#10;&#10;  local command, args&#10;&#10;  --{{{  local function getargs(spec)&#10;&#10;  --get command arguments according to the given spec from the args string&#10;  --the spec has a single character for each argument, arguments are separated&#10;  --by white space, the spec characters can be one of:&#10;  -- F for a filename    (defaults to breakfile if - given in args)&#10;  -- L for a line number (defaults to breakline if - given in args)&#10;  -- N for a number&#10;  -- V for a variable name&#10;  -- S for a string&#10;&#10;  local function getargs(spec)&#10;    local res={}&#10;    local char,arg&#10;    local ptr=1&#10;    for i=1,string.len(spec) do&#10;      char = string.sub(spec,i,i)&#10;      if     char == 'F' then&#10;        _,ptr,arg = string.find(args..' ',&quot;%s*([%w%p]*)%s*&quot;,ptr)&#10;        if not arg or arg == '' then arg = '-' end&#10;        if arg == '-' then arg = breakfile end&#10;      elseif char == 'L' then&#10;        _,ptr,arg = string.find(args..' ',&quot;%s*([%w%p]*)%s*&quot;,ptr)&#10;        if not arg or arg == '' then arg = '-' end&#10;        if arg == '-' then arg = breakline end&#10;        arg = tonumber(arg) or 0&#10;      elseif char == 'N' then&#10;        _,ptr,arg = string.find(args..' ',&quot;%s*([%w%p]*)%s*&quot;,ptr)&#10;        if not arg or arg == '' then arg = '0' end&#10;        arg = tonumber(arg) or 0&#10;      elseif char == 'V' then&#10;        _,ptr,arg = string.find(args..' ',&quot;%s*([%w%p]*)%s*&quot;,ptr)&#10;        if not arg or arg == '' then arg = '' end&#10;      elseif char == 'S' then&#10;        _,ptr,arg = string.find(args..' ',&quot;%s*([%w%p]*)%s*&quot;,ptr)&#10;        if not arg or arg == '' then arg = '' end&#10;      else&#10;        arg = ''&#10;      end&#10;      table.insert(res,arg or '')&#10;    end&#10;    return unpack(res)&#10;  end&#10;&#10;  --}}}&#10;&#10;  while true do&#10;    -- io.write(&quot;[DEBUG]&gt; &quot;)&#10;    ctrlrDebugger:write(&quot;[DEBUG]&gt; &quot;)&#10;    -- local line = io.read(&quot;*line&quot;)&#10;    local line = ctrlrDebugger:read()&#10;    if line == nil then ctrlrDebugger:write('\n'); line = 'exit' end&#10;&#10;    if string.find(line, &quot;&#94;[a-z]+&quot;) then&#10;      command = string.sub(line, string.find(line, &quot;&#94;[a-z]+&quot;))&#10;      args    = string.gsub(line,&quot;&#94;[a-z]+%s*&quot;,'',1)            --strip command off line&#10;    else&#10;      command = ''&#10;    end&#10;&#10;    if command == &quot;setb&quot; then&#10;      --{{{  set breakpoint&#10;&#10;      local line, filename  = getargs('LF')&#10;      if filename ~= '' and line ~= '' then&#10;        set_breakpoint(filename,line)&#10;        ctrlrDebugger:write(&quot;Breakpoint set in file &quot;..filename..' line '..line..'\n')&#10;      else&#10;        ctrlrDebugger:write(&quot;Bad request\n&quot;)&#10;      end&#10;&#10;      --}}}&#10;&#10;    elseif command == &quot;delb&quot; then&#10;      --{{{  delete breakpoint&#10;&#10;      local line, filename = getargs('LF')&#10;      if filename ~= '' and line ~= '' then&#10;        remove_breakpoint(filename, line)&#10;        ctrlrDebugger:write(&quot;Breakpoint deleted from file &quot;..filename..' line '..line..&quot;\n&quot;)&#10;      else&#10;        ctrlrDebugger:write(&quot;Bad request\n&quot;)&#10;      end&#10;&#10;      --}}}&#10;&#10;    elseif command == &quot;delallb&quot; then&#10;      --{{{  delete all breakpoints&#10;      breakpoints = {}&#10;      ctrlrDebugger:write('All breakpoints deleted\n')&#10;      --}}}&#10;&#10;    elseif command == &quot;listb&quot; then&#10;      --{{{  list breakpoints&#10;      for i, v in pairs(breakpoints) do&#10;        for ii, vv in pairs(v) do&#10;          ctrlrDebugger:write(&quot;Break at: &quot;..i..' in '..ii..'\n')&#10;        end&#10;      end&#10;      --}}}&#10;&#10;    elseif command == &quot;setw&quot; then&#10;      --{{{  set watch expression&#10;&#10;      if args and args ~= '' then&#10;        local func = loadstring(&quot;return(&quot; .. args .. &quot;)&quot;)&#10;        local newidx = #watches + 1&#10;        watches[newidx] = {func = func, exp = args}&#10;        ctrlrDebugger:write(&quot;Set watch exp no. &quot; .. newidx..'\n')&#10;      else&#10;        ctrlrDebugger:write(&quot;Bad request\n&quot;)&#10;      end&#10;&#10;      --}}}&#10;&#10;    elseif command == &quot;delw&quot; then&#10;      --{{{  delete watch expression&#10;&#10;      local index = tonumber(args)&#10;      if index then&#10;        watches[index] = nil&#10;        ctrlrDebugger:write(&quot;Watch expression deleted\n&quot;)&#10;      else&#10;        ctrlrDebugger:write(&quot;Bad request\n&quot;)&#10;      end&#10;&#10;      --}}}&#10;&#10;    elseif command == &quot;delallw&quot; then&#10;      --{{{  delete all watch expressions&#10;      watches = {}&#10;      ctrlrDebugger:write('All watch expressions deleted\n')&#10;      --}}}&#10;&#10;    elseif command == &quot;listw&quot; then&#10;      --{{{  list watch expressions&#10;      for i, v in pairs(watches) do&#10;        ctrlrDebugger:write(&quot;Watch exp. &quot; .. i .. &quot;: &quot; .. v.exp..'\n')&#10;      end&#10;      --}}}&#10;&#10;    elseif command == &quot;run&quot; then&#10;      --{{{  run until breakpoint&#10;      step_into = false&#10;      step_over = false&#10;      return 'cont'&#10;      --}}}&#10;&#10;    elseif command == &quot;step&quot; then&#10;      --{{{  step N lines (into functions)&#10;      local N = tonumber(args) or 1&#10;      step_over  = false&#10;      step_into  = true&#10;      step_lines = tonumber(N or 1)&#10;      return 'cont'&#10;      --}}}&#10;&#10;    elseif command == &quot;over&quot; then&#10;      --{{{  step N lines (over functions)&#10;      local N = tonumber(args) or 1&#10;      step_into  = false&#10;      step_over  = true&#10;      step_lines = tonumber(N or 1)&#10;      step_level[current_thread] = stack_level[current_thread]&#10;      return 'cont'&#10;      --}}}&#10;&#10;    elseif command == &quot;out&quot; then&#10;      --{{{  step N lines (out of functions)&#10;      local N = tonumber(args) or 1&#10;      step_into  = false&#10;      step_over  = true&#10;      step_lines = 1&#10;      step_level[current_thread] = stack_level[current_thread] - tonumber(N or 1)&#10;      return 'cont'&#10;      --}}}&#10;&#10;    elseif command == &quot;gotoo&quot; then&#10;      --{{{  step until reach line&#10;      local line, filename = getargs('LF')&#10;      if line ~= '' then&#10;        step_over  = false&#10;        step_into  = false&#10;        if has_breakpoint(filename,line) then&#10;          return 'cont'&#10;        else&#10;          set_breakpoint(filename,line,true)&#10;          return 'cont'&#10;        end&#10;      else&#10;        ctrlrDebugger:write(&quot;Bad request\n&quot;)&#10;      end&#10;      --}}}&#10;&#10;    elseif command == &quot;set&quot; then&#10;      --{{{  set/show context level&#10;      local level = args&#10;      if level and level == '' then level = nil end&#10;      if level then return level end&#10;      --}}}&#10;&#10;    elseif command == &quot;vars&quot; then&#10;      --{{{  list context variables&#10;      local depth = args&#10;      if depth and depth == '' then depth = nil end&#10;      depth = tonumber(depth) or 1&#10;      dumpvar(eval_env, depth+1, 'variables')&#10;      --}}}&#10;&#10;    elseif command == &quot;glob&quot; then&#10;      --{{{  list global variables&#10;      local depth = args&#10;      if depth and depth == '' then depth = nil end&#10;      depth = tonumber(depth) or 1&#10;      dumpvar(eval_env.__GLOBALS__,depth+1,'globals')&#10;      --}}}&#10;&#10;    elseif command == &quot;fenv&quot; then&#10;      --{{{  list function environment variables&#10;      local depth = args&#10;      if depth and depth == '' then depth = nil end&#10;      depth = tonumber(depth) or 1&#10;      dumpvar(eval_env.__ENVIRONMENT__,depth+1,'environment')&#10;      --}}}&#10;&#10;    elseif command == &quot;ups&quot; then&#10;      --{{{  list upvalue names&#10;      dumpvar(eval_env.__UPVALUES__,2,'upvalues')&#10;      --}}}&#10;&#10;    elseif command == &quot;locs&quot; then&#10;      --{{{  list locals names&#10;      dumpvar(eval_env.__LOCALS__,2,'upvalues')&#10;      --}}}&#10;&#10;    elseif command == &quot;what&quot; then&#10;      --{{{  show where a function is defined&#10;      if args and args ~= '' then&#10;        local v = eval_env&#10;        local n = nil&#10;        for w in string.gmatch(args,&quot;[%w_]+&quot;) do&#10;          v = v[w]&#10;          if n then n = n..'.'..w else n = w end&#10;          if not v then break end&#10;        end&#10;        if type(v) == 'function' then&#10;          local def = debug.getinfo(v,'S')&#10;          if def then&#10;            ctrlrDebugger:write(def.what..' in '..def.short_src..' '..def.linedefined..'..'..def.lastlinedefined..'\n')&#10;          else&#10;            ctrlrDebugger:write('Cannot get info for '..v..'\n')&#10;          end&#10;        else&#10;          ctrlrDebugger:write(v..' is not a function\n')&#10;        end&#10;      else&#10;        ctrlrDebugger:write(&quot;Bad request\n&quot;)&#10;      end&#10;      --}}}&#10;&#10;    elseif command == &quot;dump&quot; then&#10;      --{{{  dump a variable&#10;      local name, depth = getargs('VN')&#10;      if name ~= '' then&#10;        if depth == '' or depth == 0 then depth = nil end&#10;        depth = tonumber(depth or 1)&#10;        local v = eval_env&#10;        local n = nil&#10;        for w in string.gmatch(name,&quot;[&#94;%.]+&quot;) do     --get everything between dots&#10;          if tonumber(w) then&#10;            v = v[tonumber(w)]&#10;          else&#10;            v = v[w]&#10;          end&#10;          if n then n = n..'.'..w else n = w end&#10;          if not v then break end&#10;        end&#10;        dumpvar(v,depth+1,n)&#10;      else&#10;        ctrlrDebugger:write(&quot;Bad request\n&quot;)&#10;      end&#10;      --}}}&#10;&#10;    elseif command == &quot;show&quot; then&#10;      --{{{  show file around a line or the current breakpoint&#10;&#10;      local line, file, before, after = getargs('LFNN')&#10;      if before == 0 then before = 10     end&#10;      if after  == 0 then after  = before end&#10;&#10;      if file ~= '' and file ~= &quot;=stdin&quot; then&#10;        show(file,line,before,after)&#10;      else&#10;        ctrlrDebugger:write('Nothing to show\n')&#10;      end&#10;&#10;      --}}}&#10;&#10;    elseif command == &quot;poff&quot; then&#10;      --{{{  turn pause command off&#10;      pause_off = true&#10;      --}}}&#10;&#10;    elseif command == &quot;pon&quot; then&#10;      --{{{  turn pause command on&#10;      pause_off = false&#10;      --}}}&#10;&#10;    elseif command == &quot;tron&quot; then&#10;      --{{{  turn tracing on/off&#10;      local option = getargs('S')&#10;      trace_calls   = false&#10;      trace_returns = false&#10;      trace_lines   = false&#10;      if string.find(option,'c') then trace_calls   = true end&#10;      if string.find(option,'r') then trace_returns = true end&#10;      if string.find(option,'l') then trace_lines   = true end&#10;      --}}}&#10;&#10;    elseif command == &quot;trace&quot; then&#10;      --{{{  dump a stack trace&#10;      trace(eval_env.__VARSLEVEL__)&#10;      --}}}&#10;&#10;    elseif command == &quot;info&quot; then&#10;      --{{{  dump all debug info captured&#10;      info()&#10;      --}}}&#10;&#10;    elseif command == &quot;pause&quot; then&#10;      --{{{  not allowed in here&#10;      ctrlrDebugger:write('pause() should only be used in the script you are debugging\n')&#10;      --}}}&#10;&#10;    elseif command == &quot;help&quot; then&#10;      --{{{  help&#10;      local command = getargs('S')&#10;      if command ~= '' and hints[command] then&#10;        ctrlrDebugger:write(hints[command]..'\n')&#10;      else&#10;        for _,v in pairs(hints) do&#10;          local _,_,h = string.find(v,&quot;(.+)|&quot;)&#10;          ctrlrDebugger:write(h..'\n')&#10;        end&#10;      end&#10;      --}}}&#10;&#10;    elseif command == &quot;exit&quot; then&#10;      --{{{  exit debugger&#10;      return 'stop'&#10;      --}}}&#10;&#10;    elseif line ~= '' then&#10;      --{{{  just execute whatever it is in the current context&#10;&#10;      --map line starting with &quot;=...&quot; to &quot;return ...&quot;&#10;      if string.sub(line,1,1) == '=' then line = string.gsub(line,'=','return ',1) end&#10;&#10;      local ok, func = pcall(loadstring,line)&#10;      if func == nil then                             --Michael.Bringmann@lsi.com&#10;        ctrlrDebugger:write(&quot;Compile error: &quot;..line..'\n')&#10;      elseif not ok then&#10;        ctrlrDebugger:write(&quot;Compile error: &quot;..func..'\n')&#10;      else&#10;        setfenv(func, eval_env)&#10;        local res = {pcall(func)}&#10;        if res[1] then&#10;          if res[2] then&#10;            table.remove(res,1)&#10;            for _,v in ipairs(res) do&#10;              ctrlrDebugger:write(tostring(v))&#10;              ctrlrDebugger:write('\t')&#10;            end&#10;            ctrlrDebugger:write('\n')&#10;          end&#10;          --update in the context&#10;          return 0&#10;        else&#10;          ctrlrDebugger:write(&quot;Run error: &quot;..res[2]..'\n')&#10;        end&#10;      end&#10;&#10;      --}}}&#10;    end&#10;  end&#10;&#10;end&#10;&#10;--}}}&#10;--{{{  local function debug_hook(event, line, level, thread)&#10;&#10;local function debug_hook(event, line, level, thread)&#10;  if not started then debug.sethook(); coro_debugger = nil; return end&#10;  current_thread = thread or 'main'&#10;  local level = level or 2&#10;  trace_event(event,line,level)&#10;  if event == &quot;call&quot; then&#10;    stack_level[current_thread] = stack_level[current_thread] + 1&#10;  elseif event == &quot;return&quot; then&#10;    stack_level[current_thread] = stack_level[current_thread] - 1&#10;    if stack_level[current_thread] &lt; 0 then stack_level[current_thread] = 0 end&#10;  else&#10;    local vars,file,line = capture_vars(level,1,line)&#10;    local stop, ev, idx = false, events.STEP, 0&#10;    while true do&#10;      for index, value in pairs(watches) do&#10;        setfenv(value.func, vars)&#10;        local status, res = pcall(value.func)&#10;        if status and res then&#10;          ev, idx = events.WATCH, index&#10;          stop = true&#10;          break&#10;        end&#10;      end&#10;      if stop then break end&#10;      if (step_into)&#10;      or (step_over and (stack_level[current_thread] &lt;= step_level[current_thread] or stack_level[current_thread] == 0)) then&#10;        step_lines = step_lines - 1&#10;        if step_lines &lt; 1 then&#10;          ev, idx = events.STEP, 0&#10;          break&#10;        end&#10;      end&#10;      if has_breakpoint(file, line) then&#10;        ev, idx = events.BREAK, 0&#10;        break&#10;      end&#10;      return&#10;    end&#10;    if not coro_debugger then&#10;      ctrlrDebugger:write(&quot;Lua Debugger\n&quot;)&#10;      vars, file, line = report(ev, vars, file, line, idx)&#10;      ctrlrDebugger:write(&quot;Type 'help' for commands\n&quot;)&#10;      coro_debugger = true&#10;    else&#10;      vars, file, line = report(ev, vars, file, line, idx)&#10;    end&#10;    tracestack(level)&#10;    local last_next = 1&#10;    local next = 'ask'&#10;    local silent = false&#10;    while true do&#10;      if next == 'ask' then&#10;        next = debugger_loop(ev, vars, file, line, idx)&#10;      elseif next == 'cont' then&#10;        return&#10;      elseif next == 'stop' then&#10;        started = false&#10;        debug.sethook()&#10;        coro_debugger = nil&#10;        return&#10;      elseif tonumber(next) then --get vars for given level or last level&#10;        next = tonumber(next)&#10;        if next == 0 then silent = true; next = last_next else silent = false end&#10;        last_next = next&#10;        restore_vars(level,vars)&#10;        vars, file, line = capture_vars(level,next)&#10;        if not silent then&#10;          if vars and vars.__VARSLEVEL__ then&#10;            ctrlrDebugger:write('Level: '..vars.__VARSLEVEL__..'\n')&#10;          else&#10;            ctrlrDebugger:write('No level set\n')&#10;          end&#10;        end&#10;        ev = events.SET&#10;        next = 'ask'&#10;      else&#10;        ctrlrDebugger:write('Unknown command from debugger_loop: '..tostring(next)..'\n')&#10;        ctrlrDebugger:write('Stopping debugger\n')&#10;        next = 'stop'&#10;      end&#10;    end&#10;  end&#10;end&#10;&#10;--}}}&#10;&#10;--{{{  coroutine.create&#10;&#10;--This function overrides the built-in for the purposes of propagating&#10;--the debug hook settings from the creator into the created coroutine.&#10;&#10;_G.coroutine.create = function(f)&#10;  local thread&#10;  local hook, mask, count = debug.gethook()&#10;  if hook then&#10;    local function thread_hook(event,line)&#10;      hook(event,line,3,thread)&#10;    end&#10;    thread = cocreate(function(...)&#10;                        stack_level[thread] = 0&#10;                        trace_level[thread] = 0&#10;                        step_level [thread] = 0&#10;                        debug.sethook(thread_hook,mask,count)&#10;                        return f(...)&#10;                      end)&#10;    return thread&#10;  else&#10;    return cocreate(f)&#10;  end&#10;end&#10;&#10;--}}}&#10;--{{{  coroutine.wrap&#10;&#10;--This function overrides the built-in for the purposes of propagating&#10;--the debug hook settings from the creator into the created coroutine.&#10;&#10;_G.coroutine.wrap = function(f)&#10;  local thread&#10;  local hook, mask, count = debug.gethook()&#10;  if hook then&#10;    local function thread_hook(event,line)&#10;      hook(event,line,3,thread)&#10;    end&#10;    thread = cowrap(function(...)&#10;                      stack_level[thread] = 0&#10;                      trace_level[thread] = 0&#10;                      step_level [thread] = 0&#10;                      debug.sethook(thread_hook,mask,count)&#10;                      return f(...)&#10;                    end)&#10;    return thread&#10;  else&#10;    return cowrap(f)&#10;  end&#10;end&#10;&#10;--}}}&#10;&#10;--{{{  function pause(x,l,f)&#10;&#10;--&#10;-- Starts/resumes a debug session&#10;--&#10;&#10;function pause(x,l,f)&#10;  if not f and pause_off then return end       --being told to ignore pauses&#10;  pausemsg = x or 'pause'&#10;  local lines&#10;  local src = getinfo(2,'short_src')&#10;  if l then&#10;    lines = l   --being told when to stop&#10;  elseif src == &quot;stdin&quot; then&#10;    lines = 1   --if in a console session, stop now&#10;  else&#10;    lines = 2   --if in a script, stop when get out of pause()&#10;  end&#10;  if started then&#10;    --we'll stop now 'cos the existing debug hook will grab us&#10;    step_lines = lines&#10;    step_into  = true&#10;    debug.sethook(debug_hook, &quot;crl&quot;)         --reset it in case some external agent fiddled with it&#10;  else&#10;    --set to stop when get out of pause()&#10;    trace_level[current_thread] = 0&#10;    step_level [current_thread] = 0&#10;    stack_level[current_thread] = 1&#10;    step_lines = lines&#10;    step_into  = true&#10;    started    = true&#10;    debug.sethook(debug_hook, &quot;crl&quot;)         --NB: this will cause an immediate entry to the debugger_loop&#10;  end&#10;end&#10;&#10;--}}}&#10;--{{{  function dump(v,depth)&#10;&#10;--shows the value of the given variable, only really useful&#10;--when the variable is a table&#10;--see dump debug command hints for full semantics&#10;&#10;function dump(v,depth)&#10;  dumpvar(v,(depth or 1)+1,tostring(v))&#10;end&#10;&#10;--}}}&#10;--{{{  function debug.traceback(x)&#10;&#10;local _traceback = debug.traceback       --note original function&#10;&#10;--override standard function&#10;debug.traceback = function(x)&#10;  local assertmsg = _traceback(x)        --do original function&#10;  pause(x)                               --let user have a look at stuff&#10;  return assertmsg                       --carry on&#10;end&#10;&#10;_TRACEBACK = debug.traceback             --Lua 5.0 function&#10;&#10;--}}}"
                   luaMethodLinkedProperty="" luaMethodSource="0" uuid="00000000000000000000000000000005"
                   luaMethodValid="1"/>
        <luaMethod luaMethodName="inspect" luaMethodCode="function getInspect()&#10;local inspect ={&#10;  _VERSION = 'inspect.lua 3.0.0',&#10;  _URL     = 'http://github.com/kikito/inspect.lua',&#10;  _DESCRIPTION = 'human-readable representations of tables',&#10;  _LICENSE = [[&#10;    MIT LICENSE&#10;&#10;    Copyright (c) 2013 Enrique Garc&#237;a Cota&#10;&#10;    Permission is hereby granted, free of charge, to any person obtaining a&#10;    copy of this software and associated documentation files (the&#10;    &quot;Software&quot;), to deal in the Software without restriction, including&#10;    without limitation the rights to use, copy, modify, merge, publish,&#10;    distribute, sublicense, and/or sell copies of the Software, and to&#10;    permit persons to whom the Software is furnished to do so, subject to&#10;    the following conditions:&#10;&#10;    The above copyright notice and this permission notice shall be included&#10;    in all copies or substantial portions of the Software.&#10;&#10;    THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS&#10;    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF&#10;    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.&#10;    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY&#10;    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,&#10;    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE&#10;    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.&#10;  ]]&#10;}&#10;&#10;inspect.KEY       = setmetatable({}, {__tostring = function() return 'inspect.KEY' end})&#10;inspect.METATABLE = setmetatable({}, {__tostring = function() return 'inspect.METATABLE' end})&#10;&#10;-- Apostrophizes the string if it has quotes, but not aphostrophes&#10;-- Otherwise, it returns a regular quoted string&#10;local function smartQuote(str)&#10;  if str:match('&quot;') and not str:match(&quot;'&quot;) then&#10;    return &quot;'&quot; .. str .. &quot;'&quot;&#10;  end&#10;  return '&quot;' .. str:gsub('&quot;', '\\&quot;') .. '&quot;'&#10;end&#10;&#10;local controlCharsTranslation = {&#10;  [&quot;\a&quot;] = &quot;\\a&quot;,  [&quot;\b&quot;] = &quot;\\b&quot;, [&quot;\f&quot;] = &quot;\\f&quot;,  [&quot;\n&quot;] = &quot;\\n&quot;,&#10;  [&quot;\r&quot;] = &quot;\\r&quot;,  [&quot;\t&quot;] = &quot;\\t&quot;, [&quot;\v&quot;] = &quot;\\v&quot;&#10;}&#10;&#10;local function escape(str)&#10;  local result = str:gsub(&quot;\\&quot;, &quot;\\\\&quot;):gsub(&quot;(%c)&quot;, controlCharsTranslation)&#10;  return result&#10;end&#10;&#10;local function isIdentifier(str)&#10;  return type(str) == 'string' and str:match( &quot;&#94;[_%a][_%a%d]*$&quot; )&#10;end&#10;&#10;local function isSequenceKey(k, length)&#10;  return type(k) == 'number'&#10;     and 1 &lt;= k&#10;     and k &lt;= length&#10;     and math.floor(k) == k&#10;end&#10;&#10;local defaultTypeOrders = {&#10;  ['number']   = 1, ['boolean']  = 2, ['string'] = 3, ['table'] = 4,&#10;  ['function'] = 5, ['userdata'] = 6, ['thread'] = 7&#10;}&#10;&#10;local function sortKeys(a, b)&#10;  local ta, tb = type(a), type(b)&#10;&#10;  -- strings and numbers are sorted numerically/alphabetically&#10;  if ta == tb and (ta == 'string' or ta == 'number') then return a &lt; b end&#10;&#10;  local dta, dtb = defaultTypeOrders[ta], defaultTypeOrders[tb]&#10;  -- Two default types are compared according to the defaultTypeOrders table&#10;  if dta and dtb then return defaultTypeOrders[ta] &lt; defaultTypeOrders[tb]&#10;  elseif dta     then return true  -- default types before custom ones&#10;  elseif dtb     then return false -- custom types after default ones&#10;  end&#10;&#10;  -- custom types are sorted out alphabetically&#10;  return ta &lt; tb&#10;end&#10;&#10;local function getNonSequentialKeys(t)&#10;  local keys, length = {}, #t&#10;  for k,_ in pairs(t) do&#10;    if not isSequenceKey(k, length) then table.insert(keys, k) end&#10;  end&#10;  table.sort(keys, sortKeys)&#10;  return keys&#10;end&#10;&#10;local function getToStringResultSafely(t, mt)&#10;  local __tostring = type(mt) == 'table' and rawget(mt, '__tostring')&#10;  local str, ok&#10;  if type(__tostring) == 'function' then&#10;    ok, str = pcall(__tostring, t)&#10;    str = ok and str or 'error: ' .. tostring(str)&#10;  end&#10;  if type(str) == 'string' and #str &gt; 0 then return str end&#10;end&#10;&#10;local maxIdsMetaTable = {&#10;  __index = function(self, typeName)&#10;    rawset(self, typeName, 0)&#10;    return 0&#10;  end&#10;}&#10;&#10;local idsMetaTable = {&#10;  __index = function (self, typeName)&#10;    local col = setmetatable({}, {__mode = &quot;kv&quot;})&#10;    rawset(self, typeName, col)&#10;    return col&#10;  end&#10;}&#10;&#10;local function countTableAppearances(t, tableAppearances)&#10;  tableAppearances = tableAppearances or setmetatable({}, {__mode = &quot;k&quot;})&#10;&#10;  if type(t) == 'table' then&#10;    if not tableAppearances[t] then&#10;      tableAppearances[t] = 1&#10;      for k,v in pairs(t) do&#10;        countTableAppearances(k, tableAppearances)&#10;        countTableAppearances(v, tableAppearances)&#10;      end&#10;      countTableAppearances(getmetatable(t), tableAppearances)&#10;    else&#10;      tableAppearances[t] = tableAppearances[t] + 1&#10;    end&#10;  end&#10;&#10;  return tableAppearances&#10;end&#10;&#10;local copySequence = function(s)&#10;  local copy, len = {}, #s&#10;  for i=1, len do copy[i] = s[i] end&#10;  return copy, len&#10;end&#10;&#10;local function makePath(path, ...)&#10;  local keys = {...}&#10;  local newPath, len = copySequence(path)&#10;  for i=1, #keys do&#10;    newPath[len + i] = keys[i]&#10;  end&#10;  return newPath&#10;end&#10;&#10;local function processRecursive(process, item, path)&#10;  if item == nil then return nil end&#10;&#10;  local processed = process(item, path)&#10;  if type(processed) == 'table' then&#10;    local processedCopy = {}&#10;    local processedKey&#10;&#10;    for k,v in pairs(processed) do&#10;      processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY))&#10;      if processedKey ~= nil then&#10;        processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey))&#10;      end&#10;    end&#10;&#10;    local mt  = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE))&#10;    setmetatable(processedCopy, mt)&#10;    processed = processedCopy&#10;  end&#10;  return processed&#10;end&#10;&#10;&#10;-------------------------------------------------------------------&#10;&#10;local Inspector = {}&#10;local Inspector_mt = {__index = Inspector}&#10;&#10;function Inspector:puts(...)&#10;  local args   = {...}&#10;  local buffer = self.buffer&#10;  local len    = #buffer&#10;  for i=1, #args do&#10;    len = len + 1&#10;    buffer[len] = tostring(args[i])&#10;  end&#10;end&#10;&#10;function Inspector:down(f)&#10;  self.level = self.level + 1&#10;  f()&#10;  self.level = self.level - 1&#10;end&#10;&#10;function Inspector:tabify()&#10;  self:puts(self.newline, string.rep(self.indent, self.level))&#10;end&#10;&#10;function Inspector:alreadyVisited(v)&#10;  return self.ids[type(v)][v] ~= nil&#10;end&#10;&#10;function Inspector:getId(v)&#10;  local tv = type(v)&#10;  local id = self.ids[tv][v]&#10;  if not id then&#10;    id              = self.maxIds[tv] + 1&#10;    self.maxIds[tv] = id&#10;    self.ids[tv][v] = id&#10;  end&#10;  return id&#10;end&#10;&#10;function Inspector:putKey(k)&#10;  if isIdentifier(k) then return self:puts(k) end&#10;  self:puts(&quot;[&quot;)&#10;  self:putValue(k)&#10;  self:puts(&quot;]&quot;)&#10;end&#10;&#10;function Inspector:putTable(t)&#10;  if t == inspect.KEY or t == inspect.METATABLE then&#10;    self:puts(tostring(t))&#10;  elseif self:alreadyVisited(t) then&#10;    self:puts('&lt;table ', self:getId(t), '&gt;')&#10;  elseif self.level &gt;= self.depth then&#10;    self:puts('{...}')&#10;  else&#10;    if self.tableAppearances[t] &gt; 1 then self:puts('&lt;', self:getId(t), '&gt;') end&#10;&#10;    local nonSequentialKeys = getNonSequentialKeys(t)&#10;    local length            = #t&#10;    local mt                = getmetatable(t)&#10;    local toStringResult    = getToStringResultSafely(t, mt)&#10;&#10;    self:puts('{')&#10;    self:down(function()&#10;      if toStringResult then&#10;        self:puts(' -- ', escape(toStringResult))&#10;        if length &gt;= 1 then self:tabify() end&#10;      end&#10;&#10;      local count = 0&#10;      for i=1, length do&#10;        if count &gt; 0 then self:puts(',') end&#10;        self:puts(' ')&#10;        self:putValue(t[i])&#10;        count = count + 1&#10;      end&#10;&#10;      for _,k in ipairs(nonSequentialKeys) do&#10;        if count &gt; 0 then self:puts(',') end&#10;        self:tabify()&#10;        self:putKey(k)&#10;        self:puts(' = ')&#10;        self:putValue(t[k])&#10;        count = count + 1&#10;      end&#10;&#10;      if mt then&#10;        if count &gt; 0 then self:puts(',') end&#10;        self:tabify()&#10;        self:puts('&lt;metatable&gt; = ')&#10;        self:putValue(mt)&#10;      end&#10;    end)&#10;&#10;    if #nonSequentialKeys &gt; 0 or mt then -- result is multi-lined. Justify closing }&#10;      self:tabify()&#10;    elseif length &gt; 0 then -- array tables have one extra space before closing }&#10;      self:puts(' ')&#10;    end&#10;&#10;    self:puts('}')&#10;  end&#10;end&#10;&#10;function Inspector:putValue(v)&#10;  local tv = type(v)&#10;&#10;  if tv == 'string' then&#10;    self:puts(smartQuote(escape(v)))&#10;  elseif tv == 'number' or tv == 'boolean' or tv == 'nil' then&#10;    self:puts(tostring(v))&#10;  elseif tv == 'table' then&#10;    self:putTable(v)&#10;  else&#10;    self:puts('&lt;',tv,' ',self:getId(v),'&gt;')&#10;  end&#10;end&#10;&#10;-------------------------------------------------------------------&#10;&#10;function inspect.inspect(root, options)&#10;  options       = options or {}&#10;&#10;  local depth   = options.depth   or math.huge&#10;  local newline = options.newline or '\n'&#10;  local indent  = options.indent  or '  '&#10;  local process = options.process&#10;&#10;  if process then&#10;    root = processRecursive(process, root, {})&#10;  end&#10;&#10;  local inspector = setmetatable({&#10;    depth            = depth,&#10;    buffer           = {},&#10;    level            = 0,&#10;    ids              = setmetatable({}, idsMetaTable),&#10;    maxIds           = setmetatable({}, maxIdsMetaTable),&#10;    newline          = newline,&#10;    indent           = indent,&#10;    tableAppearances = countTableAppearances(root)&#10;  }, Inspector_mt)&#10;&#10;  inspector:putValue(root)&#10;&#10;  return table.concat(inspector.buffer)&#10;end&#10;&#10;setmetatable(inspect, { __call = function(_, ...) return inspect.inspect(...) end })&#10;&#10;return inspect&#10;end&#10;&#10;inspect = getInspect()"
                   luaMethodLinkedProperty="" luaMethodSource="0" uuid="00000000000000000000000000000006"
                   luaMethodValid="1"/>
      </luaMethodGroup>
      <luaMethod luaMethodName="mastertune" luaMethodCode="--&#10;-- Called when a modulator value changes&#10;-- @mod   http://ctrlr.org/api/class_ctrlr_modulator.html&#10;-- @value    new numeric value of the modulator&#10;--&#13;&#10;&#10;mastertune = function(mod, value, source)&#13;&#10;&#9;local midich = panel:getProperty(&quot;panelMidiOutputChannelDevice&quot;) - 1&#13;&#10;&#9;local val = value + 1024&#13;&#10;&#9;local cents = string.format(&quot;%.01f Cents&quot;, value/10)&#13;&#10;&#9;if value&gt;0 then&#13;&#10;&#9;&#9;cents = &quot;+&quot; .. cents&#13;&#10;&#9;end&#13;&#10;&#9;panel:getComponent(&quot;mastertuneCents&quot;):setProperty(&quot;uiLabelText&quot;, cents, false)&#13;&#10;&#9;panel:getModulatorByName(&quot;mastertune2&quot;):setValue(value, false)&#13;&#10;&#9;&#13;&#10;&#9;-- colours&#13;&#10;&#9;local red&#13;&#10;&#9;local green&#13;&#10;&#9;local blue&#13;&#10;&#9;if value&lt;0 then&#13;&#10;&#9;&#9;blue = math.floor((1024+value)/4)&#13;&#10;&#9;    red = 255 - blue&#13;&#10;&#9;&#9;green = 0&#13;&#10;&#9;elseif value == 0 then&#13;&#10;&#9;&#9;red = 0&#13;&#10;&#9;&#9;blue = 255&#13;&#10;&#9;&#9;green = 0&#13;&#10;&#9;else&#13;&#10;&#9;&#9;green = math.floor(value/4)&#13;&#10;&#9;&#9;blue = 255 - green&#13;&#10;&#9;&#9;red = 0&#13;&#10;&#9;end&#13;&#10;&#9;--local red = math.floor((1023-value)/8)&#13;&#10;&#9;--local green = 255 - red&#13;&#10;&#9;--local blue = 128&#13;&#10;&#9;local colour = string.format(&quot;0xff%02x%02x%02x&quot;, red, green, blue)&#13;&#10;&#9;panel:getComponent(&quot;Mastertune&quot;):setProperty(&quot;uiSliderRotaryFillColour&quot;, colour, false)&#13;&#10;&#13;&#10;&#9;-- sysex values&#13;&#10;&#9;b0 = val % 16&#13;&#10;&#9;val = math.floor(val/16)&#13;&#10;&#9;b1 = val % 16&#13;&#10;&#9;val = math.floor(val/16)&#13;&#10;&#9;b2 = val % 8 -- value % 16&#13;&#10;&#9;val = math.floor(val/16)&#13;&#10;&#9;b3 = 0 -- val % 16&#13;&#10;&#13;&#10;&#9;local id=panel:getModulatorByName(&quot;Reface&quot;):getValue()+3&#13;&#10;&#9;local sysex = string.format(&quot;f0 43 1%x 7f 1c %02x 00 00 02 %02x %02x %02x %02x f7&quot;,midich, id, b3, b2, b1, b0)&#13;&#10;&#9;panel:getComponent(&quot;SysEx&quot;):setProperty(&quot;uiLabelText&quot;, sysex, false)&#13;&#10;&#9;panel:sendMidiMessageNow(CtrlrMidiMessage(sysex))&#13;&#10;&#13;&#10;&#9;tune2hz()&#10;end&#13;&#10;&#13;&#10;function tune2hz ()&#13;&#10;&#9;local tune = 440&#13;&#10;&#9;local cent = 2&#94;(1/1200)&#13;&#10;&#9;local cents = panel:getModulatorByName(&quot;Mastertune&quot;):getValue() / 10&#13;&#10;&#9;local transpose = 100 * panel:getModulatorByName(&quot;Transpose&quot;):getValue()&#13;&#10;&#9;local hz = cent &#94; cents * tune&#13;&#10;&#9;hz = cent &#94; transpose * hz&#13;&#10;&#9;panel:getComponent(&quot;mastertuneHz&quot;):setProperty(&quot;uiLabelText&quot;, string.format(&quot;%.02f Hz&quot;, hz), false)&#13;&#10;end&#13;&#10;"
                 luaMethodLinkedProperty="luaModulatorValueChange" luaMethodSource="0"
                 uuid="ca022d6ea9de43b6bd177639722e5373" luaMethodValid="1"/>
      <luaMethod luaMethodName="mastertranspose" luaMethodCode="--&#10;-- Called when a modulator value changes&#10;-- @mod   http://ctrlr.org/api/class_ctrlr_modulator.html&#10;-- @value    new numeric value of the modulator&#10;--&#10;mastertranspose = function(mod, value, source)&#13;&#10;&#9;local midich = panel:getProperty(&quot;panelMidiOutputChannelDevice&quot;) - 1&#13;&#10;&#9;local id=panel:getModulatorByName(&quot;Reface&quot;):getValue()+3&#13;&#10;&#9;local sysex = string.format(&quot;f0 43 1%x 7f 1c %02x 00 00 07 %02x f7&quot;, midich, id, value+64)&#13;&#10;&#9;panel:getComponent(&quot;SysEx&quot;):setProperty(&quot;uiLabelText&quot;, sysex, false)&#13;&#10;&#9;panel:sendMidiMessageNow(CtrlrMidiMessage(sysex))&#13;&#10;&#9;tune2hz()&#10;end"
                 luaMethodLinkedProperty="" luaMethodSource="0" uuid="46bcd7efb55a4a90a65d54ac745c33a9"
                 luaMethodValid="1"/>
      <luaMethod luaMethodName="refaceColours" luaMethodCode="--&#10;-- Called when a modulator value changes&#10;-- @mod   http://ctrlr.org/api/class_ctrlr_modulator.html&#10;-- @value    new numeric value of the modulator&#10;--&#10;refaceColours = function(mod, value, source)&#13;&#10;&#9;local bg = {&quot;ffe6e6e6&quot;, &quot;ff323232&quot;, &quot;ff523b1a&quot;, &quot;ff982221&quot;}&#13;&#10;&#9;local fg = {&quot;ff000000&quot;, &quot;ffffffff&quot;, &quot;ffffffff&quot;, &quot;ffffffff&quot;}&#13;&#10;&#9;local txt = {&quot;ff000000&quot;, &quot;ffffffff&quot;, &quot;ffffffff&quot;, &quot;ffffffff&quot;}&#13;&#10;&#13;&#10;&#9;panel:getComponent(&quot;Reface&quot;):setProperty(&quot;uiComboOutlineColour&quot;, fg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;Reface&quot;):setProperty(&quot;uiComboArrowColour&quot;, fg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;Reface&quot;):setProperty(&quot;uiComboButtonGradientColour1&quot;, bg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;Reface&quot;):setProperty(&quot;uiComboButtonGradientColour2&quot;, bg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;Reface&quot;):setProperty(&quot;uiComboButtonColour&quot;, bg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;Reface&quot;):setProperty(&quot;componentLabelColour&quot;, fg[value+1], false)&#13;&#10;&#9;&#13;&#10;&#9;panel:getComponent(&quot;SysEx&quot;):setProperty(&quot;uiLabelOutlineColour&quot;, fg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;mastertuneHz&quot;):setProperty(&quot;uiLabelOutlineColour&quot;, fg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;mastertuneCents&quot;):setProperty(&quot;uiLabelOutlineColour&quot;, fg[value+1], false)&#13;&#10;&#13;&#10;&#9;panel:getComponent(&quot;Transpose&quot;):setProperty(&quot;uiSliderRotaryOutlineColour&quot;, fg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;Transpose&quot;):setProperty(&quot;uiSliderRotaryFillColour&quot;, fg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;Transpose&quot;):setProperty(&quot;componentLabelColour&quot;, fg[value+1], false)&#13;&#10;&#13;&#10;&#9;panel:getComponent(&quot;Mastertune&quot;):setProperty(&quot;uiSliderRotaryOutlineColour&quot;, fg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;Mastertune&quot;):setProperty(&quot;componentLabelColour&quot;, fg[value+1], false)&#13;&#10;&#13;&#10;&#9;panel:getComponent(&quot;mastertune2&quot;):setProperty(&quot;uiSliderIncDecButtonColour&quot;, bg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;mastertune2&quot;):setProperty(&quot;uiSliderIncDecTextColour&quot;, fg[value+1], false)&#13;&#10;&#13;&#10;&#9;panel:getComponent(&quot;BACKGROUND&quot;):setProperty(&quot;uiGroupBackgroundColour1&quot;, bg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;BACKGROUND&quot;):setProperty(&quot;uiGroupBackgroundColour2&quot;, bg[value+1], false)&#13;&#10;end&#13;&#10;"
                 luaMethodLinkedProperty="" luaMethodSource="0" uuid="789b14d90e3b4db0ab75ec90d36641a4"
                 luaMethodValid="1"/>
      <luaMethod luaMethodName="skin" luaMethodCode="--&#10;-- Called when a modulator value changes&#10;-- @mod   http://ctrlr.org/api/class_ctrlr_modulator.html&#10;-- @value    new numeric value of the modulat&#13;&#10;function skin(mod, value, source)&#13;&#10;&#9;local bg = {&quot;ffe6e6e6&quot;, &quot;ff323232&quot;, &quot;ff523b1a&quot;, &quot;ff982221&quot;}&#13;&#10;&#9;local fg = {&quot;ff000000&quot;, &quot;ffffffff&quot;, &quot;ffffffff&quot;, &quot;ffffffff&quot;}&#13;&#10;&#9;local txt = {&quot;ff000000&quot;, &quot;ffffffff&quot;, &quot;ffffffff&quot;, &quot;ffffffff&quot;}&#13;&#10;&#13;&#10;&#9;panel:getComponent(&quot;Reface&quot;):setProperty(&quot;uiComboOutlineColour&quot;, fg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;Reface&quot;):setProperty(&quot;uiComboArrowColour&quot;, fg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;Reface&quot;):setProperty(&quot;uiComboButtonGradientColour1&quot;, bg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;Reface&quot;):setProperty(&quot;uiComboButtonGradientColour2&quot;, bg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;Reface&quot;):setProperty(&quot;uiComboButtonColour&quot;, bg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;Reface&quot;):setProperty(&quot;componentLabelColour&quot;, fg[value+1], false)&#13;&#10;&#9;&#13;&#10;&#9;panel:getComponent(&quot;SysEx&quot;):setProperty(&quot;uiLabelOutlineColour&quot;, fg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;mastertuneHz&quot;):setProperty(&quot;uiLabelOutlineColour&quot;, fg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;mastertuneCents&quot;):setProperty(&quot;uiLabelOutlineColour&quot;, fg[value+1], false)&#13;&#10;&#13;&#10;&#9;panel:getComponent(&quot;Transpose&quot;):setProperty(&quot;uiSliderRotaryOutlineColour&quot;, fg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;Transpose&quot;):setProperty(&quot;uiSliderRotaryFillColour&quot;, fg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;Transpose&quot;):setProperty(&quot;componentLabelColour&quot;, fg[value+1], false)&#13;&#10;&#13;&#10;&#9;panel:getComponent(&quot;Mastertune&quot;):setProperty(&quot;uiSliderRotaryOutlineColour&quot;, fg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;Mastertune&quot;):setProperty(&quot;componentLabelColour&quot;, fg[value+1], false)&#13;&#10;&#13;&#10;&#9;panel:getComponent(&quot;BACKGROUND&quot;):setProperty(&quot;uiGroupBackgroundColour1&quot;, bg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;BACKGROUND&quot;):setProperty(&quot;uiGroupBackgroundColour2&quot;, bg[value+1], false)&#13;&#10;&#13;&#10;&#9;panel:getComponent(&quot;mastertune2&quot;):setProperty(&quot;uiSliderIncDecButtonColour&quot;, bg[value+1], false)&#13;&#10;&#9;panel:getComponent(&quot;mastertune2&quot;):setProperty(&quot;uiSliderIncDecButtonTextColour&quot;, fg[value+1], false)&#13;&#10;&#13;&#10;&#9;local tune = panel:getModulatorByName(&quot;Mastertune&quot;):getValue()&#13;&#10;&#9;panel:getModulatorByName(&quot;Mastertune&quot;):setValue(2047-tune, false)&#13;&#10;&#9;panel:getModulatorByName(&quot;Mastertune&quot;):setValue(tune, false)&#13;&#10;end&#13;&#10;"
                 luaMethodLinkedProperty="" luaMethodSource="0" uuid="9d32e6b009e246069043e78df8f19043"
                 luaMethodValid="1"/>
      <luaMethod luaMethodName="mastertune2" luaMethodCode="--&#10;-- Called when a modulator value changes&#10;-- @mod   http://ctrlr.org/api/class_ctrlr_modulator.html&#10;-- @value    new numeric value of the modulator&#10;--&#10;mastertune2 = function(mod, value, source)&#9;&#10;&#9;panel:getModulatorByName(&quot;Mastertune&quot;):setValue(value, false)&#13;&#10;end"
                 luaMethodLinkedProperty="" luaMethodSource="0" uuid="4306037335a64d619c5ad84e1b2de70a"
                 luaMethodValid="1"/>
    </luaManagerMethods>
  </luaManager>
  <panelResources>
    <resource resourceHash="4737171476880306879" resourceLoadedTime="1618034754557"
              resourceSize="38838" resourceFile="knob_48x48_127frames.png"
              resourceSourceFile="/home/m.tarenskeen/Muziek/SysEx/Ctrlr/Images/knob_48x48_127frames.png"
              resourceName="knob_48x48_127frames" resourceType="Image"/>
  </panelResources>
  <uiPanelEditor uiPanelCanvasRectangle="0 0 331 457" uiPanelSnapSize="8" uiPanelBackgroundColour="0"
                 uiPanelBackgroundColour1="0" uiPanelBackgroundColour2="0" uiPanelBackgroundGradientType="1"
                 uiPanelImageResource="-- None" uiPanelEditMode="0" uiPanelLock="0"
                 uiPanelDisabledOnEdit="0" uiPanelMenuBarVisible="1" uiPanelMenuBarHideOnExport="0"
                 uiPanelWidth="400" uiPanelHeight="400" name="Reface Mastertune"
                 uiPanelImageAlpha="255" uiPanelImageLayout="64" uiPanelSnapActive="1"
                 uiPanelPropertiesOnRight="0" luaPanelPaintBackground="-- None"
                 luaPanelResized="-- None" luaPanelFileDragDropHandler="-- None"
                 luaPanelFileDragEnterHandler="-- None" luaPanelFileDragExitHandler="-- None"
                 uiPanelInvisibleComponentAlpha="0.5" uiPanelTooltipBackgroundColour="0xffeeeebb"
                 uiPanelTooltipOutlineColour="0xff000000" uiPanelTooltipColour="0xff000000"
                 uiPanelTooltipCornerRound="1" uiPanelTooltipPlacement="2" uiPanelTooltipFont="&lt;Sans-Serif&gt;;15;1;0;0;0;1;3"
                 uiPanelZoom="1" uiPanelPropertiesSize="271" uiPanelViewPortSize="1087"
                 uiPanelDisableCombosOnEdit="1">
    <uiPanelCanvasLayer uiPanelCanvasLayerName="New layer" uiPanelCanvasLayerUid="e95e3a2d04000000502975b4fe7f0000"
                        uiPanelCanvasLayerColour="0x000000" uiPanelCanvasLayerVisibility="1"
                        uiPanelCanvasLayerIndex="0"/>
  </uiPanelEditor>
  <modulator modulatorVstExported="1" modulatorMax="1023" vstIndex="0" modulatorIsStatic="0"
             modulatorGlobalVariable="-1" modulatorMuteOnStart="0" modulatorMute="0"
             modulatorExcludeFromSnapshot="0" modulatorValueExpression="modulatorValue"
             modulatorValueExpressionReverse="midiValue" modulatorControllerExpression="value"
             luaModulatorGetValueForMIDI="-- None" luaModulatorGetValueFromMIDI="-- None"
             modulatorLinkedToPanelProperty="-- None" modulatorLinkedToModulatorProperty="-- None"
             modulatorLinkedToModulator="-- None" modulatorLinkedToModulatorSource="1"
             modulatorLinkedToComponent="Modulator" modulatorBaseValue="0"
             modulatorCustomIndex="0" modulatorCustomName="" modulatorCustomIndexGroup="0"
             modulatorCustomNameGroup="" modulatorVstNameFormat="%n" luaModulatorValueChange="mastertune"
             name="Mastertune" modulatorMin="-1024" modulatorValue="0">
    <midi midiMessageType="9" midiMessageChannelOverride="0" midiMessageChannel="1"
          midiMessageCtrlrNumber="1" midiMessageCtrlrValue="0" midiMessageMultiList=""
          midiMessageSysExFormula=""/>
    <component componentLabelPosition="top" componentLabelJustification="centred"
               componentLabelHeight="14" componentLabelWidth="0" componentLabelVisible="1"
               componentLabelAlwaysOnTop="1" componentSentBack="0" componentLabelColour="ff000000"
               componentLabelFont="&lt;Sans-Serif&gt;;16;1;0;0;0;1;3" componentVisibleName="Mastertune"
               componentMouseCursor="2" componentGroupName="BACKGROUND" componentGroupped="1"
               componentSnapSize="0" componentIsLocked="0" componentDisabled="0"
               componentRadioGroupId="0" componentRadioGroupNotifyMidi="1" componentVisibility="1"
               componentEffect="0" componentEffectRadius="1" componentEffectColour="0xff000000"
               componentEffectOffsetX="0" componentEffectOffsetY="0" componentExcludedFromLabelDisplay="0"
               componentValueDecimalPlaces="0" componentLuaMouseMoved="-- None"
               componentLuaMouseDown="-- None" componentLuaMouseDrag="-- None"
               componentLuaMouseDoubleClick="-- None" uiSliderStyle="RotaryVerticalDrag"
               uiSliderMin="-1024" uiSliderMax="1023" uiSliderInterval="1" uiSliderDoubleClickEnabled="1"
               uiSliderDoubleClickValue="1024" uiSliderValuePosition="0" uiSliderValueHeight="24"
               uiSliderValueWidth="128" uiSliderTrackCornerSize="0" uiSliderThumbCornerSize="0"
               uiSliderThumbWidth="0" uiSliderThumbHeight="0" uiSliderThumbFlatOnLeft="0"
               uiSliderThumbFlatOnRight="0" uiSliderThumbFlatOnTop="0" uiSliderThumbFlatOnBottom="0"
               uiSliderValueTextColour="0xff000000" uiSliderValueBgColour="0xffffffff"
               uiSliderRotaryOutlineColour="ff000000" uiSliderRotaryFillColour="0xff0000ff"
               uiSliderThumbColour="0xffff0000" uiSliderValueHighlightColour="0xff0000ff"
               uiSliderValueOutlineColour="ff000088" uiSliderTrackColour="0xff0f0f0f"
               uiSliderIncDecButtonColour="0xff0000ff" uiSliderIncDecTextColour="0xffffffff"
               uiSliderValueFont="&lt;Sans-Serif&gt;;12;0;0;0;0;1;3" uiSliderValueTextJustification="centred"
               uiSliderVelocitySensitivity="1" uiSliderVelocityThreshold="1"
               uiSliderVelocityOffset="0" uiSliderVelocityMode="0" uiSliderVelocityModeKeyTrigger="1"
               uiSliderSpringMode="0" uiSliderSpringValue="0" uiSliderMouseWheelInterval="1"
               uiSliderPopupBubble="0" uiLabelText="440.00 Hz" uiType="uiSlider"
               componentRectangle="40 224 221 152" componentLayerUid="e95e3a2d04000000502975b4fe7f0000"/>
  </modulator>
  <modulator modulatorCustomIndex="0" modulatorCustomIndexGroup="0" modulatorIsStatic="1"
             name="mastertuneHz" modulatorVstExported="0" modulatorValue="0">
    <component componentLabelPosition="top" componentLabelJustification="centred"
               componentLabelHeight="14" componentLabelWidth="0" componentLabelVisible="0"
               componentLabelAlwaysOnTop="0" componentSentBack="0" componentLabelColour="0xff000000"
               componentLabelFont="&lt;Sans-Serif&gt;;12;0;0;0;0;1;3" componentVisibleName=""
               componentMouseCursor="2" componentGroupName="BACKGROUND" componentGroupped="1"
               componentSnapSize="0" componentIsLocked="0" componentDisabled="0"
               componentRadioGroupId="0" componentRadioGroupNotifyMidi="1" componentVisibility="1"
               componentEffect="0" componentEffectRadius="1" componentEffectColour="0xff000000"
               componentEffectOffsetX="0" componentEffectOffsetY="0" componentExcludedFromLabelDisplay="0"
               componentValueDecimalPlaces="0" componentLuaMouseMoved="-- None"
               componentLuaMouseDown="-- None" componentLuaMouseDrag="-- None"
               componentLuaMouseDoubleClick="-- None" uiLabelBgColour="ffffffff"
               uiLabelTextColour="0xff000000" uiLabelOutline="1" uiLabelOutlineColour="ff000000"
               uiLabelJustification="centred" uiLabelFitFont="0" uiLabelFont="&lt;Sans-Serif&gt;;14;0;0;0;0;1;3"
               uiLabelText="440.00 Hz" uiLabelDisplaysAllValues="0" uiLabelDisplayFormat="%n(%N) = %v(%h)"
               uiLabelInputHighlightTextColour="0xffffffff" uiLabelInputHighlightColour="0xff0000ff"
               uiLabelEditOnSingleClick="0" uiLabelEditOnDoubleClick="0" uiLabelEditFocusDiscardsChanges="1"
               uiLabelInputAllowedChars="" uiLabelInputMaxLength="1024" uiLabelChangedCbk="-- None"
               uiType="uiLabel" componentRectangle="40 80 109 32" componentLayerUid="e95e3a2d04000000502975b4fe7f0000"/>
  </modulator>
  <modulator modulatorVstExported="1" modulatorMax="3" vstIndex="1" modulatorIsStatic="0"
             modulatorGlobalVariable="-1" modulatorMuteOnStart="0" modulatorMute="0"
             modulatorExcludeFromSnapshot="0" modulatorValueExpression="modulatorValue"
             modulatorValueExpressionReverse="midiValue" modulatorControllerExpression="value"
             luaModulatorGetValueForMIDI="-- None" luaModulatorGetValueFromMIDI="-- None"
             modulatorLinkedToPanelProperty="-- None" modulatorLinkedToModulatorProperty="-- None"
             modulatorLinkedToModulator="-- None" modulatorLinkedToModulatorSource="1"
             modulatorLinkedToComponent="Modulator" modulatorBaseValue="0"
             modulatorCustomIndex="0" modulatorCustomName="" modulatorCustomIndexGroup="0"
             modulatorCustomNameGroup="" modulatorVstNameFormat="%n" luaModulatorValueChange="skin"
             name="Reface" modulatorMin="0" modulatorValue="0">
    <midi midiMessageType="9" midiMessageChannelOverride="0" midiMessageChannel="1"
          midiMessageCtrlrNumber="1" midiMessageCtrlrValue="0" midiMessageMultiList=""
          midiMessageSysExFormula=""/>
    <component componentLabelPosition="top" componentLabelJustification="centred"
               componentLabelHeight="14" componentLabelWidth="0" componentLabelVisible="1"
               componentLabelAlwaysOnTop="1" componentSentBack="0" componentLabelColour="ff000000"
               componentLabelFont="&lt;Sans-Serif&gt;;16;1;0;0;0;1;3" componentVisibleName="YAMAHA REFACE"
               componentMouseCursor="2" componentGroupName="BACKGROUND" componentGroupped="1"
               componentSnapSize="0" componentIsLocked="0" componentDisabled="0"
               componentRadioGroupId="0" componentRadioGroupNotifyMidi="1" componentVisibility="1"
               componentEffect="0" componentEffectRadius="1" componentEffectColour="0xff000000"
               componentEffectOffsetX="0" componentEffectOffsetY="0" componentExcludedFromLabelDisplay="0"
               componentValueDecimalPlaces="0" componentLuaMouseMoved="-- None"
               componentLuaMouseDown="-- None" componentLuaMouseDrag="-- None"
               componentLuaMouseDoubleClick="-- None" uiComboArrowColour="ff000000"
               uiComboOutlineColour="ff000000" uiComboTextColour="0xff000000"
               uiComboTextJustification="centred" uiComboFont="&lt;Sans-Serif&gt;;14;0;0;0;0;1;3"
               uiComboMenuFont="&lt;Sans-Serif&gt;;16;0;0;0;0;1;3" uiComboButtonColour="ffe6e6e6"
               uiComboBgColour="0xffffffff" uiComboMenuBackgroundColour="0xfff0f0f0"
               uiComboMenuFontColour="0xff000000" uiComboMenuHighlightColour="ffadd8e6"
               uiComboMenuFontHighlightedColour="0xff232323" uiComboContent="Reface CS&#10;Reface CP&#10;Reface DX&#10;Reface YC"
               uiComboMenuBackgroundRibbed="1" uiComboButtonGradient="0" uiComboButtonGradientColour1="ffe6e6e6"
               uiComboButtonGradientColour2="ffe6e6e6" uiComboButtonWidthOverride="0"
               uiComboButtonWidth="16" uiComboDynamicContent="0" uiComboSelectedId="-1"
               uiComboSelectedIndex="-1" uiType="uiCombo" componentRectangle="88 16 134 43"
               componentLayerUid="e95e3a2d04000000502975b4fe7f0000"/>
  </modulator>
  <modulator modulatorCustomIndex="0" modulatorCustomIndexGroup="0" modulatorIsStatic="1"
             name="SysEx" modulatorVstExported="0" modulatorValue="0">
    <component componentLabelPosition="top" componentLabelJustification="centred"
               componentLabelHeight="14" componentLabelWidth="0" componentLabelVisible="0"
               componentLabelAlwaysOnTop="0" componentSentBack="0" componentLabelColour="0xff000000"
               componentLabelFont="&lt;Sans-Serif&gt;;12;0;0;0;0;1;3" componentVisibleName=""
               componentMouseCursor="2" componentGroupName="BACKGROUND" componentGroupped="1"
               componentSnapSize="0" componentIsLocked="0" componentDisabled="0"
               componentRadioGroupId="0" componentRadioGroupNotifyMidi="1" componentVisibility="1"
               componentEffect="0" componentEffectRadius="1" componentEffectColour="0xff000000"
               componentEffectOffsetX="0" componentEffectOffsetY="0" componentExcludedFromLabelDisplay="0"
               componentValueDecimalPlaces="0" componentLuaMouseMoved="-- None"
               componentLuaMouseDown="-- None" componentLuaMouseDrag="-- None"
               componentLuaMouseDoubleClick="-- None" uiLabelBgColour="ffffffff"
               uiLabelTextColour="0xff000000" uiLabelOutline="1" uiLabelOutlineColour="ff000000"
               uiLabelJustification="centred" uiLabelFitFont="0" uiLabelFont="&lt;Sans-Serif&gt;;14;0;0;0;0;1;3"
               uiLabelText="f0 43 10 7f 1c 03 00 00 07 40 f7" uiLabelDisplaysAllValues="0"
               uiLabelDisplayFormat="%n(%N) = %v(%h)" uiLabelInputHighlightTextColour="0xffffffff"
               uiLabelInputHighlightColour="0xff0000ff" uiLabelEditOnSingleClick="0"
               uiLabelEditOnDoubleClick="0" uiLabelEditFocusDiscardsChanges="1"
               uiLabelInputAllowedChars="" uiLabelInputMaxLength="1024" uiLabelChangedCbk="-- None"
               uiType="uiLabel" componentRectangle="16 392 278 29" componentLayerUid="e95e3a2d04000000502975b4fe7f0000"/>
  </modulator>
  <modulator modulatorCustomIndex="0" modulatorCustomIndexGroup="0" modulatorIsStatic="1"
             name="mastertuneCents" modulatorVstExported="0" modulatorValue="0">
    <component componentLabelPosition="top" componentLabelJustification="centred"
               componentLabelHeight="14" componentLabelWidth="0" componentLabelVisible="0"
               componentLabelAlwaysOnTop="0" componentSentBack="0" componentLabelColour="0xff000000"
               componentLabelFont="&lt;Sans-Serif&gt;;12;0;0;0;0;1;3" componentVisibleName=""
               componentMouseCursor="2" componentGroupName="BACKGROUND" componentGroupped="1"
               componentSnapSize="0" componentIsLocked="0" componentDisabled="0"
               componentRadioGroupId="0" componentRadioGroupNotifyMidi="1" componentVisibility="1"
               componentEffect="0" componentEffectRadius="1" componentEffectColour="0xff000000"
               componentEffectOffsetX="0" componentEffectOffsetY="0" componentExcludedFromLabelDisplay="0"
               componentValueDecimalPlaces="0" componentLuaMouseMoved="-- None"
               componentLuaMouseDown="-- None" componentLuaMouseDrag="-- None"
               componentLuaMouseDoubleClick="-- None" uiLabelBgColour="ffffffff"
               uiLabelTextColour="0xff000000" uiLabelOutline="1" uiLabelOutlineColour="ff000000"
               uiLabelJustification="centred" uiLabelFitFont="0" uiLabelFont="&lt;Sans-Serif&gt;;14;0;0;0;0;1;3"
               uiLabelText="0.0 Cents" uiLabelDisplaysAllValues="0" uiLabelDisplayFormat="%n(%N) = %v(%h)"
               uiLabelInputHighlightTextColour="0xffffffff" uiLabelInputHighlightColour="0xff0000ff"
               uiLabelEditOnSingleClick="0" uiLabelEditOnDoubleClick="0" uiLabelEditFocusDiscardsChanges="1"
               uiLabelInputAllowedChars="" uiLabelInputMaxLength="1024" uiLabelChangedCbk="-- None"
               componentLayerUid="e95e3a2d04000000502975b4fe7f0000" componentRectangle="40 120 109 32"
               uiType="uiLabel"/>
  </modulator>
  <modulator modulatorVstExported="1" modulatorMax="12" vstIndex="2" modulatorIsStatic="0"
             modulatorGlobalVariable="-1" modulatorMuteOnStart="0" modulatorMute="0"
             modulatorExcludeFromSnapshot="0" modulatorValueExpression="modulatorValue"
             modulatorValueExpressionReverse="midiValue" modulatorControllerExpression="value"
             luaModulatorGetValueForMIDI="-- None" luaModulatorGetValueFromMIDI="-- None"
             modulatorLinkedToPanelProperty="-- None" modulatorLinkedToModulatorProperty="-- None"
             modulatorLinkedToModulator="-- None" modulatorLinkedToModulatorSource="1"
             modulatorLinkedToComponent="Modulator" modulatorBaseValue="0"
             modulatorCustomIndex="0" modulatorCustomName="" modulatorCustomIndexGroup="0"
             modulatorCustomNameGroup="" modulatorVstNameFormat="%n" luaModulatorValueChange="mastertranspose"
             name="Transpose" modulatorMin="-12" modulatorValue="0">
    <midi midiMessageType="9" midiMessageChannelOverride="0" midiMessageChannel="1"
          midiMessageCtrlrNumber="1" midiMessageCtrlrValue="0" midiMessageMultiList=""
          midiMessageSysExFormula=""/>
    <component componentLabelPosition="top" componentLabelJustification="centred"
               componentLabelHeight="32" componentLabelWidth="0" componentLabelVisible="1"
               componentLabelAlwaysOnTop="1" componentSentBack="0" componentLabelColour="ff000000"
               componentLabelFont="&lt;Sans-Serif&gt;;12;1;0;0;0;1;3" componentVisibleName="Master&#10;Transpose"
               componentMouseCursor="2" componentGroupName="BACKGROUND" componentGroupped="1"
               componentSnapSize="0" componentIsLocked="0" componentDisabled="0"
               componentRadioGroupId="0" componentRadioGroupNotifyMidi="1" componentVisibility="1"
               componentEffect="0" componentEffectRadius="1" componentEffectColour="0xff000000"
               componentEffectOffsetX="0" componentEffectOffsetY="0" componentExcludedFromLabelDisplay="0"
               componentValueDecimalPlaces="0" componentLuaMouseMoved="-- None"
               componentLuaMouseDown="-- None" componentLuaMouseDrag="-- None"
               componentLuaMouseDoubleClick="-- None" uiSliderStyle="RotaryVerticalDrag"
               uiSliderMin="-12" uiSliderMax="12" uiSliderInterval="1" uiSliderDoubleClickEnabled="1"
               uiSliderDoubleClickValue="0" uiSliderValuePosition="4" uiSliderValueHeight="12"
               uiSliderValueWidth="64" uiSliderTrackCornerSize="5" uiSliderThumbCornerSize="3"
               uiSliderThumbWidth="0" uiSliderThumbHeight="0" uiSliderThumbFlatOnLeft="0"
               uiSliderThumbFlatOnRight="0" uiSliderThumbFlatOnTop="0" uiSliderThumbFlatOnBottom="0"
               uiSliderValueTextColour="0xff000000" uiSliderValueBgColour="0xffffffff"
               uiSliderRotaryOutlineColour="ff000000" uiSliderRotaryFillColour="ff000000"
               uiSliderThumbColour="0xffff0000" uiSliderValueHighlightColour="0xff0000ff"
               uiSliderValueOutlineColour="0xffffffff" uiSliderTrackColour="0xff0f0f0f"
               uiSliderIncDecButtonColour="0xff0000ff" uiSliderIncDecTextColour="0xffffffff"
               uiSliderValueFont="&lt;Sans-Serif&gt;;12;0;0;0;0;1;3" uiSliderValueTextJustification="centred"
               uiSliderVelocitySensitivity="1" uiSliderVelocityThreshold="1"
               uiSliderVelocityOffset="0" uiSliderVelocityMode="0" uiSliderVelocityModeKeyTrigger="1"
               uiSliderSpringMode="0" uiSliderSpringValue="0" uiSliderMouseWheelInterval="1"
               uiSliderPopupBubble="0" uiType="uiSlider" componentRectangle="200 72 75 87"
               componentLayerUid="e95e3a2d04000000502975b4fe7f0000"/>
  </modulator>
  <modulator modulatorCustomIndex="0" modulatorCustomIndexGroup="0" modulatorIsStatic="1"
             name="BACKGROUND" modulatorVstExported="0" modulatorValue="0">
    <component componentLabelPosition="top" componentLabelJustification="centred"
               componentLabelHeight="14" componentLabelWidth="0" componentLabelVisible="0"
               componentLabelAlwaysOnTop="0" componentSentBack="0" componentLabelColour="0xff000000"
               componentLabelFont="&lt;Sans-Serif&gt;;12;0;0;0;0;1;3" componentVisibleName=""
               componentMouseCursor="2" componentGroupName="" componentGroupped="0"
               componentSnapSize="0" componentIsLocked="0" componentDisabled="0"
               componentRadioGroupId="0" componentRadioGroupNotifyMidi="1" componentVisibility="1"
               componentEffect="0" componentEffectRadius="1" componentEffectColour="0xff000000"
               componentEffectOffsetX="0" componentEffectOffsetY="0" componentExcludedFromLabelDisplay="0"
               componentValueDecimalPlaces="0" componentLuaMouseMoved="-- None"
               componentLuaMouseDown="-- None" componentLuaMouseDrag="-- None"
               componentLuaMouseDoubleClick="-- None" uiGroupText="" uiGroupTextColour="0xff000000"
               uiGroupOutlineColour1="0xffa3a3a3" uiGroupOutlineColour2="0xffffffff"
               uiGroupBackgroundColour1="ffe6e6e6" uiGroupBackgroundColour2="ffe6e6e6"
               uiGroupOutlineGradientType="Vertical" uiGroupBackgroundGradientType="1"
               uiGroupBackgroundImage="" componentRectangle="8 8 313 440" uiGroupBackgroundImageLayout="36"
               uiGroupBackgroundImageAlpha="255" uiGroupTextPlacement="top"
               uiGroupTextFont="&lt;Sans-Serif&gt;;14;0;0;0;0;1;3" uiGroupOutlineThickness="2"
               uiGroupOutlineRoundAngle="8" uiGroupTextMargin="0" uiType="uiGroup"
               componentLayerUid="e95e3a2d04000000502975b4fe7f0000"/>
  </modulator>
  <modulator modulatorVstExported="1" modulatorMax="1023" vstIndex="3" modulatorIsStatic="0"
             modulatorGlobalVariable="-1" modulatorMuteOnStart="0" modulatorMute="0"
             modulatorExcludeFromSnapshot="0" modulatorValueExpression="modulatorValue"
             modulatorValueExpressionReverse="midiValue" modulatorControllerExpression="value"
             luaModulatorGetValueForMIDI="-- None" luaModulatorGetValueFromMIDI="-- None"
             modulatorLinkedToPanelProperty="-- None" modulatorLinkedToModulatorProperty="-- None"
             modulatorLinkedToModulator="-- None" modulatorLinkedToModulatorSource="1"
             modulatorLinkedToComponent="Modulator" modulatorBaseValue="0"
             modulatorCustomIndex="0" modulatorCustomName="" modulatorCustomIndexGroup="0"
             modulatorCustomNameGroup="" modulatorVstNameFormat="%n" luaModulatorValueChange="mastertune2"
             name="mastertune2" modulatorMin="-1024" modulatorValue="0">
    <midi midiMessageType="9" midiMessageChannelOverride="0" midiMessageChannel="1"
          midiMessageCtrlrNumber="1" midiMessageCtrlrValue="0" midiMessageMultiList=""
          midiMessageSysExFormula=""/>
    <component componentLabelPosition="top" componentLabelJustification="centred"
               componentLabelHeight="14" componentLabelWidth="0" componentLabelVisible="0"
               componentLabelAlwaysOnTop="0" componentSentBack="0" componentLabelColour="0xff000000"
               componentLabelFont="&lt;Sans-Serif&gt;;12;0;0;0;0;1;3" componentVisibleName=""
               componentMouseCursor="2" componentGroupName="BACKGROUND" componentGroupped="1"
               componentSnapSize="0" componentIsLocked="0" componentDisabled="0"
               componentRadioGroupId="0" componentRadioGroupNotifyMidi="1" componentVisibility="1"
               componentEffect="0" componentEffectRadius="1" componentEffectColour="0xff000000"
               componentEffectOffsetX="0" componentEffectOffsetY="0" componentExcludedFromLabelDisplay="0"
               componentValueDecimalPlaces="0" componentLuaMouseMoved="-- None"
               componentLuaMouseDown="-- None" componentLuaMouseDrag="-- None"
               componentLuaMouseDoubleClick="-- None" uiSliderStyle="IncDecButtons"
               uiSliderMin="-1024" uiSliderMax="1023" uiSliderInterval="1" uiSliderDoubleClickEnabled="1"
               uiSliderDoubleClickValue="1024" uiSliderValuePosition="4" uiSliderValueHeight="12"
               uiSliderValueWidth="64" uiSliderTrackCornerSize="5" uiSliderThumbCornerSize="3"
               uiSliderThumbWidth="0" uiSliderThumbHeight="0" uiSliderThumbFlatOnLeft="0"
               uiSliderThumbFlatOnRight="0" uiSliderThumbFlatOnTop="0" uiSliderThumbFlatOnBottom="0"
               uiSliderValueTextColour="0xff000000" uiSliderValueBgColour="0xffffffff"
               uiSliderRotaryOutlineColour="0xff0000ff" uiSliderRotaryFillColour="0xff0000ff"
               uiSliderThumbColour="0xffff0000" uiSliderValueHighlightColour="0xff0000ff"
               uiSliderValueOutlineColour="0xffffffff" uiSliderTrackColour="0xff0f0f0f"
               uiSliderIncDecButtonColour="ffe6e6e6" uiSliderIncDecTextColour="ffffffff"
               uiSliderValueFont="&lt;Sans-Serif&gt;;12;0;0;0;0;1;3" uiSliderValueTextJustification="centred"
               uiSliderVelocitySensitivity="1" uiSliderVelocityThreshold="1"
               uiSliderVelocityOffset="0" uiSliderVelocityMode="0" uiSliderVelocityModeKeyTrigger="1"
               uiSliderSpringMode="0" uiSliderSpringValue="0" uiSliderMouseWheelInterval="1"
               uiSliderPopupBubble="0" componentLayerUid="e95e3a2d04000000502975b4fe7f0000"
               componentRectangle="112 176 83 45" uiType="uiSlider" uiSliderIncDecButtonTextColour="ff000000"/>
  </modulator>
  <panelCustomData/>
</panel>
