Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

example code Feature request #92

Closed
elmcapp opened this issue Jun 3, 2022 · 3 comments
Closed

example code Feature request #92

elmcapp opened this issue Jun 3, 2022 · 3 comments

Comments

@elmcapp
Copy link

elmcapp commented Jun 3, 2022

I am using your package MidiKit. I am having a little bit of an issue using the package.

You provided a good example how to use the package but I like to know if you could provide one more example that would show how to receive messages in its simplest form. Currently looks like you are using .eventLogging in the example
I am trying to use the following but get error:
Value of type '(MidiModule) -> () -> MidiModule' has no member 'receivedMIDIEvent'

receiveHandler: .events { [weak self] events in
        // Note: this handler will be called on a background thread
        // so call the next line on main if it may result in UI updates
        DispatchQueue.main.async {
            events.forEach { self?.receivedMIDIEvent($0) }
        }
    }

Can you provide a example where everything is in a swift class and one file. Also can you provide example using the receiveHandler

import MidiKit

class MidiModule: NSObject {
    var midiManager: MIDI.IO.Manager = {
        let newManager = MIDI.IO.Manager(
            clientName: "MIDIEventLogger",
            model: "LoggerApp",
            manufacturer: "Orchetect") { notification, manager in
                print("Core MIDI notification:", notification)
            }
        do {
            logger.debug("Starting MIDI manager")
            try newManager.start()
        } catch {
            logger.default(error)
        }
        
        // uncomment this to test different API versions or limit to MIDI 1.0 protocol
        //newManager.preferredAPI = .legacyCoreMIDI
        
        return newManager
    }()

   // ... Whatever code is needed to receive midi messages that use the receivedHandler
}
@orchetect
Copy link
Owner

orchetect commented Jun 3, 2022

Creating a barebones concrete example project is on the to-do list as time allows. The Getting Started Guide explains the basics fairly well.

receivedMIDIEvent is just a local function to process the incoming MIDI messages, and the receive handler closure is calling it.

Your class is a good start. The manufacturer would be your company name or app name. You also need to set up the MIDI ports. If it's just a single virtual MIDI input to receive events, that is also explained in the guide and could be done before return newManager.

This example wouldn't log every message, just the ones handled as you can see. But it's meant to show how to handle individual event types.

Your class may look something like this then:

class MidiModule: NSObject {
    let midiManager: MIDI.IO.Manager = {
        let newManager = MIDI.IO.Manager(
            clientName: "MIDIEventLogger",
            model: "LoggerApp",
            manufacturer: "elmcapp") { notification, manager in
                print("Core MIDI notification:", notification)
            }
        do {
            logger.debug("Starting MIDI manager")
            try newManager.start()

            logger.debug("Creating virtual input MIDI port")
            let inputTag = "Virtual_MIDI_In"
            try newManager.addInput(
                name: "LoggerApp MIDI In",
                tag: inputTag,
                uniqueID: .userDefaultsManaged(key: inputTag),
                receiveHandler: .events { [weak self] events in
                    // Note: this handler will be called on a background thread
                    // so call the next line on main if it may result in UI updates
                    DispatchQueue.main.async {
                        events.forEach { self?.receivedMIDIEvent($0) }
                    }
                }
            )
        } catch {
            logger.default(error)
        }
        
        return newManager
    }()

    private func receivedMIDIEvent(_ event: MIDI.Event) {
        switch event {
        case .noteOn(let payload):
            print("NoteOn:", payload.note, payload.velocity, payload.channel)
        case .noteOff(let payload):
            print("NoteOff:", payload.note, payload.velocity, payload.channel)
        case .cc(let payload):
            print("CC:", payload.controller, payload.value, payload.channel)
        case .programChange(let payload):
            print("PrgCh:", payload.program, payload.channel)
            
        // etc...

        default:
            break
        }
    }
}

@elmcapp
Copy link
Author

elmcapp commented Jun 3, 2022

Just tried the current code but I get the following error

Value of type '(MidiModule) -> () -> MidiModule' has no member 'receivedMIDIEvent'

To resolve the issue I had to add lazy.

lazy var midiManager: MIDI.IO.Manager = {
  // rest of code
}

@orchetect
Copy link
Owner

Personally I'd rather implement initialization code in the class's init and not in the variable declaration:

public class MidiModule: NSObject {
    let midiManager = MIDI.IO.Manager(
        clientName: "MIDIEventLogger",
        model: "LoggerApp",
        manufacturer: "elmcapp")
    
    public override init() {
        super.init() // must call NSObject init first
        
        do {
            midiManager.notificationHandler = { notification, manager in
                print("Core MIDI notification:", notification)
            }
            
            print("Starting MIDI manager.")
            try midiManager.start()
            
            print("Creating virtual input MIDI port.")
            let inputTag = "Virtual_MIDI_In"
            try midiManager.addInput(
                name: "LoggerApp MIDI In",
                tag: inputTag,
                uniqueID: .userDefaultsManaged(key: inputTag),
                receiveHandler: .events { [weak self] events in
                    // Note: this handler will be called on a background thread
                    // so call the next line on main if it may result in UI updates
                    DispatchQueue.main.async {
                        events.forEach { self?.receivedMIDIEvent($0) }
                    }
                }
            )
        } catch {
            print(error)
        }
    }
    
    private func receivedMIDIEvent(_ event: MIDI.Event) {
        switch event {
        case .noteOn(let payload):
            print("NoteOn:", payload.note, payload.velocity, payload.channel)
        case .noteOff(let payload):
            print("NoteOff:", payload.note, payload.velocity, payload.channel)
        case .cc(let payload):
            print("CC:", payload.controller, payload.value, payload.channel)
        case .programChange(let payload):
            print("PrgCh:", payload.program, payload.channel)
            
            // etc...
            
        default:
            break
        }
    }
}

Repository owner locked and limited conversation to collaborators Jun 3, 2022
@orchetect orchetect converted this issue into discussion #96 Jun 3, 2022

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants