diff --git a/src/remote/CMakeLists.txt b/src/remote/CMakeLists.txt index 30bbfc8..0736c1e 100644 --- a/src/remote/CMakeLists.txt +++ b/src/remote/CMakeLists.txt @@ -7,7 +7,7 @@ find_package(rpclib REQUIRED) talcs_add_library(${PROJECT_NAME} AUTOGEN SOURCES ${_src} - LINKS talcs::Device rpclib::rpc + LINKS talcs::Device talcs::Midi rpclib::rpc LINKS_PRIVATE Boost::boost QT_INCLUDE_PRIVATE Core ) diff --git a/src/remote/RemoteAudioDevice.cpp b/src/remote/RemoteAudioDevice.cpp index 046b426..94c2edb 100644 --- a/src/remote/RemoteAudioDevice.cpp +++ b/src/remote/RemoteAudioDevice.cpp @@ -160,7 +160,7 @@ namespace talcs { } bufferPrepareStatus = reinterpret_cast(ptr); ptr += sizeof(bool); - processInfo = reinterpret_cast(ptr); + processInfo = reinterpret_cast(ptr); buffer.reset(new AudioDataWrapper(sharedAudioData.data(), maxChannelCount, bufferSize)); q->setAvailableBufferSizes({bufferSize}); @@ -259,7 +259,7 @@ namespace talcs { /** * Adds a ProcessInfoCallback. */ - void RemoteAudioDevice::addProcessInfoCallback(RemoteAudioDevice::ProcessInfoCallback *callback) { + void RemoteAudioDevice::addProcessInfoCallback(RemoteProcessInfoCallback *callback) { Q_D(RemoteAudioDevice); d->processInfoCallbackList.append(callback); } @@ -267,7 +267,7 @@ namespace talcs { /** * Removes a ProcessInfoCallback. */ - void RemoteAudioDevice::removeProcessInfoCallback(RemoteAudioDevice::ProcessInfoCallback *callback) { + void RemoteAudioDevice::removeProcessInfoCallback(RemoteProcessInfoCallback *callback) { Q_D(RemoteAudioDevice); d->processInfoCallbackList.removeOne(callback); } diff --git a/src/remote/RemoteAudioDevice.h b/src/remote/RemoteAudioDevice.h index 2942711..0da7d37 100644 --- a/src/remote/RemoteAudioDevice.h +++ b/src/remote/RemoteAudioDevice.h @@ -21,7 +21,7 @@ #define TALCS_REMOTEAUDIODEVICE_H #include -#include +#include namespace talcs { @@ -32,29 +32,6 @@ namespace talcs { Q_OBJECT Q_DECLARE_PRIVATE(RemoteAudioDevice) public: - struct ProcessInfo { - int containsInfo; - - //== Playback Status Info ==// - enum PlaybackStatus { - NotPlaying, - Playing, - RealtimePlaying, - }; - PlaybackStatus status; - - //== Timeline Info ==// - int timeSignatureNumerator; - int timeSignatureDenominator; - double tempo; - - int64_t position; - }; - - class ProcessInfoCallback { - public: - virtual void onThisBlockProcessInfo(const ProcessInfo &processInfo) = 0; - }; public: explicit RemoteAudioDevice(RemoteSocket *socket, const QString &name, QObject *parent = nullptr); @@ -63,8 +40,8 @@ namespace talcs { bool open(qint64 bufferSize, double sampleRate) override; void close() override; - void addProcessInfoCallback(ProcessInfoCallback *callback); - void removeProcessInfoCallback(ProcessInfoCallback *callback); + void addProcessInfoCallback(RemoteProcessInfoCallback *callback); + void removeProcessInfoCallback(RemoteProcessInfoCallback *callback); bool start(AudioDeviceCallback *audioDeviceCallback) override; void stop() override; diff --git a/src/remote/RemoteAudioDevice_p.h b/src/remote/RemoteAudioDevice_p.h index 1d49b12..2e63f58 100644 --- a/src/remote/RemoteAudioDevice_p.h +++ b/src/remote/RemoteAudioDevice_p.h @@ -53,14 +53,14 @@ namespace talcs { }; char *bufferPrepareStatus; QVector sharedAudioData; - RemoteAudioDevice::ProcessInfo *processInfo = nullptr; + RemoteProcessInfo *processInfo = nullptr; QScopedPointer buffer; QScopedPointer prepareBufferProducerThread; AudioDeviceCallback *audioDeviceCallback = nullptr; - QList processInfoCallbackList; + QList processInfoCallbackList; void remoteOpenRequired(qint64 bufferSize, double sampleRate, const QString &ipcKey, int maxChannelCount); void remoteCloseRequired(); diff --git a/src/remote/RemoteMidiMessageIntegrator.cpp b/src/remote/RemoteMidiMessageIntegrator.cpp new file mode 100644 index 0000000..4bcec04 --- /dev/null +++ b/src/remote/RemoteMidiMessageIntegrator.cpp @@ -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 . * + ******************************************************************************/ + +#include "RemoteMidiMessageIntegrator.h" +#include "RemoteMidiMessageIntegrator_p.h" + +namespace talcs { + RemoteMidiMessageIntegrator::RemoteMidiMessageIntegrator() : RemoteMidiMessageIntegrator(*new RemoteMidiMessageIntegratorPrivate) { + + } + + RemoteMidiMessageIntegrator::~RemoteMidiMessageIntegrator() { + + } + + bool RemoteMidiMessageIntegrator::open(qint64 bufferSize, double sampleRate) { + Q_D(RemoteMidiMessageIntegrator); + QMutexLocker locker(&d->mutex); + d->midiMessages.clear(); + return AbstractMidiMessageIntegrator::open(bufferSize, sampleRate); + } + + void RemoteMidiMessageIntegrator::close() { + Q_D(RemoteMidiMessageIntegrator); + QMutexLocker locker(&d->mutex); + d->midiMessages.clear(); + AbstractMidiMessageIntegrator::close(); + } + + QList RemoteMidiMessageIntegrator::fetch(qint64 length) { + Q_D(RemoteMidiMessageIntegrator); + QMutexLocker locker(&d->mutex); + auto ret = d->midiMessages; + d->midiMessages.clear(); + return ret; + } + + void RemoteMidiMessageIntegrator::onThisBlockProcessInfo(const RemoteProcessInfo &processInfo) { + Q_D(RemoteMidiMessageIntegrator); + QMutexLocker locker(&d->mutex); + d->midiMessages.clear(); + if (processInfo.containsInfo) { + auto midiMessagesRawData = &processInfo.midiMessages; + d->midiMessages.reserve(static_cast(midiMessagesRawData->size)); + auto midiMessagesRawDataPointer = reinterpret_cast(midiMessagesRawData->messages); + for (int i = 0; i < midiMessagesRawData->size; i++) { + auto midiMessageRawData = reinterpret_cast(midiMessagesRawDataPointer); + d->midiMessages.append({ + midiMessageRawData->position, + MidiMessage(midiMessageRawData->data, static_cast(midiMessageRawData->size), + static_cast(midiMessageRawData->position)) + }); + midiMessagesRawDataPointer+= sizeof(RemoteMidiMessage) + midiMessageRawData->size - 1; + } + } + } + + RemoteMidiMessageIntegrator::RemoteMidiMessageIntegrator(RemoteMidiMessageIntegratorPrivate &d) : AbstractMidiMessageIntegrator(d) { + } +} // talcs \ No newline at end of file diff --git a/src/remote/RemoteMidiMessageIntegrator.h b/src/remote/RemoteMidiMessageIntegrator.h new file mode 100644 index 0000000..63df59c --- /dev/null +++ b/src/remote/RemoteMidiMessageIntegrator.h @@ -0,0 +1,49 @@ +/****************************************************************************** + * 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_REMOTEMIDIMESSAGEINTEGRATOR_H +#define TALCS_REMOTEMIDIMESSAGEINTEGRATOR_H + +#include +#include + +namespace talcs { + + class RemoteMidiMessageIntegratorPrivate; + + class TALCSREMOTE_EXPORT RemoteMidiMessageIntegrator : public AbstractMidiMessageIntegrator, public RemoteProcessInfoCallback { + Q_DECLARE_PRIVATE(RemoteMidiMessageIntegrator) + public: + explicit RemoteMidiMessageIntegrator(); + ~RemoteMidiMessageIntegrator() override; + + bool open(qint64 bufferSize, double sampleRate) override; + void close() override; + + protected: + QList fetch(qint64 length) override; + void onThisBlockProcessInfo(const RemoteProcessInfo &processInfo) override; + + explicit RemoteMidiMessageIntegrator(RemoteMidiMessageIntegratorPrivate &d); + + }; + +} // talcs + +#endif //TALCS_REMOTEMIDIMESSAGEINTEGRATOR_H diff --git a/src/remote/RemoteMidiMessageIntegrator_p.h b/src/remote/RemoteMidiMessageIntegrator_p.h new file mode 100644 index 0000000..e75e5b9 --- /dev/null +++ b/src/remote/RemoteMidiMessageIntegrator_p.h @@ -0,0 +1,36 @@ +/****************************************************************************** + * 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_REMOTEMIDIMESSAGEINTEGRATOR_P_H +#define TALCS_REMOTEMIDIMESSAGEINTEGRATOR_P_H + +#include + +#include + +namespace talcs { + class RemoteMidiMessageIntegratorPrivate : public AbstractMidiMessageIntegratorPrivate { + Q_DECLARE_PUBLIC(RemoteMidiMessageIntegrator) + public: + QList midiMessages; + QMutex mutex; + }; +} + +#endif //TALCS_REMOTEMIDIMESSAGEINTEGRATOR_P_H diff --git a/src/remote/RemoteProcessInfo.h b/src/remote/RemoteProcessInfo.h new file mode 100644 index 0000000..5f6416f --- /dev/null +++ b/src/remote/RemoteProcessInfo.h @@ -0,0 +1,67 @@ +/****************************************************************************** + * 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_REMOTEPROCESSINFO_H +#define TALCS_REMOTEPROCESSINFO_H + +#include + +namespace talcs { + + struct RemoteMidiMessage { + int64_t size; + int64_t position; + char data[1]; + }; + + struct RemoteMidiMessageList { + int64_t size; + RemoteMidiMessage messages[1]; + }; + + struct RemoteProcessInfo { + int containsInfo; + + //== Playback Status Info ==// + enum PlaybackStatus { + NotPlaying, + Playing, + RealtimePlaying, + }; + PlaybackStatus status; + + //== Timeline Info ==// + int timeSignatureNumerator; + int timeSignatureDenominator; + double tempo; + + int64_t position; + + //== MIDI ==// + RemoteMidiMessageList midiMessages; + }; + + class RemoteProcessInfoCallback { + public: + virtual void onThisBlockProcessInfo(const RemoteProcessInfo &processInfo) = 0; + }; + +} + +#endif //TALCS_REMOTEPROCESSINFO_H diff --git a/src/remote/TransportAudioSourceProcessInfoCallback.cpp b/src/remote/TransportAudioSourceProcessInfoCallback.cpp index d0435e0..0baff70 100644 --- a/src/remote/TransportAudioSourceProcessInfoCallback.cpp +++ b/src/remote/TransportAudioSourceProcessInfoCallback.cpp @@ -42,8 +42,8 @@ namespace talcs { * - If the remote audio context is playing, the source will be played and the position will be synchronized with * the remote audio context. */ - void TransportAudioSourceProcessInfoCallback::onThisBlockProcessInfo(const RemoteAudioDevice::ProcessInfo &processInfo) { - if (processInfo.status == RemoteAudioDevice::ProcessInfo::NotPlaying) { + void TransportAudioSourceProcessInfoCallback::onThisBlockProcessInfo(const RemoteProcessInfo &processInfo) { + if (processInfo.status == RemoteProcessInfo::NotPlaying) { if (m_tpSrc->isPlaying() && !m_isPaused) m_tpSrc->pause(); m_isPaused = true; diff --git a/src/remote/TransportAudioSourceProcessInfoCallback.h b/src/remote/TransportAudioSourceProcessInfoCallback.h index 16e757c..aa5d374 100644 --- a/src/remote/TransportAudioSourceProcessInfoCallback.h +++ b/src/remote/TransportAudioSourceProcessInfoCallback.h @@ -26,10 +26,10 @@ namespace talcs { class TransportAudioSource; - class TALCSREMOTE_EXPORT TransportAudioSourceProcessInfoCallback : public RemoteAudioDevice::ProcessInfoCallback { + class TALCSREMOTE_EXPORT TransportAudioSourceProcessInfoCallback : public RemoteProcessInfoCallback { public: explicit TransportAudioSourceProcessInfoCallback(TransportAudioSource *tpSrc); - void onThisBlockProcessInfo(const RemoteAudioDevice::ProcessInfo &processInfo) override; + void onThisBlockProcessInfo(const RemoteProcessInfo &processInfo) override; private: TransportAudioSource *m_tpSrc;