Eine Elixier -Wrapper für die RTMIDI -Bibliothek. Inspiriert teilweise von Python-rtmidi.
WARNUNG: Diese Bibliothek gilt als experimentell/vor Alpha, bis einige der folgenden Probleme angegangen werden.
Überprüfen Sie die Registerkarte "Probleme", wenn Sie helfen möchten.
Diese Bibliothek funktioniert nach wie vor, aber ich bin kein C ++-Programmierer. Alle Beiträge sind willkommen, aber die Hilfe in diesen spezifischen Bereichen würde einen langen Weg gehen:
C ++
src/ex_rtmidi_{output,input}.cpp könnte OOP und Templating viel besser verwenden, um die Code -Duplikation zu reduziereninput_callback und attach_listener in src/ex_rtmidi_input.cpp benötigen einen guten Look. Auch hier ist ein Refaktor vorher vorzuziehendetach_listener sollte keinen Fehler drucken, wenn er ohne Listener aufgerufen wirdElixier
init -Methode für Eingänge/Ausgänge dauert länger als für einen NIF empfohlen. Siehe lib/ex_rtmidi/{output,input}.ex KommentareopenVirtualPort von RTMIDIMix.Tasks.Compile.Rtmidi OUT mix.exs . Siehe Kommentar in mix.exsAllgemein
C ++ ist eine OO -Sprache, Elixir nicht. Ich war zerrissen, ob ich Dinge funktionaler oder mehr im Einklang mit OO -Konventionen ausdrücken sollte. Am Ende wurde ein funktionalerer Ansatz gewählt.
Um eine RTMIDI -Instanz zu erstellen, wird eine init -Methode mit einer Instanzkennung aufgerufen. In C ++ wird die Instanz als Wert in einer Karte gespeichert, in der die Kennung der Schlüssel ist. Zukünftige Aufrufe bei RTMIDI -Instanzmethoden erfordern, dass die Kennung übergeben wird, um zu wissen, welche Instanz zum Ziel ist.
NIFs sind in erster Linie ein Erlang -Konstrukt, daher werden Sie sehen, dass der Elixier -Wrapper viel zu und von Charlists durchführt. Dies liegt daran, dass Saiten in Erlang Charlists in Elixir sind, daher nehmen NIF -String -Methoden Charlists anstelle von String.t() .
Hörer an Eingangsports, die als PID an C ++ übergeben wurden. Nach Erhalt einer Nachricht übernimmt die NIF die Nachricht asynchronisiert an die angegebene PID.
Bis einige der dringenderen C ++ - Probleme gelöst werden, möchte ich diese Bibliothek nicht für die öffentliche Verwendung bewerben. Bis dahin müssen Sie es von Github bekommen:
def deps do
[
{ :ex_rtmidi , git: "https://github.com/kieraneglin/ex_rtmidi" }
]
end Derzeit verfolgt diese Bibliothek einen bloßen Ansatz für die Handhabung von Nachrichten, als Sie vielleicht erwarten. Sie können einen Wert von einem kleinen Wrapper erhalten, das auf Ihre Anwendungsfälle zugeschnitten ist und analysiert wird.
Ich habe einige grundlegende Anwendungsfälle beschrieben, aber Sie sollten lib/ex_rtmidi/{output,input}.ex für eingehende Dokumentation sehen.
alias ExRtmidi.Output
{ :ok , instance } = Output . init ( :my_instance_name ) # Instance name can be whatever you want - it's unrelated to available MIDI devices
Output . get_port_count ( instance )
# iex> {:ok, 2}
Output . get_ports ( instance )
# iex> {:ok, ["IAC Midi", "Dummy MIDI"]}
Output . open_port ( instance , 0 ) # Or `Output.open_port(instance, "IAC Midi")`
# iex> :ok
Output . send_message ( instance , [ 0x90 , 60 , 100 ] )
# iex> :ok
Output . close_port ( instance )
# iex> :okEs gibt einen Wrapper für MIDI -Nachrichten, der die Erfahrung des Erstellens von Nachrichten verbessert. Dies gilt hauptsächlich für die Ausgabe und wurde nicht so portiert, um eingehende Nachrichten zu dekonstruieren (siehe Abschnitt "Hilfe benötigt").
Eine vollständige Liste von Nachrichten finden Sie unter lib/ex_rtmidi/message/spec.ex .
alias ExRtmidi.Output
alias ExRtmidi.Message
# Assume `init` has been run and a port has been opened as in the instance above
message = Message . compose ( :note_on , channel: 0 , note: 60 , velocity: 100 )
Output . send_message ( instance , message ) # In midi_input_server.ex
defmodule MidiInputServer do
use GenServer
def init ( state \ [ ] ) do
{ :ok , state }
end
def handle_info ( { :midi_input , midi_message } , state ) do
IO . inspect ( midi_message )
{ :noreply , state }
end
end
# In another file
alias ExRtmidi.Input
# Much of setup including init, listing ports, and opening a port is the same as in the Output example above.
# Setup will be omitted for brevity. Assume we have an instance at our disposal.
{ :ok , midi_listener_pid } = GenServer . start_link ( MidiInputServer , [ ] )
# You should attach the listener before opening the port to ensure no messages get missed
Input . attach_listener ( instance , midi_listener_pid )
# iex> :ok
Input . open_port ( instance )
# iex> :ok
# Messages will be handled from this point on
# When you're done, be sure to detatch the listener before closing the port
Input . detatch_listener ( instance )
# iex> :ok
Input . close_port ( instance )
# iex> :ok Copyright 2021
Die Erlaubnis wird hiermit einer Person, die eine Kopie dieser Software und zugehörigen Dokumentationsdateien (der "Software") erhält, kostenlos erteilt, um die Software ohne Einschränkung zu behandeln, einschließlich ohne Einschränkung der Rechte, zu verwenden, zu kopieren, zu modifizieren, zusammenzufassen, zu veröffentlichen, zu veröffentlichen, zu verteilen, zu verteilt, und/oder Kopien der Software zu ermöglichen, um Personen zu beanstanden, an denen die Software zugänglich ist, um die folgenden Bedingungen zu beantragen.
Die oben genannte Copyright -Mitteilung und diese Erlaubnisbekanntmachung müssen in alle Kopien oder wesentlichen Teile der Software enthalten sein.
Die Software wird "wie es ist" ohne Garantie jeglicher Art, ausdrücklich oder stillschweigend bereitgestellt, einschließlich, aber nicht beschränkt auf die Gewährleistung der Handelsfähigkeit, die Eignung für einen bestimmten Zweck und die Nichtverletzung. In keinem Fall sind die Autoren oder Urheberrechtsinhaber für Ansprüche, Schäden oder andere Haftungen haftbar, sei es in einer Vertragsklage, unerbittlich oder auf andere Weise, die sich aus oder im Zusammenhang mit der Software oder anderen Geschäften in der Software ergeben.