#pragma once
#define LINK_AUDIO YES
#include <ableton/link_audio/ApiConfig.hpp>
#include <memory>
#include <optional>
#include <string>
#include <vector>
namespace ableton
{
template <typename Clock>
class BasicLinkAudio : public BasicLink<Clock>
{
public:
BasicLinkAudio(double bpm, std::string name);
~BasicLinkAudio();
bool isLinkAudioEnabled() const;
void enableLinkAudio(bool bEnable);
std::string peerName() const;
void setPeerName(std::string name);
template <typename Callback>
void setChannelsChangedCallback(Callback callback);
struct Channel
{
ChannelId id;
std::string name;
PeerId peerId;
std::string peerName;
};
std::vector<Channel> channels() const;
template <typename Function>
void callOnLinkThread(Function func);
private:
using Controller = ableton::link::ApiController<Clock>;
link_audio::ChannelsChangedCallback mChannelsChangedCallback = []() {};
};
class LinkAudio : public BasicLinkAudio<link::platform::Clock>
{
public:
using Clock = link::platform::Clock;
LinkAudio(double bpm, std::string name)
: BasicLinkAudio<Clock>(bpm, name)
{
}
private:
friend class LinkAudioSink;
friend class LinkAudioSource;
};
class LinkAudioSink
{
public:
template <typename LinkAudio>
LinkAudioSink(LinkAudio& link, std::string name, size_t maxNumSamples);
LinkAudioSink(const LinkAudioSink&) = default;
LinkAudioSink& operator=(const LinkAudioSink&) = default;
LinkAudioSink(LinkAudioSink&&) = default;
LinkAudioSink& operator=(LinkAudioSink&&) = default;
std::string name() const;
void setName(std::string name);
void requestMaxNumSamples(size_t numSamples);
size_t maxNumSamples() const;
struct BufferHandle
{
BufferHandle(LinkAudioSink&);
BufferHandle(const BufferHandle&) = delete;
BufferHandle(BufferHandle&& other) = delete;
BufferHandle& operator=(const BufferHandle&) = delete;
BufferHandle& operator=(BufferHandle&& other) = delete;
~BufferHandle();
operator bool() const;
int16_t* samples;
size_t maxNumSamples;
template <typename SessionState>
bool commit(const SessionState&,
double beatsAtBufferBegin,
double quantum,
size_t numFrames,
size_t numChannels,
uint32_t sampleRate);
private:
std::weak_ptr<link_audio::Sink> mpSink;
link_audio::Buffer<int16_t>* mpBuffer;
};
private:
friend struct BufferHandle;
std::shared_ptr<link_audio::Sink> mpImpl;
};
class LinkAudioSource
{
public:
struct BufferHandle;
template <typename LinkAudio, typename Callback>
LinkAudioSource(LinkAudio& link, ChannelId id, Callback callback);
LinkAudioSource(const LinkAudioSource&) = default;
LinkAudioSource& operator=(const LinkAudioSource&) = default;
LinkAudioSource(LinkAudioSource&&) = default;
LinkAudioSource& operator=(LinkAudioSource&&) = default;
~LinkAudioSource();
ChannelId id() const;
struct BufferHandle
{
struct Info
{
size_t numChannels;
size_t numFrames;
uint32_t sampleRate;
uint64_t count;
double sessionBeatTime;
double tempo;
SessionId sessionId;
template <typename SessionState>
std::optional<double> beginBeats(const SessionState&, double quantum) const;
template <typename SessionState>
std::optional<double> endBeats(const SessionState&, double quantum) const;
};
int16_t* samples;
Info info;
};
private:
std::shared_ptr<link_audio::Source> mpImpl;
};
}
#include <ableton/LinkAudio.ipp>