Home Forums General Programming how to output a table into console or uiLabel

This topic contains 21 replies, has 4 voices, and was last updated by  human fly 1 month, 4 weeks ago.

Viewing 20 posts - 1 through 20 (of 22 total)
  • Author
    Posts
  • #72656

    EnzoF04
    Participant

    I want to monitor the sysex i construct. I’m changing a table’s contents based on a chosen item in a combo. I store the value from the combo into a variable and i make a table with 8 bytes. I want to view this table but I don’t know how to print it in console.
    This is the function i use when the combo is changed:

    currentSmpNmChanged = function(--[[ CtrlrModulator --]] mod, --[[ number --]] value, --[[ number --]] source)
    	sNmb = modCbSmpNum:getModulatorValue()
    	midiMsg = CtrlrMidiMessage({0xf0, 0x47, 0x00, 0x04, 0x41, sNmb, 0x00, 0xf7})
    	console(string.format(midiMsg))
    	opSmpNum:getComponent():setPropertyString ("uiLabelText", tostring(sNmb))
    	opSYXMsg:getComponent():setPropertyString ("uiLabelText", string.format(midiMsg))
    end

    The last line of code gets me an error. What am i doing wrong?

    • This topic was modified 2 months ago by  EnzoF04.
    #72659

    human fly
    Participant

    if you make a button to trigger your method
    eg: mousedown or onValueChange

    you open the Lua Console before you run your function,
    and whatever the output of console() is appears there.

    it also appears in the window beneath the editor, but
    i never quite know when it’s going to do it – i was
    thinking about just this, writing output to a label,
    to check the results from functions, before i moved on
    to other stuff – concluded that i could write a fakeConsole
    function, that sends the output via
    setPropertyString(“UILabelText”,(your result))

    i’m using this at the moment for muck-around things happening
    in the panel, but haven’t yet tried it as a faux console
    readout device.

    this works:
    getComponent():setProperty("uiLabelText", "some text", false)
    (maybe could be “uiLabelText”,””..(variable))
    and this also works:
    panel:getComponent("init_result"):setPropertyString("uiLabelText",""..(ret))
    (ret here was ‘return’ from a menu selection ie: can be whatever variable
    you want etc.)
    *as far as i could figure out* 😉

    keen to hear how you get on with displaying your console results
    on the workspace (that’s it, right?)

    #72660

    human fly
    Participant

    except i’m not sure offhand how one would do that.
    if console() is a function that sends it’s result to the Console,
    then fauxConsole(), what would the variables be, and how would you
    invoke it?/include it in a method to fire off the output to the
    UILabel?

    #72663

    EnzoF04
    Participant

    Thanks for the replies, Human! Well I need to know how i convert the contents of the user data / table variable to a form which is to be displayed in the uiLabel Text. So my question mainly was about how to convert the data in the (table) variable. I’ve tried string.format or tostring but this didn’t work.
    The error i get with the last sentence of my code is attached.
    opSYXMsg:getComponent():setPropertyString ("uiLabelText", string.format(midiMsg))

    Attachments:
    You must be logged in to view attached files.
    #72666

    human fly
    Participant

    bear in mind that i’m just finding this stuff out right now too..

    yeah, so that’s because midiMsg isn’t a string – ‘string expected’.
    i guess you have to make table (or memory block? see that topic
    re convert decimal to hex, what Possemo and goodweather wrote)

    look at the method called midiMessageReceived.
    there’s a bit that goes PatchToneSyx = midiMessage:getLuaData()
    -it gets quite hairy here tbh haha.

    somehow you have to get your Lua data into a string, and then
    you can send it over to your label.

    oh: sorry, all change: have you tried
    setPropertyString ("uiLabelText",""..(midiMsg))

    #72667
    Possemo
    Possemo
    Participant

    As far as I know “user data” isn’t a number nor a string. Lua can’t do anything with user data.

    CtrlrMidiMessage({0xf0, 0x47, 0x00, 0x04, 0x41, sNmb, 0x00, 0xf7})

    This seems to be an example of user data. CtrlrMidiMessage is a command and can probably not be displayed. As you see “console(string.format(midiMsg))” doesn’t work either. It won’t throw an error but it won’t display anything in the console.

    So when you want to display the hex numbers I would do it like this:

    currentSmpNmChanged = function(--[[ CtrlrModulator --]] mod, --[[ number --]] value, --[[ number --]] source)
    	sNmb = panel:getModulatorByName("modulator-2"):getModulatorValue()
    	sNmbHex = string.format("%.2x", sNmb)
    	message = "f0 47 00 04 41 "..sNmbHex.." 00 f7"
    	midiMsg = CtrlrMidiMessage(message)
    
    	console(string.format(message))
    	opSmpNum:getComponent():setPropertyString ("uiLabelText", tostring(sNmb))
    	opSYXMsg:getComponent():setPropertyString ("uiLabelText", message)
    end

    As HumanFly’s example showed – yes you can exchange
    :setPropertyString (“uiLabelText”, message)
    with
    :setProperty (“uiLabelText”, message, false)

    setProperty will work with a string as well as a number. So you don’t have to convert a number to a string.

    SetPropertyString expects a string
    SetPropertyInt expects an integer number

    #72668

    EnzoF04
    Participant

    Thanks guys! Glad that I’m doing nothing wrong than putting undisplayable items. I’ll find my way round to show it.

    Is there a place where I can read about the functions / commands like CtrlrMidiMessage and what it does and how it does?

    #72673
    goodweather
    goodweather
    Participant

    Hi!
    Ctrlr has its own functions and is also using the Juce library.
    All Ctrlr info (you need to learn reading the definitions of the functions (not the code itself) is at: https://sourceforge.net/p/ctrlrv4/code/HEAD/tree/nightly/Source/
    For things coming from Juce, they are in Lua/JuceCLasses folder; for midi message in Midi folder…
    Juce API doc: https://www.juce.com/doc/classes
    FOr example, for memoryblock; click on M then scroll a bit.
    You will find all functions of the memoryblock object and their syntax. Usually, all are ported into Ctrlr (you can check by looking at file LMemoryBlock.h in Lua/JuceCLasses folder).

    You use CtrlrMidiMessage with a string or better a MemoryBlock. The advantage with memory blocks is that you handle directly the values as integer or hexa.
    To remind you:
    – 63 is a integer
    – “3F” is a string representing the hexa value of the integer
    – 0x3F is the hexa value
    In the code above presented by Possemo, you handle strings.

    In the code below, I’m handling only actual values:

    -- Send device inquiry message
    msg = CtrlrMidiMessage({0xF0, 0x7E, 0x7F, 0x06, 0x01, 0xF7})
    panel:sendMidiMessageNow(msg)

    Here I’m using a string

    msg = string.format("F0 01 2C 05 %.2x %.2x F7", sBank, sProgram)
    panel:sendMidiMessageNow(CtrlrMidiMessage(msg))

    Here I’m using a memory block that I assemble from different parts `(LoadedProgramData is my unpacked sysex dump of a DSI program)
    mbTemp= MemoryBlock ({0xF0, 0x01, 0x2C, 0x03})
    mbTemp:append(PackDsiData(LoadedProgramData))
    mbTemp:append(MemoryBlock ({0xF7}))
    panel:sendMidiMessageNow(CtrlrMidiMessage(mbTemp))`

    You view the content of a memory block with
    console(LoadedProgramData:toHexString(1))
    It gives you:
    24 24 24 24 34 30 33 31 7f 7f 7f 7f 02 02 00 02…

    When you recieve a Midi message, you get a memory block that you can further handle:
    MidiMessageReceived = function(MidiMessage)
    MidiMessage:getData() is a memory block
    console(MidiMessage:getData():toHexString(1)) shows you the message
    you can check a particular byte with
    if MidiMessage:getData():getByte(6) == 0x2C then (for example)
    You can extract a complete part (from byte 4 take 1171 bytes) with
    MidiMessage:getData():getRange(4, 1171)

    Good reading!

    #72677
    Possemo
    Possemo
    Participant

    yes that’s it. Just want to say that Roman ported the open source project to Github some time ago. I would look there:
    https://github.com/RomanKubiak/ctrlr/tree/master/Source/

    It is somewhat “less abandoned” 🙂 Unfortunately there is no comment / explanation. As a beginner you will have to guess a lot…

    • This reply was modified 2 months ago by Possemo Possemo.
    #72679
    goodweather
    goodweather
    Participant

    Thx Possemo, I missed that one…

    #72680

    EnzoF04
    Participant

    OK OK, dance of happiness! It works! I’ve got code working and i get response from the sampler. This is really great!!
    Nice explanations guys! Especially the Goodweather explanation on constructing sysex as strings with spaces dividing the bytes. And the %.2x after the string for the variables is very helpful! the working code for the onChange of the uiCombo is:

    currentSmpNmChanged = function(--[[ CtrlrModulator --]] mod, --[[ number --]] value, --[[ number --]] source)
    	sNmb = modCbSmpNum:getModulatorValue()
    	midiMsg = string.format("F0 47 00 04 41 %.2x 00 F7", sNmb)
    	opSmpNum:getComponent():setPropertyString ("uiLabelText", tostring(sNmb))
    	opSYXMsg:getComponent():setPropertyString ("uiLabelText", string.format(midiMsg))
    end

    I’m very visually orientated and i NEED to get feedback on a uiLabel so i can get the variable further. I’ll now go on with the dump of the data received into a uiLabel. That worked in a previous version. Many thanks, guys!

    #72681

    human fly
    Participant

    ‘very visually oriented’ – yes! that’s the phrase i was looking for..
    good news ! i’m ‘revising’ now, with yesterday’s tutorial.
    i think goodweather showed us the way..

    #72683
    goodweather
    goodweather
    Participant

    Glad I could help.

    Please note that the string based method above is fine for short sysex but will become more difficult to manage with long ones as full banks or patches.
    Even if the string based method can work with any length I strongly recommend you to look at MemoryBlocks. For example, swapping patches between banks is done in just a few lines of code.

    Visual feedback is indeed very important BUT, regarding sysex, only during development.
    And, when developing, usualy one uses a debugger.
    There is one in Ctrlr but I never succeeded using it so, for me, the debugger is the console even if a uiLabel works as well…
    You find the console under Panel – Lua console

    For the console:
    – you type at the bottom, you get results on top
    – you can execute line of codes as myVariable = 1 meaning you don’t need to run your panel to test a code; you can make shortcuts
    – to display things, you use the console() statement. Just remember that it only accepts a string
    – some statements:

    iProgram = 24
    console(tostring(iProgram))
    24
    iProgram = 0x3F
    console(tostring(iProgram))
    63
    sProgram = "My patch"
    console(sProgram)
    My patch
    -- concatenation
    console(tostring(iProgram).." - "..sProgram)
    63 - My patch
    -- display of a MemoryBlock (previously filled in with data)
    console(myMemoryBlock:toHexString(1))
    24 24 24 24 34 30 33 31 7f 7f 7f 7f 02 02 00 02 00
    #72701

    EnzoF04
    Participant

    In a previous try I got an output of a received midi message to an uiLabel working. I lost that panel and I’m searching for the way I did this. (Bottom right uiLabel with visible name “output” in screen dump).
    sd
    I do this

    midiMessageReceived = function(MidiMessage)
    	s = MidiMessage:getSize()
    	midiFromS700Size = MidiMessage:getSize()
    
    	midiFromS700 = MidiMessage:getData()
    	midiFromS700String = string.format(midiFromS700)
    	console (tostring(midiFromS700Size))
    	console (midiFromS700:toString())
    	opSYXRcv:getComponent():setPropertyString ("uiLabelText", string.format(midiFromS700))
    end

    It’s so frustrating to not be able to read some clear documentation on formatting of variables and formatting them to suit the output I’m putting them to. All in above code are attempts to get it working.

    Attachments:
    You must be logged in to view attached files.
    #72703
    goodweather
    goodweather
    Participant

    Well… the answer is in what I wrote above 😉

    – MidiMessage:getData() is a MemoryBlock
    – MidiMessage:getData():toHexString(1) gives you the translation in hexa as a string
    – console() must have a string as argument

    So… just do:

    midiMessageReceived = function(MidiMessage)
    
    	console (tostring(MidiMessage:getSize()))
    	sMsg = MidiMessage:getSize():toHexString(1)
    	console (sMsg)
    	opSYXRcv:getComponent():setPropertyString ("uiLabelText", sMsg)
    
    end

    Provided you declared opSYXRcv before as opSYXRcv = panel:getModulatorByName(“something”)
    I removed your variable assignments as you seem not to do anything with them but you can also keep them for testing size or…
    Remember than writing sMsg doesn’t make the variable a string by default, it is the assignment to a string that makes the variable a string.

    #72704

    EnzoF04
    Participant

    Thanks!
    OK, sorry for being too quick with my question.
    But it’s quite inefficiënt to format the variable before using it? This way one needs to have multiple variables for one value. In stead of converting it at “use time” to the desired format?

    Or am I wrong with my thoughts?
    Thanks Goodweather!

    #72705
    goodweather
    goodweather
    Participant

    I don’t fully understand your question, sorry…
    The principle with variables is that you use them (= you assign them) if you will use the calculation / conversion / … more than once later on.
    In your code above you don’t do anything with size and you call 2 times getSize()…
    So, as you are using it only once, the most efficient is just to use it when you display it in the console.
    OK?

    #72706

    EnzoF04
    Participant

    I understand. It was for testing reasons why I pushed some (the size of the sysex received) into a variable.
    What I’m trying to point out:
    When I get a value from the sysex, lets say the sample number the device is sending to the panel, in this case it’s hex 0x00 (sample 1), and I store it in a variable as such, and i want to use it as a string for visual reference on what sample I’m working, that I need to make a new variable with the contents / formatting of string. So if I use this variable on 3 different locations in my panel I need to declare 3 different variables. It would be much more easy to convert the value to the desired data type ‘on use’ time?

    #72708
    goodweather
    goodweather
    Participant

    OK. No you don’t need to assign the variable three times.
    In Lua, variables are global by default.
    If you want to make them local, you put the keyword local in front of the assignment.

    This doesn’t mean that you don’t need to do some further conversion depending on context.
    For your example of sample number, if it is a number, keep it as number!
    ANd of course, if you want to display it in the console or in a label then you convert it ad hoc without declaring a new variable.

    -- Get the sample number from a midi message
    iSampleNo = MidiMessage:getData():getByte(5)
    -- Display it in console
    console(tostring(iSampleNo))
    -- Display it in a uiLabel
    opSmpNum:getComponent():setPropertyString ("uiLabelText", tostring(iSampleNo))

    Of course, if you don’t want to convert then you can also assign it directly to a variable and use that variable at different places
    sSampleNo = tostring(iSampleNo)

    I prefer to keep things as they are because I always remember what they are…
    A sample number is an integer
    A sample name is a string

    and I convert ad hoc when needed.

    #72710

    EnzoF04
    Participant

    OK, that’s clear! Thanks for the nice explanation! I’m really getting forward! And i’m building it to my satisfactory too. BUT.. 🙂 (sorry folks…)

    What’s the difference between
    MidiMessage.getData()
    and
    MidiMessage.getLuaData()
    or something like this.

    I’m getting into the total blocks that a sample consists of so I can start putting these blocks into memory blocks and then put them into a file… But that’s quite far away from here… still.
    I really appreciate all your help Goodweather and others!!

    I’m doing all my calculations in the midiReceived method. I can think of a better way to calculate different parameters of my sample. But how…

    • This reply was modified 2 months ago by  EnzoF04.
    Attachments:
    You must be logged in to view attached files.
Viewing 20 posts - 1 through 20 (of 22 total)

You must be logged in to reply to this topic.

Comments are closed.