Skip to content

Commit bb3af7b

Browse files
committed
initial commit
1 parent 8e29cf7 commit bb3af7b

File tree

10 files changed

+569
-3
lines changed

10 files changed

+569
-3
lines changed

Project.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
name = "PortMidi"
22
uuid = "42b16160-194f-40b3-8419-7a13c10fa643"
33
authors = ["SteffenPL <[email protected]> and contributors"]
4-
version = "1.0.0-DEV"
4+
version = "0.1.0"
5+
6+
[deps]
7+
PortMidi_jll = "6b227df9-c220-5195-838c-e1464939a66f"
58

69
[compat]
710
julia = "1.6"
11+
PortMidi_jll = "2.0.4"
812

913
[extras]
1014
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

README.md

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,61 @@
1-
# PortMidi
1+
# PortMidi.jl
22

3+
<!---
34
[![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://SteffenPL.github.io/PortMidi.jl/stable/)
45
[![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://SteffenPL.github.io/PortMidi.jl/dev/)
56
[![Build Status](https://github.com/SteffenPL/PortMidi.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/SteffenPL/PortMidi.jl/actions/workflows/CI.yml?query=branch%3Amain)
7+
--->
8+
9+
A Julia wrapper for the [PortMidi](https://github.com/PortMidi/portmidi).
10+
See the [C documentation](https://portmidi.github.io/portmidi_docs/) for a list of functions.
11+
12+
_This wrapper is work in progress. As this is just a hobby for me, I am also happy to hand over the repository in more suitable hands._
13+
14+
## Example
15+
16+
See the `examples` folder for a test case.
17+
18+
```julia
19+
using PortMidi
20+
21+
Pm_Initialize()
22+
23+
# 0. Get info about devices
24+
for i in 0:Pm_CountDevices()-1
25+
info = unsafe_load(Pm_GetDeviceInfo(i))
26+
println(i, ": ", info.output > 0 ? "[Output ] " : "[Input] ", unsafe_string(info.name), " (", unsafe_string(info.interf), ")")
27+
end
28+
29+
# 1. Select device
30+
id = 0 # change this number if needed
31+
print("Use: ", unsafe_string(unsafe_load(Pm_GetDeviceInfo(id)).name))
32+
33+
# 2. Open device
34+
stream = Ref{Ptr{PortMidi.PortMidiStream}}(C_NULL)
35+
Pm_OpenOutput(stream, id, C_NULL, 0, C_NULL, C_NULL, 0)
36+
# don't forget to call later: Pm_Close(stream[])
37+
38+
# 3. Send MIDI messages
39+
Note_ON = 0x90
40+
Note_OFF = 0x80
41+
C4 = 60
42+
43+
function play_note(stream, note, velocity, duration)
44+
Pm_WriteShort(stream[], 0, Pm_Message(Note_ON, note, velocity))
45+
sleep(duration)
46+
Pm_WriteShort(stream[], 0, Pm_Message(Note_OFF, note, velocity))
47+
end
48+
49+
# make a random tune...
50+
for i in 1:12
51+
@async play_note(stream, C4 + rand([-5,-2,0,2,5]), rand(80:120), 0.4 + 0.05*rand())
52+
sleep(0.5 + 0.05*rand())
53+
end
54+
55+
# 4. Close device
56+
Pm_Close(stream[])
57+
```
58+
59+
On Windows, one could use the program [loopMIDI](https://www.tobias-erichsen.de/software/loopmidi.html) to create a virtual MIDI device
60+
and in combination with some virtual instruments (e.g. DAWs, VCV Rack, ...) one can also then listen to the notes in realtime. But this
61+
is only one out of many possible ways to use the `PortMidi` library.

examples/play_notes.jl

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using PortMidi
2+
3+
Pm_Initialize()
4+
5+
# 0. Get info about devices
6+
for i in 0:Pm_CountDevices()-1
7+
info = unsafe_load(Pm_GetDeviceInfo(i))
8+
println(i, ": ", info.output > 0 ? "[Output ] " : "[Input] ", unsafe_string(info.name), " (", unsafe_string(info.interf), ")")
9+
end
10+
11+
# 1. Select device
12+
id = 11
13+
print("Use: ", unsafe_string(unsafe_load(Pm_GetDeviceInfo(id)).name))
14+
15+
# 2. Open device
16+
stream = Ref{Ptr{PortMidi.PortMidiStream}}(C_NULL)
17+
Pm_OpenOutput(stream, id, C_NULL, 0, C_NULL, C_NULL, 0)
18+
# don't forget to call later: Pm_Close(stream[])
19+
20+
# 3. Send MIDI messages
21+
Note_ON = 0x90
22+
Note_OFF = 0x80
23+
C4 = 60
24+
25+
function play_note(stream, note, velocity, duration)
26+
Pm_WriteShort(stream[], 0, Pm_Message(Note_ON, note, velocity))
27+
sleep(duration)
28+
Pm_WriteShort(stream[], 0, Pm_Message(Note_OFF, note, velocity))
29+
end
30+
31+
# make a random tune...
32+
for i in 1:12
33+
@async play_note(stream, C4 + rand([-5,-2,0,2,5]), rand(80:120), 0.4 + 0.05*rand())
34+
sleep(0.5 + 0.05*rand())
35+
end
36+
37+
# 4. Close device
38+
Pm_Close(stream[])

gen/Manifest.toml

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
# This file is machine-generated - editing it directly is not advised
2+
3+
julia_version = "1.9.1"
4+
manifest_format = "2.0"
5+
project_hash = "40f0b0cca44e6451975797e90b2d06a0b8d8569a"
6+
7+
[[deps.ArgTools]]
8+
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"
9+
version = "1.1.1"
10+
11+
[[deps.Artifacts]]
12+
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
13+
14+
[[deps.Base64]]
15+
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
16+
17+
[[deps.CEnum]]
18+
git-tree-sha1 = "389ad5c84de1ae7cf0e28e381131c98ea87d54fc"
19+
uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82"
20+
version = "0.5.0"
21+
22+
[[deps.Clang]]
23+
deps = ["CEnum", "Clang_jll", "Downloads", "Pkg", "TOML"]
24+
git-tree-sha1 = "846054622cb22aa63b5d51b5d84ec04b42d4d587"
25+
uuid = "40e3b903-d033-50b4-a0cc-940c62c95e31"
26+
version = "0.17.8"
27+
28+
[[deps.Clang_jll]]
29+
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "TOML", "Zlib_jll", "libLLVM_jll"]
30+
git-tree-sha1 = "124bb00d4ceace456054f17c7cb01e5c8195c609"
31+
uuid = "0ee61d77-7f21-5576-8119-9fcc46b10100"
32+
version = "14.0.6+4"
33+
34+
[[deps.Dates]]
35+
deps = ["Printf"]
36+
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
37+
38+
[[deps.Downloads]]
39+
deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"]
40+
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
41+
version = "1.6.0"
42+
43+
[[deps.FileWatching]]
44+
uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"
45+
46+
[[deps.InteractiveUtils]]
47+
deps = ["Markdown"]
48+
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
49+
50+
[[deps.JLLWrappers]]
51+
deps = ["Artifacts", "Preferences"]
52+
git-tree-sha1 = "7e5d6779a1e09a36db2a7b6cff50942a0a7d0fca"
53+
uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210"
54+
version = "1.5.0"
55+
56+
[[deps.LibCURL]]
57+
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
58+
uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"
59+
version = "0.6.3"
60+
61+
[[deps.LibCURL_jll]]
62+
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
63+
uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"
64+
version = "7.84.0+0"
65+
66+
[[deps.LibGit2]]
67+
deps = ["Base64", "NetworkOptions", "Printf", "SHA"]
68+
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"
69+
70+
[[deps.LibSSH2_jll]]
71+
deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
72+
uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"
73+
version = "1.10.2+0"
74+
75+
[[deps.Libdl]]
76+
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
77+
78+
[[deps.Logging]]
79+
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
80+
81+
[[deps.Markdown]]
82+
deps = ["Base64"]
83+
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
84+
85+
[[deps.MbedTLS_jll]]
86+
deps = ["Artifacts", "Libdl"]
87+
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"
88+
version = "2.28.2+0"
89+
90+
[[deps.MozillaCACerts_jll]]
91+
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"
92+
version = "2022.10.11"
93+
94+
[[deps.NetworkOptions]]
95+
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"
96+
version = "1.2.0"
97+
98+
[[deps.Pkg]]
99+
deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
100+
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
101+
version = "1.9.0"
102+
103+
[[deps.PortMidi_jll]]
104+
deps = ["Artifacts", "JLLWrappers", "Libdl", "alsa_jll"]
105+
git-tree-sha1 = "865436b433a7ed35ca02b5ef12a00ce29c75364b"
106+
uuid = "6b227df9-c220-5195-838c-e1464939a66f"
107+
version = "2.0.4+0"
108+
109+
[[deps.Preferences]]
110+
deps = ["TOML"]
111+
git-tree-sha1 = "00805cd429dcb4870060ff49ef443486c262e38e"
112+
uuid = "21216c6a-2e73-6563-6e65-726566657250"
113+
version = "1.4.1"
114+
115+
[[deps.Printf]]
116+
deps = ["Unicode"]
117+
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"
118+
119+
[[deps.REPL]]
120+
deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
121+
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
122+
123+
[[deps.Random]]
124+
deps = ["SHA", "Serialization"]
125+
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
126+
127+
[[deps.SHA]]
128+
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
129+
version = "0.7.0"
130+
131+
[[deps.Serialization]]
132+
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
133+
134+
[[deps.Sockets]]
135+
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"
136+
137+
[[deps.TOML]]
138+
deps = ["Dates"]
139+
uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
140+
version = "1.0.3"
141+
142+
[[deps.Tar]]
143+
deps = ["ArgTools", "SHA"]
144+
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"
145+
version = "1.10.0"
146+
147+
[[deps.UUIDs]]
148+
deps = ["Random", "SHA"]
149+
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
150+
151+
[[deps.Unicode]]
152+
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
153+
154+
[[deps.Zlib_jll]]
155+
deps = ["Libdl"]
156+
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"
157+
version = "1.2.13+0"
158+
159+
[[deps.alsa_jll]]
160+
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
161+
git-tree-sha1 = "69859a01e7735ce5b49b1328827f6e3f4cdd7d19"
162+
uuid = "45378030-f8ea-5b20-a7c7-1a9d95efb90e"
163+
version = "1.2.5+0"
164+
165+
[[deps.libLLVM_jll]]
166+
deps = ["Artifacts", "Libdl"]
167+
uuid = "8f36deef-c2a5-5394-99ed-8e07531fb29a"
168+
version = "14.0.6+3"
169+
170+
[[deps.nghttp2_jll]]
171+
deps = ["Artifacts", "Libdl"]
172+
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"
173+
version = "1.48.0+0"
174+
175+
[[deps.p7zip_jll]]
176+
deps = ["Artifacts", "Libdl"]
177+
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
178+
version = "17.4.0+0"

gen/Project.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[deps]
2+
Clang = "40e3b903-d033-50b4-a0cc-940c62c95e31"
3+
PortMidi_jll = "6b227df9-c220-5195-838c-e1464939a66f"

gen/epilogue.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Pm_Message(status, data1, data2) = ((((data2) << 16) & 0xFF0000) | (((data1) << 8) & 0xFF00) | ((status) & 0xFF))
2+
Pm_MessageStatus(msg) = ((msg) & 0xFF)
3+
Pm_MessageData1(msg) = (((msg) >> 8) & 0xFF)
4+
Pm_MessageData2(msg) = (((msg) >> 16) & 0xFF)
5+
6+
export Pm_Message, Pm_MessageStatus, Pm_MessageData1, Pm_MessageData2

gen/generate.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using Clang.Generators
2+
using PortMidi_jll
3+
4+
cd(@__DIR__)
5+
include_dir = normpath(PortMidi_jll.artifact_dir, "include")
6+
7+
options = load_options(joinpath(@__DIR__, "generator.toml"))
8+
args = get_default_args()
9+
push!(args, "-I$include_dir")
10+
11+
headers = detect_headers(include_dir, args)
12+
ctx = create_context(headers, args, options)
13+
14+
build!(ctx)

gen/generator.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[general]
2+
library_name = "libportmidi"
3+
output_file_path = "../src/PortMidi.jl"
4+
module_name = "PortMidi"
5+
jll_pkg_name = "PortMidi_jll"
6+
7+
# use_julia_native_enum_type = true
8+
9+
# prologue_file_path = "prologue.jl"
10+
# epilogue_file_path = "epilogue.jl"
11+
12+
# export_symbol_prefixes = ["Pm"]
13+
# output_ignorelist = ["TRUE", "FALSE"]
14+
15+
ignore_pure_definition = false

gen/prologue.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
to_c_type(::Type{<:AbstractString}) = Cstring # or Ptr{Cchar}
2+
to_c_type(t::Type{<:Union{AbstractArray,Ref}}) = Ptr{eltype(t)}

0 commit comments

Comments
 (0)