Observed since 20 Oct, 16:57 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
aalink
Async Python interface for Ableton Link
======
aalink
======
aalink is a Python wrapper for Ableton Link built for interactive applications
using asyncio event loops.
It provides a simple programming interface for writing concurrent Python code
synchronized to a beat. The beat can optionally be time-aligned with other
peers in an Ableton Link session.
Installation
============
aalink requires at least Python 3.9. It can be installed using pip::
pip3 install aalink
It may be required to install the latest version of MSVC Runtime libraries
on Windows to use the binary wheels currently hosted on PyPI.
Usage
=====
aalink uses asyncio. To connect to a Link session, create a ``Link`` object,
and await for ``Link.sync()`` as follows:
.. code-block:: python
import asyncio
from aalink import Link
async def main():
link = Link(120)
link.enabled = True
while True:
await link.sync(1)
print('bang!')
asyncio.run(main())
``Link.sync(n)`` returns a ``Future`` scheduled to be *done* when Link time
reaches next n-th beat on the timeline.
In the above example, awaiting for ``link.sync(1)`` will pause and resume
the ``main`` coroutine at beats 1, 2, 3, and so on.
Keep in mind that awaiting for ``sync(n)`` does not cause a coroutine to sleep
for the given number of beats. Regardless of the moment when the coroutine is
suspended, it will resume when the next closest n-th beat is reached on the
shared Link timeline, e.g. awaiting for ``sync(2)`` at beat 11.5 will resume
at beat 12.
Non-integral beat syncing is supported. For example:
.. code-block:: python
await link.sync(1/2) # resumes at beats 0.5, 1, 1.5...
await link.sync(3/2) # resumes at beats 1.5, 3, 4.5...
from fractions import Fraction
await link.sync(Fraction(1, 2)) # works too
Sync events can be scheduled with an offset (also expressed in beats) by
passing an ``offset`` argument to ``sync()``. Offset can be either positive
or negative. Use this to add groove to the coroutine rhythm.
.. code-block:: python
async def arpeggiate():
for i in range(16):
swing = 0.25 if i % 2 == 1 else 0
await link.sync(1/2, offset=swing)
print('###', i)
await link.sync(1/2, offset=0)
print('@@@', i)
Combine synced coroutines to run in series or concurrently:
.. code-block:: python
import asyncio
from aalink import Link
async def main():
link = Link(120)
link.enabled = True
async def sequence(name):
for i in range(4):
await link.sync(1)
print('bang!', name)
await sequence('a')
await sequence('b')
await asyncio.gather(sequence('c'), sequence('d'))
asyncio.run(main())
Limitations
-----------
aalink aims to be punctual, but it is not 100% accurate due to the processing
delay in the internal scheduler and the uncertainty of event loop iterations
timing.
For convenience, the numerical values of futures returned from ``sync()``
aren't equal to the exact beat time from the moment the futures are *done*.
They correspond to the previously estimated resume times instead.
.. code-block:: python
b = await link.sync(1) # b will be 1.0, returned at beat 1.00190
b = await link.sync(1) # b will be 2.0, returned at beat 2.00027
b = await link.sync(1) # b will be 3.0, returned at beat 3.00005
License
-------
Copyright (c) 2023 Artem Popov <art@artfwo.net>
aalink is licensed under the GNU General Public License (GPL) version 3.
You can find the full text of the GPL license in the ``LICENSE`` file included
in this repository.
aalink includes code from pybind11 and Ableton Link.
`pybind11 <https://pybind11.readthedocs.io/>`_
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>, All rights reserved.
`pybind11 license <https://github.com/pybind/pybind11/blob/master/LICENSE>`_
`Ableton Link <https://ableton.github.io/link/>`_
Copyright 2016, Ableton AG, Berlin. All rights reserved.
`Ableton Link license <https://github.com/Ableton/link/blob/master/LICENSE.md>`_
Download counts and popularity will appear here as the collector receives them.
Declarations describe requirements; they are not a resolved dependency graph.
bdist_wheel · 199.03 KB · Python cp310
bdist_wheel · 214.08 KB · Python cp310
bdist_wheel · 212 KB · Python cp310
bdist_wheel · 223.74 KB · Python cp310
bdist_wheel · 1,182.29 KB · Python cp310
bdist_wheel · 1,243.24 KB · Python cp310
bdist_wheel · 373.65 KB · Python cp310
bdist_wheel · 539.17 KB · Python cp310
bdist_wheel · 200.14 KB · Python cp311
bdist_wheel · 215.33 KB · Python cp311
bdist_wheel · 212.79 KB · Python cp311
bdist_wheel · 224.22 KB · Python cp311
bdist_wheel · 1,182.94 KB · Python cp311
bdist_wheel · 1,244.5 KB · Python cp311
bdist_wheel · 374.4 KB · Python cp311
bdist_wheel · 540.18 KB · Python cp311
bdist_wheel · 200.51 KB · Python cp312
bdist_wheel · 216.05 KB · Python cp312
bdist_wheel · 213.12 KB · Python cp312
bdist_wheel · 225.24 KB · Python cp312
bdist_wheel · 1,182.93 KB · Python cp312
bdist_wheel · 1,244.59 KB · Python cp312
bdist_wheel · 375.32 KB · Python cp312
bdist_wheel · 539.22 KB · Python cp312
bdist_wheel · 200.57 KB · Python cp313
bdist_wheel · 216.12 KB · Python cp313
bdist_wheel · 213.17 KB · Python cp313
bdist_wheel · 225.25 KB · Python cp313
bdist_wheel · 1,182.97 KB · Python cp313
bdist_wheel · 1,244.69 KB · Python cp313
bdist_wheel · 375.36 KB · Python cp313
bdist_wheel · 539.23 KB · Python cp313
bdist_wheel · 200.74 KB · Python cp314
bdist_wheel · 216.2 KB · Python cp314
bdist_wheel · 213.42 KB · Python cp314
bdist_wheel · 225.64 KB · Python cp314
bdist_wheel · 1,183.29 KB · Python cp314
bdist_wheel · 1,245.03 KB · Python cp314
bdist_wheel · 206.88 KB · Python cp314
bdist_wheel · 222 KB · Python cp314
bdist_wheel · 215.05 KB · Python cp314
bdist_wheel · 226.99 KB · Python cp314
bdist_wheel · 1,187.01 KB · Python cp314
bdist_wheel · 1,247.84 KB · Python cp314
bdist_wheel · 398.03 KB · Python cp314
bdist_wheel · 563.86 KB · Python cp314
bdist_wheel · 387.56 KB · Python cp314
bdist_wheel · 558.08 KB · Python cp314
bdist_wheel · 199.14 KB · Python cp39
bdist_wheel · 214.16 KB · Python cp39
Observed since 20 Oct, 16:57 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:3af5b580126868ca043ab4a1eb4660152b42ed8a5bfed339eade5cc915a942e4