Old 02-26-2023, 10:14 AM   #1
JamesX
Human being with feelings
 
Join Date: Feb 2022
Posts: 90
Default SendMIDIMessageToHardware()

Is there an example for the use of SendMIDIMessageToHardware() (v6.76rc1) available?

Something simple like CC7 on channel 1 set to 127 (B0 07 127) on say, port ID 20.

I assume SendMIDIMessageToHardware() can send sysex messages of any length as well?

This looks very useful for my purposes, but I can't decipher the syntax at this point...

Thanks in advance,

J
JamesX is offline   Reply With Quote
Old 02-26-2023, 12:02 PM   #2
daniellumertz
Human being with feelings
 
daniellumertz's Avatar
 
Join Date: Dec 2017
Location: Brazil
Posts: 2,009
Default

not really an example but this might help you:

here is the docs to reference :
Code:
C: void SendMIDIMessageToHardware(int output, const char* msg_buf, int msg_len)

EEL2: SendMIDIMessageToHardware(int output, "msg_buf", int msg_len)

Lua: reaper.SendMIDIMessageToHardware(integer output, string msg_buf, integer msg_len)

Python: RPR_SendMIDIMessageToHardware(Int output, String msg_buf, Int msg_len)

Sends a MIDI message to output device specified by output. msg_len must be at least 3, and msg_buf should contain the contents of the message. Message is sent in immediate mode.
1 argument you want the device you want to send to, you can check it with retval, nameout = reaper.GetMIDIOutputName( dev, nameout ) and reaper.GetNumMIDIOutputs()


2 you want to put the midi message into a string, each string "letter" is a byte sooo each letter will be a midi byte. Anyway I made a function to pack midi messages to string the name is PackMIDIMessage, you put the midi_type, midi channel, and all the datatypes values afterwards, as many as required.

Code:
---Receives numbers(0-255). or strings. and return them in a string as bytes
---@param ... number
---@return string
function PackMessage(...)
    local msg = ''
    for i, v in ipairs( { ... } ) do
        local new_val
        if type(v) == 'number' then 
            new_val = string.char(v) 
        elseif type(v) == 'string' then -- In case it is a string (useful for midi text where each byte is a character)
            new_val = v
        elseif not v then -- in case some of the messages is nil. No problem! This is useful as PackMIDITable will send .val2 and .text. not all midi have val2 and not all midi have .text
            new_val = ''
        end
        msg = msg..new_val
    end
    return msg
end

---Pack a midi message in a string form. Each character is a midi byte. Can receive as many data bytes needed. Just join midi_type and midi_ch in the status bytes and thow it in PackMessage. 
---@param midi_type number midi message type: Note Off = 8; Note On = 9; Aftertouch = 10; CC = 11; Program Change = 12; Channel Pressure = 13; Pitch Vend = 14; text = 15.
---@param midi_ch number midi ch 1-16 (1 based.)
---@param ... number sequence of data bytes can be number (will be converted to string(a character with the equivalent byte)) or can be a string that will be added to the message (useful for midi text where each byte is a character).
function PackMIDIMessage(midi_type,midi_ch,...)
    local midi_ch = midi_ch - 1 -- make it 0 based
    local status_byte = (midi_type<<4)+midi_ch -- where is your bitwise operation god now?
    return PackMessage(status_byte,...)
end
3 will probably have some changes, as justin commented
daniellumertz is online now   Reply With Quote
Old 02-26-2023, 02:40 PM   #3
JamesX
Human being with feelings
 
Join Date: Feb 2022
Posts: 90
Default

daniellumertz,

I'm familiar with reaper.StuffMIDIMessage(integer mode, integer msg1, integer msg2, integer msg3) and I think this is what your script use is referencing.

But reaper.SendMIDIMessageToHardware has a different format (it's new!!!) and I'm just not getting it. I've tried several approaches and basically I'm throwing darts in the dark. string msg_buf is the dart board, I can't hit it.

Thanks for your reply,

J
JamesX is offline   Reply With Quote
Old 02-26-2023, 03:39 PM   #4
daniellumertz
Human being with feelings
 
daniellumertz's Avatar
 
Join Date: Dec 2017
Location: Brazil
Posts: 2,009
Default

I was referring to the new API!!!

use my function to create your midi packed string
daniellumertz is online now   Reply With Quote
Old 02-27-2023, 12:33 PM   #5
JamesX
Human being with feelings
 
Join Date: Feb 2022
Posts: 90
Default

daniellumertz,

Looks like the API has changed as of v6.76rc3.

I don't know how to implement your script. Could you show a simple example like CC7 on channel 1 set to 127 (B0 07 127)?

I'm receiving midi messages being sent to hardware. I've been randomly inserting values into string msg checking for some kind of correlation, and I'm getting nowhere.

A step by step example would go a long towards my learning this function, as I'm not a proficient coder.

Thanks,

J
JamesX is offline   Reply With Quote
Old 02-27-2023, 01:33 PM   #6
daniellumertz
Human being with feelings
 
daniellumertz's Avatar
 
Join Date: Dec 2017
Location: Brazil
Posts: 2,009
Default

Quote:
Originally Posted by JamesX View Post
daniellumertz,

Looks like the API has changed as of v6.76rc3.

I don't know how to implement your script. Could you show a simple example like CC7 on channel 1 set to 127 (B0 07 127)?

I'm receiving midi messages being sent to hardware. I've been randomly inserting values into string msg checking for some kind of correlation, and I'm getting nowhere.

A step by step example would go a long towards my learning this function, as I'm not a proficient coder.

Thanks,

J
Code:
---Receives numbers(0-255). or strings. and return them in a string as bytes
---@param ... number
---@return string
function PackMessage(...)
    local msg = ''
    for i, v in ipairs( { ... } ) do
        local new_val
        if type(v) == 'number' then 
            new_val = string.char(v) 
        elseif type(v) == 'string' then -- In case it is a string (useful for midi text where each byte is a character)
            new_val = v
        elseif not v then -- in case some of the messages is nil. No problem! This is useful as PackMIDITable will send .val2 and .text. not all midi have val2 and not all midi have .text
            new_val = ''
        end
        msg = msg..new_val
    end
    return msg
end

---Pack a midi message in a string form. Each character is a midi byte. Can receive as many data bytes needed. Just join midi_type and midi_ch in the status bytes and thow it in PackMessage. 
---@param midi_type number midi message type: Note Off = 8; Note On = 9; Aftertouch = 10; CC = 11; Program Change = 12; Channel Pressure = 13; Pitch Vend = 14; text = 15.
---@param midi_ch number midi ch 1-16 (1 based.)
---@param ... number sequence of data bytes can be number (will be converted to string(a character with the equivalent byte)) or can be a string that will be added to the message (useful for midi text where each byte is a character).
function PackMIDIMessage(midi_type,midi_ch,...)
    local midi_ch = midi_ch - 1 -- make it 0 based
    local status_byte = (midi_type<<4)+midi_ch -- where is your bitwise operation god now?
    return PackMessage(status_byte,...)
end

--  CC7 on channel 1 set to 127
local midi_msg = PackMIDIMessage(11,1,7,127) -- feed that to the SendMIDIMessageToHardware()
just a short explanation on the arguments I used :
11 = say this is a CC message
1 = channel
7 = CC
127 = CC value

Last edited by daniellumertz; 02-27-2023 at 01:39 PM.
daniellumertz is online now   Reply With Quote
Old 02-27-2023, 01:58 PM   #7
JamesX
Human being with feelings
 
Join Date: Feb 2022
Posts: 90
Default

daniellumertz,

Yes! This works. Of course it does.

Thank you so much for your time and effort,

J
JamesX is offline   Reply With Quote
Old 03-09-2024, 02:28 PM   #8
Rockum
Human being with feelings
 
Join Date: Apr 2009
Location: Nashville
Posts: 187
Default

How would I send a raw sysex message?

Here's an example message I know will work for testing:

"F0 00 20 29 03 03 12 00 02 00 02 02 04 01 09 01 04 42 75 74 74 6F 6E
20 32 00 01 09 03 04 20 20 20 31 00 01 12 01 04 42 75 74 74 6F 6E 20
33 00 01 12 03 04 20 20 20 4F 4E 00 F7"


EDIT - Never mind I got it... MPL had provided in another thread.



SysEx_msg =""
SysEx_msg_bin = '' for hex in SysEx_msg:gmatch('[A-F,0-9]+') do SysEx_msg_bin = SysEx_msg_bin..string.char(tonumber(hex, 16)) end
reaper.SendMIDIMessageToHardware(port_number, SysEx_msg_bin)

Last edited by Rockum; 03-09-2024 at 03:11 PM. Reason: Solved
Rockum is online now   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 02:03 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.