Pembungkus elixir untuk Perpustakaan RTMIDI. Sebagian terinspirasi oleh Python-rtmidi.
Peringatan: Perpustakaan ini dianggap eksperimental/pra-alpha sampai beberapa masalah di bawah ini ditangani.
Pertimbangkan untuk memeriksa tab "Masalah" jika Anda ingin membantu.
Perpustakaan ini berfungsi apa adanya, tapi saya bukan programmer C ++. Kontribusi apa pun dipersilakan, tetapi bantuan di bidang -bidang khusus ini akan sangat membantu:
C ++
src/ex_rtmidi_{output,input}.cpp bisa jauh lebih baik memanfaatkan oop dan templating untuk mengurangi duplikasi kodeinput_callback dan attach_listener di src/ex_rtmidi_input.cpp membutuhkan tampilan yang bagus. Sekali lagi, seorang refactor sebelumnya lebih disukaidetach_listener tidak boleh mencetak kesalahan jika dipanggil tanpa pendengarEliksir
init untuk input/output membutuhkan waktu lebih lama dari yang disarankan untuk NIF. Lihat lib/ex_rtmidi/{output,input}.ex komentaropenVirtualPort RTMIDIMix.Tasks.Compile.Rtmidi out of mix.exs . Lihat Komentar di mix.exsUmum
C ++ adalah bahasa OO, elixir tidak. Saya terpecah apakah akan mengekspresikan hal -hal lebih fungsional atau lebih sesuai dengan konvensi OO. Pada akhirnya pendekatan yang lebih fungsional dipilih.
Untuk membuat instance RTMIDI, metode init dipanggil dengan pengidentifikasi instan. Dalam C ++, instance disimpan sebagai nilai di peta di mana pengidentifikasi adalah kuncinya. Panggilan di masa depan ke metode instance RTMIDI mengharuskan pengidentifikasi dilewati untuk mengetahui contoh apa yang akan ditargetkan.
NIF terutama merupakan konstruksi Erlang, jadi Anda akan melihat bahwa pembungkus elixir melakukan banyak konversi ke dan dari charlists. Ini karena string di Erlang adalah charlists di elixir, oleh karena itu metode string NIF benar -benar mengambil dan mengembalikan charlists bukan String.t() .
Pendengar pada port input sebagaimana diteruskan ke C ++ sebagai PID. Setelah menerima pesan, NIF mem -parse dan menyampaikan pesan ke async ke PID yang ditentukan.
Sampai beberapa masalah C ++ yang lebih mendesak diselesaikan, saya tidak ingin mempromosikan perpustakaan ini untuk penggunaan publik. Sampai saat itu, Anda harus mendapatkannya dari GitHub:
def deps do
[
{ :ex_rtmidi , git: "https://github.com/kieraneglin/ex_rtmidi" }
]
end Saat ini, perpustakaan ini mengambil pendekatan yang lebih telanjang untuk menangani pesan daripada yang Anda harapkan. Anda mungkin mendapatkan nilai dari pembungkus kecil di sekitar pengiriman dan penguraian pesan yang disesuaikan dengan kasing Anda.
Saya telah menguraikan beberapa kasus penggunaan dasar, tetapi Anda akan melihat lib/ex_rtmidi/{output,input}.ex untuk dokumentasi yang lebih mendalam.
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> :okAda pembungkus untuk pesan MIDI yang meningkatkan pengalaman membuat pesan. Ini terutama untuk output dan belum diangkut untuk mendekonstruksi pesan yang masuk (lihat bagian "Bantuan yang Dibutuhkan").
Untuk daftar lengkap pesan, lihat 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 Hak Cipta 2021
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
Pemberitahuan hak cipta di atas dan pemberitahuan izin ini harus dimasukkan dalam semua salinan atau bagian substansial dari perangkat lunak.
Perangkat lunak ini disediakan "sebagaimana adanya", tanpa jaminan apa pun, tersurat maupun tersirat, termasuk tetapi tidak terbatas pada jaminan dapat diperjualbelikan, kebugaran untuk tujuan tertentu dan nonpringement. Dalam hal apa pun penulis atau pemegang hak cipta tidak akan bertanggung jawab atas klaim, kerusakan atau tanggung jawab lainnya, baik dalam tindakan kontrak, gugatan atau sebaliknya, timbul dari, di luar atau sehubungan dengan perangkat lunak atau penggunaan atau transaksi lain dalam perangkat lunak.