{"id":13431015,"url":"https://github.com/artfwo/aalink","last_synced_at":"2025-12-30T00:36:04.022Z","repository":{"id":165671414,"uuid":"637351635","full_name":"artfwo/aalink","owner":"artfwo","description":"Async Python interface for Ableton Link","archived":false,"fork":false,"pushed_at":"2024-04-04T17:20:52.000Z","size":41,"stargazers_count":21,"open_issues_count":1,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-09-27T05:26:37.212Z","etag":null,"topics":["ableton-link","algorithmic-composition","computer-music","creative-coding","electronic-music","multimedia","music","python"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/artfwo.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-05-07T09:40:14.000Z","updated_at":"2024-09-04T02:05:58.000Z","dependencies_parsed_at":null,"dependency_job_id":"f9347405-f706-4eed-8659-2c7517793935","html_url":"https://github.com/artfwo/aalink","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artfwo%2Faalink","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artfwo%2Faalink/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artfwo%2Faalink/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artfwo%2Faalink/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/artfwo","download_url":"https://codeload.github.com/artfwo/aalink/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221656503,"owners_count":16858784,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ableton-link","algorithmic-composition","computer-music","creative-coding","electronic-music","multimedia","music","python"],"created_at":"2024-07-31T02:00:59.824Z","updated_at":"2025-12-30T00:36:04.016Z","avatar_url":"https://github.com/artfwo.png","language":"C++","funding_links":[],"categories":["C++"],"sub_categories":[],"readme":"======\naalink\n======\n\naalink is a Python wrapper for Ableton Link built for interactive applications\nusing asyncio event loops.\n\nIt provides a simple programming interface for writing concurrent Python code\nsynchronized to a beat. The beat can optionally be time-aligned with other\npeers in an Ableton Link session.\n\nInstallation\n============\n\naalink requires at least Python 3.9. It can be installed using pip::\n\n    pip3 install aalink\n\nIt may be required to install the latest version of MSVC Runtime libraries\non Windows to use the binary wheels currently hosted on PyPI.\n\nUsage\n=====\n\naalink uses asyncio. To connect to a Link session, create a ``Link`` object,\npassing the asyncio event loop to the constructor, and await for\n``Link.sync()`` as follows:\n\n.. code-block:: python\n\n    import asyncio\n\n    from aalink import Link\n\n    async def main():\n        loop = asyncio.get_running_loop()\n\n        link = Link(120, loop)\n        link.enabled = True\n\n        while True:\n            await link.sync(1)\n            print('bang!')\n\n    asyncio.run(main())\n\n``Link.sync(n)`` returns a ``Future`` scheduled to be *done* when Link time\nreaches next n-th beat on the timeline.\n\nIn the above example, awaiting for ``link.sync(1)`` will pause and resume\nthe ``main`` coroutine at beats 1, 2, 3, and so on.\n\nKeep in mind that awaiting for ``sync(n)`` does not cause a coroutine to sleep\nfor the given number of beats. Regardless of the moment when the coroutine is\nsuspended, it will resume when the next closest n-th beat is reached on the\nshared Link timeline, e.g. awaiting for ``sync(2)`` at beat 11.5 will resume\nat beat 12.\n\nNon-integral beat syncing is supported. For example:\n\n.. code-block:: python\n\n    await link.sync(1/2) # resumes at beats 0.5, 1, 1.5...\n    await link.sync(3/2) # resumes at beats 1.5, 3, 4.5...\n\nSync events can be scheduled with an offset (also expressed in beats) by\npassing an ``offset`` argument to ``sync()``. Use this to add groove to the\ncoroutine rhythm.\n\n.. code-block:: python\n\n    async def arpeggiate():\n        for i in range(16):\n            swing = 0.25 if i % 2 == 1 else 0\n\n            await link.sync(1/2, offset=swing)\n            print('###', i)\n\n            await link.sync(1/2, offset=0)\n            print('@@@', i)\n\nCombine synced coroutines to run in series or concurrently:\n\n.. code-block:: python\n\n    import asyncio\n    from aalink import Link\n\n    async def main():\n        loop = asyncio.get_running_loop()\n\n        link = Link(120, loop)\n        link.enabled = True\n\n        async def sequence(name):\n            for i in range(4):\n                await link.sync(1)\n                print('bang!', name)\n\n        await sequence('a')\n        await sequence('b')\n\n        await asyncio.gather(sequence('c'), sequence('d'))\n\n    asyncio.run(main())\n\nLimitations\n-----------\n\naalink aims to be punctual, but it is not 100% accurate due to the processing\ndelay in the internal scheduler and the uncertainty of event loop iterations\ntiming.\n\nFor convenience, the numerical values of futures returned from ``sync()``\naren't equal to the exact beat time from the moment the futures are *done*.\nThey correspond to the previously estimated resume times instead.\n\n.. code-block:: python\n\n    b = await link.sync(1) # b will be 1.0, returned at beat 1.00190\n    b = await link.sync(1) # b will be 2.0, returned at beat 2.00027\n    b = await link.sync(1) # b will be 3.0, returned at beat 3.00005\n\nLicense\n-------\n\nCopyright (c) 2023 Artem Popov \u003cart@artfwo.net\u003e\n\naalink is licensed under the GNU General Public License (GPL) version 3.\nYou can find the full text of the GPL license in the ``LICENSE`` file included\nin this repository.\n\naalink includes code from pybind11 and Ableton Link.\n\n`pybind11 \u003chttps://pybind11.readthedocs.io/\u003e`_\n\nCopyright (c) 2016 Wenzel Jakob \u003cwenzel.jakob@epfl.ch\u003e, All rights reserved.\n\n`pybind11 license \u003chttps://github.com/pybind/pybind11/blob/master/LICENSE\u003e`_\n\n`Ableton Link \u003chttps://ableton.github.io/link/\u003e`_\n\nCopyright 2016, Ableton AG, Berlin. All rights reserved.\n\n`Ableton Link license \u003chttps://github.com/Ableton/link/blob/master/LICENSE.md\u003e`_\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fartfwo%2Faalink","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fartfwo%2Faalink","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fartfwo%2Faalink/lists"}