Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Link implementation is incomplete #3

Open
brunchboy opened this issue May 23, 2018 · 5 comments
Open

Link implementation is incomplete #3

brunchboy opened this issue May 23, 2018 · 5 comments

Comments

@brunchboy
Copy link

I was interested in using this in my Beat Link Trigger project, so that people would no longer have to run my Carabiner as a separate process in order to synchronize Link with DJ shows, but I can’t because your set-beat function doesn’t implement the actual Link library requestBeatAtTime API; it assumes that the time at which the function was called is the time at which the beat is desired. In my case, that’s not true; I have a timestamp at which I received a beat packet from a Pioneer CDJ, and I want the Link session’s beat to occur at that time.

In general, users of your library may need to use the Link API as Ableton provided it; could you please make a version that fully exposes the actual underlying API?

I think it would also be very nice to separate this into two projects, one which does nothing more than provide a faithful Clojure interface to the Link API as Ableton defined it, and a second project where you build things like your event queue and clock thread to bridge things to the Overtone world. I am only interested in the former. Would you consider such a split? Otherwise, I may want to fork this project and do it myself.

@hlolli
Copy link
Member

hlolli commented May 23, 2018

I wouldn't mind if you'd fork the project and do it yourself, but I also don't see a reason to be able to use the API without the clock thread layer. I based this decision on the success of https://github.com/2bbb/node-abletonlink/blob/master/index.js which behaves very similarly. It makes a better user story, I don't think the c++ api was intended for a user, but a developers makeing software to make music.

To make this very easy, you can always access symbols from the defclib macro

https://github.com/overtone/ableton-link/blob/master/src/overtone/ableton_link.clj#L10-L25

The logic for the - prefix on the symbols, was to indicate these symbols as non-public. But they are in fact public and you can call them, and I'd suggest just rename them.

Another reason why I'd want to include some layer over the Ableton API is that I'd preferably want to use Ableton-Link as hot replace for overtone/at-at project. The difference being that at-at doesn't have any native dependencies but ableton-link does, and that means that by the nature of distributing shared library, this is going to fail for some users (but they should be in small minority tough, or use exotic linux-distro). I'd see it as good move to move that interface to a new file and leave to core api in its own file.

The issue about requestBeatAtTime, set-beat actually calls this function
https://github.com/overtone/ableton-link/blob/master/bindings/link_bindings.hpp#L35-L40
And this is, like much of that file, taken from the node bindings of ableton-link. And there it looks the same. So if it's failing, it's probably the c++ code there that's doing something wrong.

It's still incomplete, the newest, stopsync functionality is not yet implemented, until that is finished, and more people, like you, test it, find errors, I will first then be able to remove the alpha tag away and call it a release.

@brunchboy
Copy link
Author

I think we had some miscommunication. I fully understand why you want to build a layer on top of the Ableton API in order to provide a more convenient user experience in the Overtone world. And I personally was looking for a simple Clojure interface to the exact API that Ableton provided for Link. That’s why I was thinking that it might make sense to have two projects, one that provided the low-level Clojure interface with no semantic changes for developers like me, and one built on top that that provided a friendly Overtone adaptation of it.

What I was saying about set-beat was that it is missing a time parameter; I need to be able to say, as the Link API allows, “this beat occurred at a specific point in the past” because I received a packet very slightly in the past telling me about it, and people are using my software to synchronize music, video, lights, and lasers to things being performed by DJs. While set-beat instead only allows me to say “this beat occurred now” because it does not accept a timestamp argument—instead it asks the system what the current time is when processing the function call, and passes that along to Link.

Accessing the low-level AbletonLink_setBeat function does not help because that function is the one that is missing the timestamp parameter which the actual Link API offers. So it seems you are right, if this code came from the node bindings, then those are themselves an incorrect implementation of the Link protocol. The function it calls in Link is void requestBeatAtTime(double beat, std::chrono::microseconds time, double quantum);

However, now that I have noticed that this project links with the Ableton-provided Link code, and must therefore be released under the GPL, I can’t use it anyway; my libraries and projects are released under the EPL so as to allow people more freedom in how they use them, including for commercial projects. Which is why I went a different route in writing my Carabiner network-to-Link daemon, and I will simply continue to use that. So if you are not interested in offering both a low-level and high-level Clojure interface to Link, feel free to close this issue.

In any case, congratulations on what you have accomplished so far, it is a nice integration for the Clojure world, and best of luck in completing the features you are working on!

@hlolli
Copy link
Member

hlolli commented May 23, 2018

If there's a seperate file for the layer, and you'd only require the core one, then it wouldn't matter for your case that extra 20kb clj file is in your maven repo but never used. So don't think there's misunderstanding there on my behalf.

But I'll admit I misunderstood you on the setBeat, you're really looking for requestBeatAtTime. But like you say, you're really in dilemma with licencing. I'm not a patent lawyer, if Ableton are hard on their licencing, then I'm not sure that alternative interface useing seperate sources can use the brandname ableton-link. Maybe companies wanting to implement Ableton Link in their proprietary products can get some good deals with Ableton. Can't believe that they are very restrictive, when companies are trying to build products that can communicate with their products.

But today is not the best time, in a new country today, music gig this weekend. I'll keep the ticket open, it's not my intention to have this specific to overtone at all. I'll add an interface in c++ to requestBeatAtTime and recompile, for that I need my mac and windows back in Berlin, so I could do it next week. I'll update here.

@brunchboy
Copy link
Author

Ah, excellent point, yes, I could ignore your higher level enable-link function and simply use the lower-level C++ bindings to AbletonLink_ctor, AbletonLink_enable, and so on directly, once you had added bindings for requestBeatAtTime and forceBeatAtTime.

But, as you say, the license prevents me from doing that (if I was selling a product, or giving away a compiled executable, I would be able to make arrangements with Ableton, but as I am building free libraries and development platforms for other people to create things with, I can’t). Which is why I built Carabiner, and I can simply continue using it.

I need to add the new stop sync features there as well, when I have some time. Enjoy your gig, what kind of music do you play? I was just invited to the Ever After music festival in Canada to finally see people using my Beat Link Trigger on a big stage next month! 😄

@brunchboy
Copy link
Author

When you are back and working on this, I’m happy to report that it was pretty easy to add start/stop sync support to Carabiner. Most of the work came from the fact that Ableton changed the Link API in a backwards-incompatible way, so all code that used to refer to the Timeline needed to be changed to refer to the SessionState instead. So you’ll need to make changes throughout the C++ bindings, but that will be a good opportunity to expose the full API within Clojure as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants