Closing Open Midi Devices

So I’m new to Renoise scripting and hopefully this isn’t a dumb question.

I have a MidiInput class which creates a midi device (pulled mostly from the snippets).

class 'MidiInput'
  function MidiInput:__init(device_name)
    self.device_name = device_name
  end
  
  function MidiInput:startInput()
    self.device = renoise.Midi.create_input_device(
      self.device_name, 
      { self, MidiInput.midi_callback }, 
      { MidiInput.sysex_callback, self }
    )
  end
  
  function MidiInput:stopInput()
    if self.device then 
      self.device:close()
      self.device = nil
    end
  end
  
  function MidiInput:midi_callback(message)
    --print(('%s: MidiInput MIDI %X %X %X'):format(
      --self.device_name, message[1], message[2], message[3]))
    onMidi(message[1], message[2], message[3])
  end

  function MidiInput:sysex_callback(message)
    --print(('%s: MidiInput SYSEX with %d bytes'):format(
      --self.device_name, #message))
  end

  local inputs = renoise.Midi.available_input_devices()

  if not table.is_empty(inputs) then
    local device_name = inputs[1]
    midi_input = MidiInput(device_name)
  end

I then have an init() function that I call at the beginning of my code. The problem with this is that midi_input.is_open is “nil” until “startInput” is called.

function init()
  if midi_input.is_open then
    midi_input:stopInput()
  end
  if not midi_input.is_open then
    midi_input:startInput()
  end
  createOscConnection()
end

If I run this code multiple times, I end up getting multiple midi inputs that are open and cannot be closed. Is there a way for me to see which devices are currently open? Or maybe a better way for me to initialize my code?

From what you have shown dplduffy, what initially came to my mind is:

class 'MidiInput'
  function MidiInput:__init(device_name)
    self.device_name = device_name
  end
  
  function MidiInput:startInput()
    self.device = renoise.Midi.create_input_device(
      self.device_name, 
      { self, MidiInput.midi_callback }, 
      { MidiInput.sysex_callback, self }
    )
  end
  
  function MidiInput:stopInput()
    if self.device then 
      self.device:close()
      self.device = nil
    end
  end
  
  function MidiInput:getOpen()
    return self.device.is_open
  end

  function MidiInput:midi_callback(message)
    --print(('%s: MidiInput MIDI %X %X %X'):format(
      --self.device_name, message[1], message[2], message[3]))
    onMidi(message[1], message[2], message[3])
  end

  function MidiInput:sysex_callback(message)
    --print(('%s: MidiInput SYSEX with %d bytes'):format(
      --self.device_name, #message))
  end

local midi_input

function init()

  local inputs = renoise.Midi.available_input_devices()
  --Ask user what midi device etc...
  
  midi_input = MidiInput(inputs[1]) -- Just for example I force the first device here
  
  midi_input:startInput() -- Create the input device  
  
  createOscConnection()

end

function exit()

  if midi_input:getOpen() then
    midi_input:stopInput()
  end

end

A function ‘init’ that gets the available midi inputs from Renoise, then creates the ‘object’ of type MidiInput initialised to that device (in my example above I just pass the first string), get Renoise to create the midi device with ‘startInput’ function. Then I would’ve thought you would have a cleanup function (I’ve called it ‘exit’ above) for when the user closes your tool. I’ve added a ‘getter method/function’ called ‘getOpen’ to query if the device is really open or not in the class.

I’m not an expert in lua object orientated coding (never done it before), so you’ll probably have to take this post with a grain of salt. You could be looking for something more complicated however :slight_smile:

thank you! I think the important part in your example is the exit function. After a little thought I realized there is no way to see what midi devices are “open” on startup because the “open” quality of a midi device isn’t available until I create the device. Thus the only time I can close an open midi device is while I am still in the same instance of code. If I run the init() function 2 times in a row, the first midi_device gets replaced with the second. There is then no way to close the first midi_device.

Okay dplduffy, no problem. So long as you’ve managed to work something out from my quick guess work :slight_smile: