غلاف Elixir لمكتبة RTMIDI. مستوحاة جزئيا من بيثون rtmidi.
تحذير: تعتبر هذه المكتبة تجريبية/ما قبل الألف حتى تتم معالجة بعض المشكلات أدناه.
فكر في التحقق من علامة التبويب "المشكلات" إذا كنت تتطلع إلى المساعدة.
تعمل هذه المكتبة كما هي ، لكنني لست مبرمجًا C ++. أي مساهمات مرحب بها ، لكن المساعدة في هذه المجالات المحددة ستقطع شوطًا طويلاً:
C ++
src/ex_rtmidi_{output,input}.cpp يمكن أن تستخدم OOP بشكل أفضل بكثير و templating لتقليل تكرار الكودinput_callback و attach_listener في src/ex_rtmidi_input.cpp بحاجة إلى نظرة جيدة. مرة أخرى ، يمكن تفضيل Refactor مسبقًاdetach_listener إذا تم استدعاؤه بدون مستمعإكسير
init للمدخلات/المخرجات وقتًا أطول من الموصى بها لـ NIF. انظر lib/ex_rtmidi/{output,input}.ex تعليقاتopenVirtualPortMix.Tasks.Compile.Rtmidi من mix.exs . انظر التعليق في mix.exsعام
C ++ هي لغة OO ، Elixir ليس كذلك. لقد تمزق ما إذا كنت سأعبر عن الأشياء بشكل أكثر وظيفية أو أكثر تمشيا مع اتفاقيات OO. في النهاية تم اختيار نهج أكثر وظيفية.
لإنشاء مثيل RTMIDI ، يتم استدعاء طريقة init مع معرف مثيل. في C ++ ، يتم تخزين المثيل كقيمة في خريطة حيث يكون المعرف هو المفتاح. تتطلب مكالمات المستقبلية إلى طرق مثيل RTMIDI تمرير المعرف لمعرفة مثال الاستهداف.
NIFs هي في المقام الأول بناء erlang ، لذلك سترى أن غلاف Elixir يقوم بالكثير من ConverStion من وإلى charlists. وذلك لأن الأوتار في Erlang هي charlists في Elixir ، وبالتالي فإن طرق سلسلة NIF تأخذ فعليًا وإرجاع charlists بدلاً من String.t() .
المستمعين على منافذ الإدخال كما تم تمريرها إلى C ++ كـ PID. عند استلام الرسالة ، يقوم NIF بتوزيع ويمرر الرسالة على Async إلى PID المحدد.
حتى يتم حل بعض مشكلات C ++ الأكثر إلحاحًا ، لا أريد الترويج لهذه المكتبة للاستخدام العام. حتى ذلك الحين ، سيتعين عليك الحصول عليه من Github:
def deps do
[
{ :ex_rtmidi , git: "https://github.com/kieraneglin/ex_rtmidi" }
]
end حاليًا ، تتخذ هذه المكتبة مقاربة أكثر عارية للتعامل مع الرسائل مما تتوقعه. قد تحصل على قيمة من غلاف صغير حول إرسال الرسائل المخصصة لحالة الاستخدام الخاصة بك.
لقد حددت بعض حالات الاستخدام الأساسية ، ولكن يجب أن ترى lib/ex_rtmidi/{output,input}.ex لمزيد من الوثائق المتعمقة.
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> :okهناك غلاف لرسائل MIDI التي تعمل على تحسين تجربة إنشاء الرسائل. هذا مخصص بشكل أساسي ولم يتم نقله لتفكيك الرسائل الواردة (انظر قسم "المساعدة المطلوبة").
للحصول على قائمة كاملة بالرسائل ، راجع 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 حقوق الطبع والنشر 2021
يتم منح الإذن بموجب هذا ، مجانًا ، لأي شخص يحصل على نسخة من هذا البرنامج وملفات الوثائق المرتبطة به ("البرنامج") ، للتعامل في البرنامج دون تقييد ، بما في ذلك على سبيل المثال لا الحصر حقوق استخدام الأشخاص ونسخها ودمجها ودمجها وتوزيعها وتوزيعها على ما يلي:
يجب إدراج إشعار حقوق الطبع والنشر أعلاه وإشعار الإذن هذا في جميع النسخ أو الأجزاء الكبيرة من البرنامج.
يتم توفير البرنامج "كما هو" ، دون أي ضمان من أي نوع ، صريح أو ضمني ، بما في ذلك على سبيل المثال لا الحصر ضمانات القابلية للتسويق واللياقة لغرض معين وعدم الانفجار. لا يجوز بأي حال من الأحوال أن يكون المؤلفون أو حاملي حقوق الطبع والنشر مسؤولاً عن أي مطالبة أو أضرار أو مسؤولية أخرى ، سواء في إجراء عقد أو ضرر أو غير ذلك ، ناشئة عن أو خارج البرنامج أو الاستخدام أو غيرها من المعاملات في البرنامج.