Skip to content

Commit 3aa5238

Browse files
authored
Merge pull request #4 from artfwo/pybind11
Migrate back from nanobind to pybind11
2 parents 068ef6d + e03cdbc commit 3aa5238

File tree

7 files changed

+47
-47
lines changed

7 files changed

+47
-47
lines changed

.gitmodules

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[submodule "link"]
22
path = ext/link
33
url = https://github.com/Ableton/link.git
4-
[submodule "ext/nanobind"]
5-
path = ext/nanobind
6-
url = https://github.com/wjakob/nanobind
4+
[submodule "ext/pybind11"]
5+
path = ext/pybind11
6+
url = https://github.com/pybind/pybind11

CMakeLists.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ endif()
1111

1212
set(CMAKE_CXX_STANDARD 20)
1313

14-
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/ext/nanobind)
15-
nanobind_add_module(aalink src/aalink.cpp)
14+
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/ext/pybind11)
15+
pybind11_add_module(aalink src/aalink.cpp)
1616

1717
include(${CMAKE_CURRENT_SOURCE_DIR}/ext/link/AbletonLinkConfig.cmake)
1818
target_link_libraries(aalink PUBLIC Ableton::Link)

README.rst

+4-4
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,13 @@ aalink is licensed under the GNU General Public License (GPL) version 3.
131131
You can find the full text of the GPL license in the ``LICENSE`` file included
132132
in this repository.
133133

134-
aalink includes code from nanobind and Ableton Link.
134+
aalink includes code from pybind11 and Ableton Link.
135135

136-
`nanobind <https://nanobind.readthedocs.io/>`_
136+
`pybind11 <https://pybind11.readthedocs.io/>`_
137137

138-
Copyright (c) 2022 Wenzel Jakob <wenzel.jakob@epfl.ch>, All rights reserved.
138+
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>, All rights reserved.
139139

140-
`nanobind license <https://github.com/wjakob/nanobind/blob/master/LICENSE>`_
140+
`pybind11 license <https://github.com/pybind/pybind11/blob/master/LICENSE>`_
141141

142142
`Ableton Link <https://ableton.github.io/link/>`_
143143

ext/nanobind

-1
This file was deleted.

ext/pybind11

Submodule pybind11 added at 2b2e4ca

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
44

55
[project]
66
name = "aalink"
7-
version = "0.0.5"
7+
version = "0.0.6"
88
description = "Async Python interface for Ableton Link"
99
readme = "README.rst"
1010
requires-python = ">=3.8"

src/aalink.cpp

+36-36
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#include <nanobind/stl/chrono.h>
2-
#include <nanobind/nanobind.h>
1+
#include <pybind11/chrono.h>
2+
#include <pybind11/pybind11.h>
33

44
#include <algorithm>
55
#include <chrono>
@@ -9,10 +9,10 @@
99

1010
#include <ableton/Link.hpp>
1111

12-
namespace nb = nanobind;
12+
namespace py = pybind11;
1313

1414
struct SchedulerSyncEvent {
15-
nb::object future;
15+
py::object future;
1616

1717
double beat;
1818
double offset;
@@ -40,10 +40,10 @@ static double next_link_beat(double current_beat, double sync_beat, double offse
4040
return std::max(next_beat, 0.0);
4141
}
4242

43-
static void set_future_result(nb::object future, double link_beat) {
44-
nb::gil_scoped_acquire acquire;
43+
static void set_future_result(py::object future, double link_beat) {
44+
py::gil_scoped_acquire acquire;
4545

46-
bool done = nb::cast<bool>(future.attr("done")());
46+
bool done = py::cast<bool>(future.attr("done")());
4747

4848
if (!done) {
4949
auto set_result = future.attr("set_result");
@@ -52,7 +52,7 @@ static void set_future_result(nb::object future, double link_beat) {
5252
}
5353

5454
struct Scheduler {
55-
Scheduler(ableton::Link& link, nb::object loop) : m_link(link), m_loop(loop) {
55+
Scheduler(ableton::Link& link, py::object loop) : m_link(link), m_loop(loop) {
5656
start();
5757
}
5858

@@ -86,13 +86,13 @@ struct Scheduler {
8686

8787
for (auto it = m_events.begin(); it != m_events.end();) {
8888
if (link_beat > it->link_beat) {
89-
nb::gil_scoped_acquire acquire;
89+
py::gil_scoped_acquire acquire;
9090

91-
bool loop_is_running = nb::cast<bool>(m_loop.attr("is_running")());
91+
bool loop_is_running = py::cast<bool>(m_loop.attr("is_running")());
9292

9393
if (loop_is_running) {
9494
auto loop_call_soon_threadsafe = m_loop.attr("call_soon_threadsafe");
95-
loop_call_soon_threadsafe(nb::cpp_function(&set_future_result), it->future, it->link_beat);
95+
loop_call_soon_threadsafe(py::cpp_function(&set_future_result), it->future, it->link_beat);
9696
}
9797

9898
it = m_events.erase(it);
@@ -111,7 +111,7 @@ struct Scheduler {
111111
}
112112
}
113113

114-
void schedule_sync(nb::object future, double beat, double offset, double origin) {
114+
void schedule_sync(py::object future, double beat, double offset, double origin) {
115115
SchedulerSyncEvent event = {
116116
.future = future,
117117
.beat = beat,
@@ -121,7 +121,7 @@ struct Scheduler {
121121
};
122122

123123
// prevent occasional GIL deadlocks when calling link.sync()
124-
nb::gil_scoped_release release;
124+
py::gil_scoped_release release;
125125

126126
m_events_mutex.lock();
127127
m_events.push_back(std::move(event));
@@ -151,11 +151,11 @@ struct Scheduler {
151151
std::atomic<double> m_link_quantum{1};
152152

153153
ableton::Link& m_link;
154-
nb::object m_loop;
154+
py::object m_loop;
155155
};
156156

157157
struct Link {
158-
Link(double bpm, nb::object loop)
158+
Link(double bpm, py::object loop)
159159
: m_link(bpm), m_loop(loop), m_scheduler(m_link, m_loop) {}
160160

161161
std::size_t num_peers() {
@@ -254,71 +254,71 @@ struct Link {
254254
m_scheduler.reschedule_sync_events(beat);
255255
}
256256

257-
void set_num_peers_callback(nb::callable callback) {
257+
void set_num_peers_callback(py::function callback) {
258258
m_link.setNumPeersCallback([this, callback](std::size_t num_peers) {
259259
// ensure the callback isn't called when the runtime is finalizing
260260
if (!_Py_IsFinalizing()) {
261-
nb::gil_scoped_acquire acquire;
261+
py::gil_scoped_acquire acquire;
262262

263263
auto loop_call_soon_threadsafe = this->m_loop.attr("call_soon_threadsafe");
264264
loop_call_soon_threadsafe(callback, num_peers);
265265
}
266266
});
267267
}
268268

269-
void set_tempo_callback(nb::callable callback) {
269+
void set_tempo_callback(py::function callback) {
270270
m_link.setTempoCallback([this, callback](double tempo) {
271271
// ensure the callback isn't called when the runtime is finalizing
272272
if (!_Py_IsFinalizing()) {
273-
nb::gil_scoped_acquire acquire;
273+
py::gil_scoped_acquire acquire;
274274

275275
auto loop_call_soon_threadsafe = this->m_loop.attr("call_soon_threadsafe");
276276
loop_call_soon_threadsafe(callback, tempo);
277277
}
278278
});
279279
}
280280

281-
void set_start_stop_callback(nb::callable callback) {
281+
void set_start_stop_callback(py::function callback) {
282282
m_link.setStartStopCallback([this, callback](bool playing) {
283283
// ensure the callback isn't called when the runtime is finalizing
284284
if (!_Py_IsFinalizing()) {
285-
nb::gil_scoped_acquire acquire;
285+
py::gil_scoped_acquire acquire;
286286

287287
auto loop_call_soon_threadsafe = this->m_loop.attr("call_soon_threadsafe");
288288
loop_call_soon_threadsafe(callback, playing);
289289
}
290290
});
291291
}
292292

293-
nb::object sync(double beat, double offset, double origin) {
293+
py::object sync(double beat, double offset, double origin) {
294294
auto future = m_loop.attr("create_future")();
295295
m_scheduler.schedule_sync(future, beat, offset, origin);
296296
return future;
297297
}
298298

299299
ableton::Link m_link;
300-
nb::object m_loop;
300+
py::object m_loop;
301301
Scheduler m_scheduler;
302302
};
303303

304-
NB_MODULE(aalink, m) {
305-
nb::class_<Link>(m, "Link")
306-
.def(nb::init<double, nb::object>(), nb::arg("bpm"), nb::arg("loop"))
307-
.def_prop_ro("num_peers", &Link::num_peers)
308-
.def_prop_ro("beat", &Link::beat)
309-
.def_prop_ro("phase", &Link::phase)
310-
.def_prop_ro("time", &Link::time)
311-
.def_prop_rw("quantum", &Link::quantum, &Link::set_quantum)
312-
.def_prop_rw("enabled", &Link::enabled, &Link::set_enabled)
313-
.def_prop_rw("start_stop_sync_enabled", &Link::start_stop_sync_enabled, &Link::set_start_stop_sync_enabled)
314-
.def_prop_rw("tempo", &Link::tempo, &Link::set_tempo)
315-
.def_prop_rw("playing", &Link::playing, &Link::set_playing)
304+
PYBIND11_MODULE(aalink, m) {
305+
py::class_<Link>(m, "Link")
306+
.def(py::init<double, py::object>(), py::arg("bpm"), py::arg("loop"))
307+
.def_property_readonly("num_peers", &Link::num_peers)
308+
.def_property_readonly("beat", &Link::beat)
309+
.def_property_readonly("phase", &Link::phase)
310+
.def_property_readonly("time", &Link::time)
311+
.def_property("quantum", &Link::quantum, &Link::set_quantum)
312+
.def_property("enabled", &Link::enabled, &Link::set_enabled)
313+
.def_property("start_stop_sync_enabled", &Link::start_stop_sync_enabled, &Link::set_start_stop_sync_enabled)
314+
.def_property("tempo", &Link::tempo, &Link::set_tempo)
315+
.def_property("playing", &Link::playing, &Link::set_playing)
316316
.def("request_beat", &Link::request_beat)
317317
.def("force_beat", &Link::force_beat)
318318
.def("request_beat_at_start_playing_time", &Link::request_beat_at_start_playing_time)
319319
.def("set_is_playing_and_request_beat_at_time", &Link::set_is_playing_and_request_beat_at_time)
320320
.def("set_num_peers_callback", &Link::set_num_peers_callback)
321321
.def("set_tempo_callback", &Link::set_tempo_callback)
322322
.def("set_start_stop_callback", &Link::set_start_stop_callback)
323-
.def("sync", &Link::sync, nb::arg("beat"), nb::arg("offset") = 0, nb::arg("origin") = 0);
323+
.def("sync", &Link::sync, py::arg("beat"), py::arg("offset") = 0, py::arg("origin") = 0);
324324
}

0 commit comments

Comments
 (0)