diff --git a/CMakeLists.txt b/CMakeLists.txt
index 65363d2..913942c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,6 +19,7 @@ option(TALCS_FORMAT "Build talcs::Format library" ON)
option(TALCS_MIDI "Build talcs::Midi library" ON)
option(TALCS_REMOTE "Build talcs::Remote library" ON)
option(TALCS_JUCE_ADAPTER "Build talcs::JuceAdapter library" OFF)
+option(TALCS_DSPX "Build talcs::Dspx library" OFF)
# ----------------------------------
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 851a46e..e7b1622 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -127,6 +127,10 @@ if(TALCS_JUCE_ADAPTER)
add_subdirectory(juceadapter)
endif()
+if(TALCS_DSPX)
+ add_subdirectory(dspx)
+endif()
+
if(TALCS_INSTALL)
# Add install target
set(_install_dir ${CMAKE_INSTALL_LIBDIR}/cmake/${TALCS_INSTALL_NAME})
diff --git a/src/dspx/CMakeLists.txt b/src/dspx/CMakeLists.txt
new file mode 100644
index 0000000..8eb7179
--- /dev/null
+++ b/src/dspx/CMakeLists.txt
@@ -0,0 +1,9 @@
+project(TalcsDspx VERSION ${TALCS_VERSION} LANGUAGES CXX)
+
+file(GLOB_RECURSE _src *.h *.cpp)
+
+talcs_add_library(${PROJECT_NAME} AUTOGEN
+ SOURCES ${_src}
+ LINKS talcs::Core talcs::Format
+ QT_INCLUDE_PRIVATE Core
+)
diff --git a/src/dspx/DspxAudioClipContext.cpp b/src/dspx/DspxAudioClipContext.cpp
new file mode 100644
index 0000000..f616284
--- /dev/null
+++ b/src/dspx/DspxAudioClipContext.cpp
@@ -0,0 +1,178 @@
+/******************************************************************************
+ * Copyright (c) 2024 CrSjimo *
+ * *
+ * This file is part of TALCS. *
+ * *
+ * TALCS is free software: you can redistribute it and/or modify it under the *
+ * terms of the GNU Lesser General Public License as published by the Free *
+ * Software Foundation, either version 3 of the License, or (at your option) *
+ * any later version. *
+ * *
+ * TALCS is distributed in the hope that it will be useful, but WITHOUT ANY *
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for *
+ * more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public License *
+ * along with TALCS. If not, see . *
+ ******************************************************************************/
+
+#include "DspxAudioClipContext.h"
+#include "DspxAudioClipContext_p.h"
+
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+namespace talcs {
+
+ DspxAudioClipContext::DspxAudioClipContext(DspxTrackContext *trackContext) : QObject(trackContext), d_ptr(new DspxAudioClipContextPrivate) {
+ Q_D(DspxAudioClipContext);
+ d->q_ptr = this;
+
+ d->controlMixer = std::make_unique();
+ d->clipMixer = std::make_unique();
+
+ d->controlMixer->addSource(d->clipMixer.get());
+
+ d->trackContext = trackContext;
+ }
+
+ DspxAudioClipContext::~DspxAudioClipContext() {
+
+ }
+
+ PositionableMixerAudioSource *DspxAudioClipContext::controlMixer() const {
+ Q_D(const DspxAudioClipContext);
+ return d->controlMixer.get();
+ }
+
+ PositionableMixerAudioSource *DspxAudioClipContext::clipMixer() const {
+ Q_D(const DspxAudioClipContext);
+ return d->clipMixer.get();
+ }
+
+ BufferingAudioSource *DspxAudioClipContext::contentSource() const {
+ Q_D(const DspxAudioClipContext);
+ return d->contentSource.get();
+ }
+
+ DspxTrackContext *DspxAudioClipContext::trackContext() const {
+ Q_D(const DspxAudioClipContext);
+ return d->trackContext;
+ }
+
+ void DspxAudioClipContext::setStart(int tick) {
+ Q_D(DspxAudioClipContext);
+ if (d->startTick != tick) {
+ d->startTick = tick;
+ updatePosition();
+ }
+ }
+
+ int DspxAudioClipContext::start() const {
+ Q_D(const DspxAudioClipContext);
+ return d->startTick;
+ }
+
+ void DspxAudioClipContext::setClipStart(int tick) {
+ Q_D(DspxAudioClipContext);
+ if (d->clipStartTick != tick) {
+ d->clipStartTick = tick;
+ updatePosition();
+ }
+ }
+
+ int DspxAudioClipContext::clipStart() const {
+ Q_D(const DspxAudioClipContext);
+ return d->clipStartTick;
+ }
+
+ void DspxAudioClipContext::setClipLen(int tick) {
+ Q_D(DspxAudioClipContext);
+ if (d->clipLenTick != tick) {
+ d->clipLenTick = tick;
+ updatePosition();
+ }
+ }
+
+ int DspxAudioClipContext::clipLen() const {
+ Q_D(const DspxAudioClipContext);
+ return d->clipLenTick;
+ }
+
+ void DspxAudioClipContextPrivate::handleIO(AbstractAudioFormatIO *io) {
+ auto rawSource_ = std::make_unique(io, true);
+ if (contentSource)
+ clipMixer->removeSource(contentSource.get());
+ contentSource.reset(trackContext->projectContext()->makeBufferable(rawSource_.get(), 2));
+ rawSource = std::move(rawSource_);
+ clipMixer->prependSource(contentSource.get());
+ }
+
+ bool DspxAudioClipContext::setPathLoad(const QString &path, const QVariant &data) {
+ Q_D(DspxAudioClipContext);
+ auto formatManager = d->trackContext->projectContext()->formatManager();
+ if (!formatManager)
+ return false;
+ auto io = formatManager->getFormatLoad(path, data);
+ if (!io)
+ return false;
+ d->handleIO(io);
+ d->path = path;
+ return true;
+ }
+
+ bool DspxAudioClipContext::setPathOpen(const QString &path, const QString &filter, QVariant &data) {
+ Q_D(DspxAudioClipContext);
+ auto formatManager = d->trackContext->projectContext()->formatManager();
+ if (!formatManager)
+ return false;
+ AbstractAudioFormatIO *io = nullptr;
+ for (auto entry : formatManager->entries()) {
+ if (filter.isEmpty() || entry->filters().contains(filter)) {
+ io = entry->getFormatLoad(path, data);
+ if (io)
+ break;
+ }
+ }
+ if (!io)
+ return false;
+ d->handleIO(io);
+ d->path = path;
+ return true;
+ }
+
+ QString DspxAudioClipContext::path() const {
+ Q_D(const DspxAudioClipContext);
+ return d->path;
+ }
+
+ void DspxAudioClipContext::updatePosition() {
+ Q_D(DspxAudioClipContext);
+ auto clipSeries = d->trackContext->clipSeries();
+ auto convertTime = d->trackContext->projectContext()->timeConverter();
+ auto startSample = convertTime(d->clipStartTick);
+ clipSeries->setClipStartPos(d->clipView, startSample);
+ auto firstSample = convertTime(d->startTick + d->clipStartTick);
+ auto lastSample = convertTime(d->startTick + d->clipStartTick + d->clipLenTick);
+ clipSeries->setClipRange(d->clipView, firstSample, qMax(qint64(1), lastSample - firstSample));
+ }
+
+ void DspxAudioClipContext::setData(const QVariant &data) {
+ Q_D(DspxAudioClipContext);
+ d->data = data;
+ }
+
+ QVariant DspxAudioClipContext::data() const {
+ Q_D(const DspxAudioClipContext);
+ return d->data;
+ }
+
+} // talcs
\ No newline at end of file
diff --git a/src/dspx/DspxAudioClipContext.h b/src/dspx/DspxAudioClipContext.h
new file mode 100644
index 0000000..1bafde7
--- /dev/null
+++ b/src/dspx/DspxAudioClipContext.h
@@ -0,0 +1,76 @@
+/******************************************************************************
+ * Copyright (c) 2024 CrSjimo *
+ * *
+ * This file is part of TALCS. *
+ * *
+ * TALCS is free software: you can redistribute it and/or modify it under the *
+ * terms of the GNU Lesser General Public License as published by the Free *
+ * Software Foundation, either version 3 of the License, or (at your option) *
+ * any later version. *
+ * *
+ * TALCS is distributed in the hope that it will be useful, but WITHOUT ANY *
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for *
+ * more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public License *
+ * along with TALCS. If not, see . *
+ ******************************************************************************/
+
+#ifndef TALCS_DSPXAUDIOCLIPCONTEXT_H
+#define TALCS_DSPXAUDIOCLIPCONTEXT_H
+
+#include
+#include
+
+#include
+
+namespace talcs {
+
+ class PositionableMixerAudioSource;
+ class BufferingAudioSource;
+
+ class DspxTrackContext;
+
+ class DspxAudioClipContextPrivate;
+
+ class TALCSDSPX_EXPORT DspxAudioClipContext : public QObject {
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(DspxAudioClipContext)
+ friend class DspxTrackContext;
+ public:
+ explicit DspxAudioClipContext(DspxTrackContext *trackContext);
+ ~DspxAudioClipContext() override;
+
+ PositionableMixerAudioSource *controlMixer() const;
+ PositionableMixerAudioSource *clipMixer() const;
+ BufferingAudioSource *contentSource() const;
+
+ DspxTrackContext *trackContext() const;
+
+ void setStart(int tick);
+ int start() const;
+
+ void setClipStart(int tick);
+ int clipStart() const;
+
+ void setClipLen(int tick);
+ int clipLen() const;
+
+ bool setPathLoad(const QString &path, const QVariant &data = {});
+ bool setPathOpen(const QString &path, const QString &selectedFilter, QVariant &data);
+ QString path() const;
+
+ void updatePosition();
+
+ void setData(const QVariant &data);
+ QVariant data() const;
+
+ private:
+ QScopedPointer d_ptr;
+
+ };
+
+} // talcs
+
+#endif //TALCS_DSPXAUDIOCLIPCONTEXT_H
diff --git a/src/dspx/DspxAudioClipContext_p.h b/src/dspx/DspxAudioClipContext_p.h
new file mode 100644
index 0000000..98cc1f5
--- /dev/null
+++ b/src/dspx/DspxAudioClipContext_p.h
@@ -0,0 +1,59 @@
+/******************************************************************************
+ * Copyright (c) 2024 CrSjimo *
+ * *
+ * This file is part of TALCS. *
+ * *
+ * TALCS is free software: you can redistribute it and/or modify it under the *
+ * terms of the GNU Lesser General Public License as published by the Free *
+ * Software Foundation, either version 3 of the License, or (at your option) *
+ * any later version. *
+ * *
+ * TALCS is distributed in the hope that it will be useful, but WITHOUT ANY *
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for *
+ * more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public License *
+ * along with TALCS. If not, see . *
+ ******************************************************************************/
+
+#ifndef TALCS_DSPXAUDIOCLIPCONTEXT_P_H
+#define TALCS_DSPXAUDIOCLIPCONTEXT_P_H
+
+#include
+
+#include
+
+#include
+
+namespace talcs {
+
+ class AbstractAudioFormatIO;
+
+ class DspxAudioClipContextPrivate {
+ Q_DECLARE_PUBLIC(DspxAudioClipContext);
+ public:
+ DspxAudioClipContext *q_ptr;
+
+ std::unique_ptr rawSource;
+ std::unique_ptr contentSource;
+ std::unique_ptr clipMixer;
+ std::unique_ptr controlMixer;
+
+ DspxTrackContext *trackContext;
+
+ AudioSourceClipSeries::ClipView clipView;
+
+ int startTick = 0;
+ int clipStartTick = 0;
+ int clipLenTick = 0;
+ QString path;
+
+ QVariant data;
+
+ void handleIO(AbstractAudioFormatIO *io);
+
+ };
+}
+
+#endif //TALCS_DSPXAUDIOCLIPCONTEXT_P_H
diff --git a/src/dspx/DspxProjectContext.cpp b/src/dspx/DspxProjectContext.cpp
new file mode 100644
index 0000000..8b6391c
--- /dev/null
+++ b/src/dspx/DspxProjectContext.cpp
@@ -0,0 +1,170 @@
+/******************************************************************************
+ * Copyright (c) 2024 CrSjimo *
+ * *
+ * This file is part of TALCS. *
+ * *
+ * TALCS is free software: you can redistribute it and/or modify it under the *
+ * terms of the GNU Lesser General Public License as published by the Free *
+ * Software Foundation, either version 3 of the License, or (at your option) *
+ * any later version. *
+ * *
+ * TALCS is distributed in the hope that it will be useful, but WITHOUT ANY *
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for *
+ * more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public License *
+ * along with TALCS. If not, see . *
+ ******************************************************************************/
+
+#include "DspxProjectContext.h"
+#include "DspxProjectContext_p.h"
+
+#include
+#include
+#include
+
+#include
+
+namespace talcs {
+
+ DspxProjectContextBufferingAudioSourceObject::DspxProjectContextBufferingAudioSourceObject(PositionableAudioSource *src, int channelCount, qint64 readAheadSize, QObject *parent)
+ : QObject(parent), BufferingAudioSource(src, channelCount, readAheadSize) {
+ }
+
+ DspxProjectContextBufferingAudioSourceObject::~DspxProjectContextBufferingAudioSourceObject() = default;
+
+ DspxProjectContext::DspxProjectContext(QObject *parent) : QObject(parent), d_ptr(new DspxProjectContextPrivate) {
+ Q_D(DspxProjectContext);
+ d->q_ptr = this;
+
+ d->preMixer = std::make_unique();
+ d->transport = std::make_unique();
+ d->postMixer = std::make_unique();
+ d->masterControlMixer = std::make_unique();
+ d->masterTrackMixer = std::make_unique();
+
+ d->masterControlMixer->addSource(d->masterTrackMixer.get());
+ d->postMixer->addSource(d->masterControlMixer.get());
+ d->transport->setSource(d->postMixer.get());
+ d->preMixer->addSource(d->transport.get());
+ }
+
+ DspxProjectContext::~DspxProjectContext() = default;
+
+ MixerAudioSource *DspxProjectContext::preMixer() const {
+ Q_D(const DspxProjectContext);
+ return d->preMixer.get();
+ }
+
+ TransportAudioSource *DspxProjectContext::transport() const {
+ Q_D(const DspxProjectContext);
+ return d->transport.get();
+ }
+
+ PositionableMixerAudioSource *DspxProjectContext::postMixer() const {
+ Q_D(const DspxProjectContext);
+ return d->postMixer.get();
+ }
+
+ PositionableMixerAudioSource *DspxProjectContext::masterControlMixer() const {
+ Q_D(const DspxProjectContext);
+ return d->masterControlMixer.get();
+ }
+
+ PositionableMixerAudioSource *DspxProjectContext::masterTrackMixer() const {
+ Q_D(const DspxProjectContext);
+ return d->masterTrackMixer.get();
+ }
+
+ void DspxProjectContext::setFormatManager(FormatManager *formatManager) {
+ Q_D(DspxProjectContext);
+ d->formatManager = formatManager;
+ }
+
+ FormatManager *DspxProjectContext::formatManager() const {
+ Q_D(const DspxProjectContext);
+ return d->formatManager;
+ }
+
+ void DspxProjectContext::setTimeConverter(const std::function &converter) {
+ Q_D(DspxProjectContext);
+ d->timeConverter = converter;
+ }
+
+ std::function DspxProjectContext::timeConverter() const {
+ Q_D(const DspxProjectContext);
+ return d->timeConverter;
+ }
+
+ void DspxProjectContext::setBufferingReadAheadSize(qint64 size) {
+ Q_D(DspxProjectContext);
+ if (size != d->bufferingReadAheadSize) {
+ d->bufferingReadAheadSize = size;
+ emit d->readAheadSizeChanged(size);
+ }
+ }
+
+ qint64 DspxProjectContext::bufferingReadAheadSize() const {
+ Q_D(const DspxProjectContext);
+ return d->bufferingReadAheadSize;
+ }
+
+ BufferingAudioSource *DspxProjectContext::makeBufferable(PositionableAudioSource *source, int channelCount) {
+ Q_D(DspxProjectContext);
+ auto bufSrc = new DspxProjectContextBufferingAudioSourceObject(source, channelCount, d->bufferingReadAheadSize);
+ connect(d, &DspxProjectContextPrivate::readAheadSizeChanged, bufSrc, [bufSrc](qint64 size) {
+ bufSrc->setReadAheadSize(size);
+ });
+ return bufSrc;
+ }
+
+ DspxTrackContext *DspxProjectContext::addTrack(int index) {
+ Q_D(DspxProjectContext);
+ Q_ASSERT(index >= 0 && index <= d->tracks.size());
+ auto track = new DspxTrackContext(this);
+ d->tracks.insert(index, track);
+ d->masterTrackMixer->insertSource(d->masterTrackMixer->sourceAt(index), track->controlMixer());
+ return track;
+ }
+
+ void DspxProjectContext::removeTrack(int index) {
+ Q_D(DspxProjectContext);
+ Q_ASSERT(index >= 0 && index < d->tracks.size());
+ auto track = d->tracks.at(index);
+ d->tracks.removeAt(index);
+ d->masterTrackMixer->removeSource(track->controlMixer());
+ delete track;
+ }
+
+ void DspxProjectContext::moveTrack(int index, int count, int dest) {
+ Q_D(DspxProjectContext);
+ Q_ASSERT(index >= 0 && index < d->tracks.size() && count > 0 && index + count <= d->tracks.size() && dest >= 0 && dest <= d->tracks.size());
+
+ QVector tmp;
+ tmp.resize(count);
+ std::copy(d->tracks.begin() + index, d->tracks.begin() + index + count, tmp.begin());
+ int correctDest;
+ if (dest > index) {
+ correctDest = dest - count;
+ auto sz = correctDest - index;
+ for (int i = 0; i < sz; ++i) {
+ d->tracks[index + i] = d->tracks[index + count + i];
+ }
+ } else {
+ correctDest = dest;
+ auto sz = index - dest;
+ for (int i = sz - 1; i >= 0; --i) {
+ d->tracks[dest + count + i] = d->tracks[dest + i];
+ }
+ }
+ std::copy(tmp.begin(), tmp.end(), d->tracks.begin() + correctDest);
+
+ d->masterTrackMixer->moveSource(d->masterTrackMixer->sourceAt(dest), d->masterTrackMixer->sourceAt(index), d->masterTrackMixer->sourceAt(index + count));
+ }
+
+ QList DspxProjectContext::tracks() const {
+ Q_D(const DspxProjectContext);
+ return d->tracks;
+ }
+}
\ No newline at end of file
diff --git a/src/dspx/DspxProjectContext.h b/src/dspx/DspxProjectContext.h
new file mode 100644
index 0000000..e52218a
--- /dev/null
+++ b/src/dspx/DspxProjectContext.h
@@ -0,0 +1,78 @@
+/******************************************************************************
+ * Copyright (c) 2024 CrSjimo *
+ * *
+ * This file is part of TALCS. *
+ * *
+ * TALCS is free software: you can redistribute it and/or modify it under the *
+ * terms of the GNU Lesser General Public License as published by the Free *
+ * Software Foundation, either version 3 of the License, or (at your option) *
+ * any later version. *
+ * *
+ * TALCS is distributed in the hope that it will be useful, but WITHOUT ANY *
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for *
+ * more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public License *
+ * along with TALCS. If not, see . *
+ ******************************************************************************/
+
+#ifndef TALCS_DSPXPROJECTCONTEXT_H
+#define TALCS_DSPXPROJECTCONTEXT_H
+
+#include
+
+#include
+
+#include
+
+namespace talcs {
+
+ class MixerAudioSource;
+ class TransportAudioSource;
+ class PositionableMixerAudioSource;
+ class PositionableAudioSource;
+ class BufferingAudioSource;
+
+ class FormatManager;
+
+ class DspxTrackContext;
+
+ class DspxProjectContextPrivate;
+
+ class TALCSDSPX_EXPORT DspxProjectContext : public QObject {
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(DspxProjectContext)
+ public:
+ explicit DspxProjectContext(QObject *parent = nullptr);
+ ~DspxProjectContext() override;
+
+ MixerAudioSource *preMixer() const;
+ TransportAudioSource *transport() const;
+ PositionableMixerAudioSource *postMixer() const;
+ PositionableMixerAudioSource *masterControlMixer() const;
+ PositionableMixerAudioSource *masterTrackMixer() const;
+
+ void setFormatManager(FormatManager *formatManager);
+ FormatManager *formatManager() const;
+
+ void setTimeConverter(const std::function &converter);
+ std::function timeConverter() const;
+
+ void setBufferingReadAheadSize(qint64 size);
+ qint64 bufferingReadAheadSize() const;
+ BufferingAudioSource *makeBufferable(PositionableAudioSource *source, int channelCount);
+
+ DspxTrackContext *addTrack(int index);
+ void removeTrack(int index);
+ void moveTrack(int index, int count, int dest);
+
+ QList tracks() const;
+
+ private:
+ QScopedPointer d_ptr;
+ };
+
+} // talcs
+
+#endif //TALCS_DSPXPROJECTCONTEXT_H
diff --git a/src/dspx/DspxProjectContext_p.h b/src/dspx/DspxProjectContext_p.h
new file mode 100644
index 0000000..453a6cd
--- /dev/null
+++ b/src/dspx/DspxProjectContext_p.h
@@ -0,0 +1,61 @@
+/******************************************************************************
+ * Copyright (c) 2024 CrSjimo *
+ * *
+ * This file is part of TALCS. *
+ * *
+ * TALCS is free software: you can redistribute it and/or modify it under the *
+ * terms of the GNU Lesser General Public License as published by the Free *
+ * Software Foundation, either version 3 of the License, or (at your option) *
+ * any later version. *
+ * *
+ * TALCS is distributed in the hope that it will be useful, but WITHOUT ANY *
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for *
+ * more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public License *
+ * along with TALCS. If not, see . *
+ ******************************************************************************/
+
+#ifndef TALCS_DSPXPROJECTCONTEXT_P_H
+#define TALCS_DSPXPROJECTCONTEXT_P_H
+
+#include
+
+#include
+
+#include
+
+namespace talcs {
+
+ class DspxProjectContextBufferingAudioSourceObject : public QObject, public BufferingAudioSource {
+ Q_OBJECT
+ public:
+ explicit DspxProjectContextBufferingAudioSourceObject(PositionableAudioSource *src, int channelCount, qint64 readAheadSize, QObject *parent = nullptr);
+ ~DspxProjectContextBufferingAudioSourceObject() override;
+ };
+
+ class DspxProjectContextPrivate : public QObject {
+ Q_OBJECT
+ Q_DECLARE_PUBLIC(DspxProjectContext);
+ public:
+ DspxProjectContext *q_ptr;
+
+ std::unique_ptr masterTrackMixer;
+ std::unique_ptr masterControlMixer;
+ std::unique_ptr postMixer;
+ std::unique_ptr transport;
+ std::unique_ptr preMixer;
+
+ FormatManager *formatManager = nullptr;
+ std::function timeConverter = [](int) { return 0; };
+ qint64 bufferingReadAheadSize = 0;
+
+ QList tracks;
+
+ signals:
+ void readAheadSizeChanged(qint64 readAheadSize);
+ };
+}
+
+#endif //TALCS_DSPXPROJECTCONTEXT_P_H
diff --git a/src/dspx/DspxTrackContext.cpp b/src/dspx/DspxTrackContext.cpp
new file mode 100644
index 0000000..737efee
--- /dev/null
+++ b/src/dspx/DspxTrackContext.cpp
@@ -0,0 +1,104 @@
+/******************************************************************************
+ * Copyright (c) 2024 CrSjimo *
+ * *
+ * This file is part of TALCS. *
+ * *
+ * TALCS is free software: you can redistribute it and/or modify it under the *
+ * terms of the GNU Lesser General Public License as published by the Free *
+ * Software Foundation, either version 3 of the License, or (at your option) *
+ * any later version. *
+ * *
+ * TALCS is distributed in the hope that it will be useful, but WITHOUT ANY *
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for *
+ * more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public License *
+ * along with TALCS. If not, see . *
+ ******************************************************************************/
+
+#include "DspxTrackContext.h"
+#include "DspxTrackContext_p.h"
+
+#include
+
+#include
+#include
+#include
+
+namespace talcs {
+ DspxTrackContext::DspxTrackContext(DspxProjectContext *projectContext) : QObject(projectContext), d_ptr(new DspxTrackContextPrivate) {
+ Q_D(DspxTrackContext);
+ d->q_ptr = this;
+
+ d->controlMixer = std::make_unique();
+ d->trackMixer = std::make_unique();
+ d->clipSeries = std::make_unique();
+
+ d->trackMixer->addSource(d->clipSeries.get());
+ d->controlMixer->addSource(d->trackMixer.get());
+
+ d->projectContext = projectContext;
+ }
+
+ DspxTrackContext::~DspxTrackContext() {
+
+ }
+
+ PositionableMixerAudioSource *DspxTrackContext::controlMixer() const {
+ Q_D(const DspxTrackContext);
+ return d->controlMixer.get();
+ }
+
+ PositionableMixerAudioSource *DspxTrackContext::trackMixer() const {
+ Q_D(const DspxTrackContext);
+ return d->trackMixer.get();
+ }
+
+ AudioSourceClipSeries *DspxTrackContext::clipSeries() const {
+ Q_D(const DspxTrackContext);
+ return d->clipSeries.get();
+ }
+
+ DspxProjectContext *DspxTrackContext::projectContext() const {
+ Q_D(const DspxTrackContext);
+ return d->projectContext;
+ }
+
+ void DspxTrackContext::setData(const QVariant &data) {
+ Q_D(DspxTrackContext);
+ d->data = data;
+ }
+
+ QVariant DspxTrackContext::data() const {
+ Q_D(const DspxTrackContext);
+ return d->data;
+ }
+
+ DspxAudioClipContext *DspxTrackContext::addAudioClip(int id) {
+ Q_D(DspxTrackContext);
+ auto clip = new DspxAudioClipContext(this);
+ auto clipView = d->clipSeries->insertClip(clip->controlMixer(), 0, 0, 1);
+ d->clips.insert(id, {clip, clipView});
+ clip->d_func()->clipView = clipView;
+ return clip;
+ }
+
+ void DspxTrackContext::removeAudioClip(int id) {
+ Q_D(DspxTrackContext);
+ Q_ASSERT(d->clips.contains(id));
+ auto clip = d->clips.value(id);
+ d->clips.remove(id);
+ d->clipSeries->removeClip(clip.second);
+ }
+
+ QList DspxTrackContext::clips() const {
+ Q_D(const DspxTrackContext);
+ QList list;
+ list.reserve(d->clips.size());
+ for (const auto &[clip, _] : d->clips.values()) {
+ list.append(clip);
+ }
+ return list;
+ }
+} // talcs
\ No newline at end of file
diff --git a/src/dspx/DspxTrackContext.h b/src/dspx/DspxTrackContext.h
new file mode 100644
index 0000000..9e3d74d
--- /dev/null
+++ b/src/dspx/DspxTrackContext.h
@@ -0,0 +1,64 @@
+/******************************************************************************
+ * Copyright (c) 2024 CrSjimo *
+ * *
+ * This file is part of TALCS. *
+ * *
+ * TALCS is free software: you can redistribute it and/or modify it under the *
+ * terms of the GNU Lesser General Public License as published by the Free *
+ * Software Foundation, either version 3 of the License, or (at your option) *
+ * any later version. *
+ * *
+ * TALCS is distributed in the hope that it will be useful, but WITHOUT ANY *
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for *
+ * more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public License *
+ * along with TALCS. If not, see . *
+ ******************************************************************************/
+
+#ifndef TALCS_DSPXTRACKCONTEXT_H
+#define TALCS_DSPXTRACKCONTEXT_H
+
+#include
+
+#include
+
+namespace talcs {
+
+ class PositionableMixerAudioSource;
+ class AudioSourceClipSeries;
+
+ class DspxProjectContext;
+ class DspxAudioClipContext;
+
+ class DspxTrackContextPrivate;
+
+ class TALCSDSPX_EXPORT DspxTrackContext : public QObject {
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(DspxTrackContext)
+ public:
+ explicit DspxTrackContext(DspxProjectContext *projectContext);
+ ~DspxTrackContext() override;
+
+ PositionableMixerAudioSource *controlMixer() const;
+ PositionableMixerAudioSource *trackMixer() const;
+ AudioSourceClipSeries *clipSeries() const;
+
+ DspxProjectContext *projectContext() const;
+
+ void setData(const QVariant &data);
+ QVariant data() const;
+
+ DspxAudioClipContext *addAudioClip(int id);
+ void removeAudioClip(int id);
+
+ QList clips() const;
+
+ private:
+ QScopedPointer d_ptr;
+ };
+
+} // talcs
+
+#endif //TALCS_DSPXTRACKCONTEXT_H
diff --git a/src/dspx/DspxTrackContext_p.h b/src/dspx/DspxTrackContext_p.h
new file mode 100644
index 0000000..3c8df07
--- /dev/null
+++ b/src/dspx/DspxTrackContext_p.h
@@ -0,0 +1,50 @@
+/******************************************************************************
+ * Copyright (c) 2024 CrSjimo *
+ * *
+ * This file is part of TALCS. *
+ * *
+ * TALCS is free software: you can redistribute it and/or modify it under the *
+ * terms of the GNU Lesser General Public License as published by the Free *
+ * Software Foundation, either version 3 of the License, or (at your option) *
+ * any later version. *
+ * *
+ * TALCS is distributed in the hope that it will be useful, but WITHOUT ANY *
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for *
+ * more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public License *
+ * along with TALCS. If not, see . *
+ ******************************************************************************/
+
+#ifndef TALCS_DSPXTRACKCONTEXT_P_H
+#define TALCS_DSPXTRACKCONTEXT_P_H
+
+#include
+
+#include
+
+#include
+
+#include
+
+namespace talcs {
+ class DspxTrackContextPrivate {
+ Q_DECLARE_PUBLIC(DspxTrackContext)
+ public:
+ DspxTrackContext *q_ptr;
+
+ std::unique_ptr clipSeries;
+ std::unique_ptr trackMixer;
+ std::unique_ptr controlMixer;
+
+ DspxProjectContext *projectContext = nullptr;
+
+ QVariant data;
+
+ QMap> clips;
+
+ };
+}
+
+#endif //TALCS_DSPXTRACKCONTEXT_P_H
diff --git a/src/dspx/TalcsDspxGlobal.h b/src/dspx/TalcsDspxGlobal.h
new file mode 100644
index 0000000..4d369f5
--- /dev/null
+++ b/src/dspx/TalcsDspxGlobal.h
@@ -0,0 +1,37 @@
+/******************************************************************************
+ * Copyright (c) 2024 CrSjimo *
+ * *
+ * This file is part of TALCS. *
+ * *
+ * TALCS is free software: you can redistribute it and/or modify it under the *
+ * terms of the GNU Lesser General Public License as published by the Free *
+ * Software Foundation, either version 3 of the License, or (at your option) *
+ * any later version. *
+ * *
+ * TALCS is distributed in the hope that it will be useful, but WITHOUT ANY *
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for *
+ * more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public License *
+ * along with TALCS. If not, see . *
+ ******************************************************************************/
+
+#ifndef TALCS_TALCSDSPXGLOBAL_H
+#define TALCS_TALCSDSPXGLOBAL_H
+
+#include
+
+#ifndef TALCSDSPX_EXPORT
+# ifdef TALCSDSPX_STATIC
+# define TALCSDSPX_EXPORT
+# else
+# ifdef TALCSDSPX_LIBRARY
+# define TALCSDSPX_EXPORT Q_DECL_EXPORT
+# else
+# define TALCSDSPX_EXPORT Q_DECL_IMPORT
+# endif
+# endif
+#endif
+
+#endif //TALCS_TALCSDSPXGLOBAL_H