feat: add WebsSocket API for mixer engine control
New files: - MixerApi.hpp/cpp: Model-level API bridging WebSocket messages to MixerEngine control (channel volume/pan/mute/solo/hpf, bus control, routing, state queries) - 15 new WebSocket message handlers in PiPedalSocket.cpp for full mixer control surface Integration: - MixerEngine member added to PiPedalModel with Get/Set accessors - SetMixerEngine propagates to AudioHost rt processing pipeline - Socket handler auto-wires MixerEngine to MixerApi on connect Messages implemented: mixerSetChannelVolume, mixerSetChannelPan, mixerSetChannelMute, mixerSetChannelSolo, mixerSetChannelLabel, mixerSetChannelHpf, mixerGetState, mixerAddChannel, mixerRemoveChannel, mixerSetBusVolume, mixerSetBusMute, mixerAddBus, mixerRemoveBus, mixerRouteChannelToBus
This commit is contained in:
@@ -373,6 +373,7 @@ set (PIPEDAL_SOURCES
|
||||
MixerChannelStrip.cpp MixerChannelStrip.hpp
|
||||
MixerBus.cpp MixerBus.hpp
|
||||
MixerEngine.cpp MixerEngine.hpp
|
||||
MixerApi.cpp MixerApi.hpp
|
||||
|
||||
${VST3_SOURCES}
|
||||
)
|
||||
|
||||
@@ -0,0 +1,252 @@
|
||||
// Copyright (c) 2026 Ourpad Network
|
||||
// See LICENSE file in the project root for full license text.
|
||||
|
||||
#include "pch.h"
|
||||
#include "MixerApi.hpp"
|
||||
#include "MixerEngine.hpp"
|
||||
#include "MixerChannelStrip.hpp"
|
||||
#include "MixerBus.hpp"
|
||||
#include "json.hpp"
|
||||
#include <sstream>
|
||||
|
||||
using namespace pipedal;
|
||||
|
||||
MixerApi::MixerApi()
|
||||
{
|
||||
}
|
||||
|
||||
MixerApi::~MixerApi()
|
||||
{
|
||||
}
|
||||
|
||||
void MixerApi::setChannelVolume(int channelIndex, float volumeDb)
|
||||
{
|
||||
if (!mixerEngine_) return;
|
||||
auto* channel = mixerEngine_->getChannel(channelIndex);
|
||||
if (channel) channel->setVolume(volumeDb);
|
||||
}
|
||||
|
||||
void MixerApi::setChannelPan(int channelIndex, float pan)
|
||||
{
|
||||
if (!mixerEngine_) return;
|
||||
auto* channel = mixerEngine_->getChannel(channelIndex);
|
||||
if (channel) channel->setPan(pan);
|
||||
}
|
||||
|
||||
void MixerApi::setChannelMute(int channelIndex, bool mute)
|
||||
{
|
||||
if (!mixerEngine_) return;
|
||||
auto* channel = mixerEngine_->getChannel(channelIndex);
|
||||
if (channel) channel->setMute(mute);
|
||||
}
|
||||
|
||||
void MixerApi::setChannelSolo(int channelIndex, bool solo)
|
||||
{
|
||||
if (!mixerEngine_) return;
|
||||
auto* channel = mixerEngine_->getChannel(channelIndex);
|
||||
if (channel) channel->setSolo(solo);
|
||||
}
|
||||
|
||||
void MixerApi::setChannelLabel(int channelIndex, const std::string& label)
|
||||
{
|
||||
if (!mixerEngine_) return;
|
||||
auto* channel = mixerEngine_->getChannel(channelIndex);
|
||||
if (channel) channel->setLabel(label);
|
||||
}
|
||||
|
||||
void MixerApi::setChannelType(int channelIndex, const std::string& type)
|
||||
{
|
||||
if (!mixerEngine_) return;
|
||||
auto* channel = mixerEngine_->getChannel(channelIndex);
|
||||
|
||||
if (!channel) return;
|
||||
if (type == "Instrument" || type == "instrument") {
|
||||
channel->setChannelType(MixerChannelType::Instrument);
|
||||
} else if (type == "Mic" || type == "mic") {
|
||||
channel->setChannelType(MixerChannelType::Mic);
|
||||
} else if (type == "Line" || type == "line") {
|
||||
channel->setChannelType(MixerChannelType::Line);
|
||||
}
|
||||
}
|
||||
|
||||
void MixerApi::setChannelHpf(int channelIndex, bool enabled, float frequency)
|
||||
{
|
||||
if (!mixerEngine_) return;
|
||||
auto* channel = mixerEngine_->getChannel(channelIndex);
|
||||
if (channel) {
|
||||
channel->setHpEnabled(enabled);
|
||||
if (frequency > 0) channel->setHpFrequency(frequency);
|
||||
}
|
||||
}
|
||||
|
||||
int MixerApi::addChannel(int physicalInputIndex)
|
||||
{
|
||||
if (!mixerEngine_) return -1;
|
||||
auto* channel = mixerEngine_->addChannel(physicalInputIndex);
|
||||
return channel ? channel->channelIndex() : -1;
|
||||
}
|
||||
|
||||
void MixerApi::removeChannel(int channelIndex)
|
||||
{
|
||||
if (!mixerEngine_) return;
|
||||
mixerEngine_->removeChannel(channelIndex);
|
||||
}
|
||||
|
||||
void MixerApi::setBusVolume(int64_t busId, float volumeDb)
|
||||
{
|
||||
if (!mixerEngine_) return;
|
||||
auto* bus = mixerEngine_->getBus(busId);
|
||||
if (bus) bus->setVolume(volumeDb);
|
||||
}
|
||||
|
||||
void MixerApi::setBusMute(int64_t busId, bool mute)
|
||||
{
|
||||
if (!mixerEngine_) return;
|
||||
auto* bus = mixerEngine_->getBus(busId);
|
||||
if (bus) bus->setMute(mute);
|
||||
}
|
||||
|
||||
int64_t MixerApi::addBus(const std::string& type, const std::string& name, int channels)
|
||||
{
|
||||
if (!mixerEngine_) return -1;
|
||||
|
||||
MixerBusType busType = MixerBusType::Subgroup;
|
||||
if (type == "Master" || type == "master") busType = MixerBusType::Master;
|
||||
else if (type == "Aux" || type == "aux") busType = MixerBusType::Aux;
|
||||
else if (type == "FxReturn" || type == "fxreturn") busType = MixerBusType::FxReturn;
|
||||
else if (type == "Subgroup" || type == "subgroup") busType = MixerBusType::Subgroup;
|
||||
|
||||
return mixerEngine_->addBus(busType, name, channels);
|
||||
}
|
||||
|
||||
void MixerApi::removeBus(int64_t busId)
|
||||
{
|
||||
if (!mixerEngine_) return;
|
||||
mixerEngine_->removeBus(busId);
|
||||
}
|
||||
|
||||
void MixerApi::routeChannelToBus(int channelIndex, int64_t busId, float levelDb)
|
||||
{
|
||||
if (!mixerEngine_) return;
|
||||
mixerEngine_->routeChannelToBus(channelIndex, busId, levelDb);
|
||||
}
|
||||
|
||||
void MixerApi::routeBusToBus(int64_t sourceBusId, int64_t targetBusId, float levelDb)
|
||||
{
|
||||
if (!mixerEngine_) return;
|
||||
mixerEngine_->routeBusToBus(sourceBusId, targetBusId, levelDb);
|
||||
}
|
||||
|
||||
void MixerApi::removeRoute(int64_t sourceId, int64_t targetBusId)
|
||||
{
|
||||
if (!mixerEngine_) return;
|
||||
mixerEngine_->removeRoute(sourceId, targetBusId);
|
||||
}
|
||||
|
||||
std::string MixerApi::getStateJson() const
|
||||
{
|
||||
if (!mixerEngine_) return "{}";
|
||||
|
||||
auto snapshot = mixerEngine_->captureSnapshot();
|
||||
|
||||
std::stringstream ss;
|
||||
json_writer writer(ss, false);
|
||||
writer.start_object();
|
||||
|
||||
writer.write_member("channels", "");
|
||||
// Overwrite the empty string with raw array
|
||||
writer.write_raw("[");
|
||||
bool first = true;
|
||||
for (const auto& cs : snapshot.channels) {
|
||||
if (!first) writer.write_raw(",");
|
||||
first = false;
|
||||
writer.start_object();
|
||||
writer.write_member("channelIndex", (int64_t)cs.channelIndex);
|
||||
writer.write_member("volume", (double)cs.volume);
|
||||
writer.write_member("pan", (double)cs.pan);
|
||||
writer.write_member("mute", cs.mute);
|
||||
writer.write_member("solo", cs.solo);
|
||||
|
||||
const char* typeStr = "Instrument";
|
||||
switch (cs.channelType) {
|
||||
case MixerChannelType::Mic: typeStr = "Mic"; break;
|
||||
case MixerChannelType::Line: typeStr = "Line"; break;
|
||||
case MixerChannelType::AuxReturn: typeStr = "AuxReturn"; break;
|
||||
default: typeStr = "Instrument"; break;
|
||||
}
|
||||
writer.write_member("type", typeStr);
|
||||
writer.write_member("label", cs.label);
|
||||
writer.write_member("hpEnabled", cs.hpEnabled);
|
||||
writer.write_member("hpFrequency", (double)cs.hpFrequency);
|
||||
writer.end_object();
|
||||
}
|
||||
writer.write_raw("]");
|
||||
|
||||
writer.write_member("buses", "");
|
||||
writer.write_raw("[");
|
||||
first = true;
|
||||
for (const auto& bs : snapshot.buses) {
|
||||
if (!first) writer.write_raw(",");
|
||||
first = false;
|
||||
writer.start_object();
|
||||
writer.write_member("id", bs.id);
|
||||
writer.write_member("name", bs.name);
|
||||
|
||||
const char* typeStr = "Subgroup";
|
||||
switch (bs.type) {
|
||||
case MixerBusType::Master: typeStr = "Master"; break;
|
||||
case MixerBusType::Aux: typeStr = "Aux"; break;
|
||||
case MixerBusType::FxReturn: typeStr = "FxReturn"; break;
|
||||
default: typeStr = "Subgroup"; break;
|
||||
}
|
||||
writer.write_member("type", typeStr);
|
||||
writer.write_member("volume", (double)bs.volume);
|
||||
writer.write_member("mute", bs.mute);
|
||||
writer.end_object();
|
||||
}
|
||||
writer.write_raw("]");
|
||||
|
||||
writer.write_member("routes", "");
|
||||
writer.write_raw("[");
|
||||
first = true;
|
||||
for (const auto& route : snapshot.routes) {
|
||||
if (!first) writer.write_raw(",");
|
||||
first = false;
|
||||
writer.start_object();
|
||||
writer.write_member("sourceId", route.sourceId);
|
||||
writer.write_member("targetBusId", route.targetBusId);
|
||||
writer.write_member("level", (double)route.level);
|
||||
|
||||
const char* sourceType = (route.sourceType == MixerRouteEntry::SourceChannel) ? "channel" : "bus";
|
||||
writer.write_member("sourceType", sourceType);
|
||||
writer.end_object();
|
||||
}
|
||||
writer.write_raw("]");
|
||||
|
||||
writer.end_object();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string MixerApi::saveScene(const std::string& name)
|
||||
{
|
||||
// TODO: Implement scene persistence using the existing Storage pattern
|
||||
return "{\"error\":\"not implemented\"}";
|
||||
}
|
||||
|
||||
bool MixerApi::loadScene(const std::string& sceneId)
|
||||
{
|
||||
// TODO: Implement scene loading
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string MixerApi::listScenes() const
|
||||
{
|
||||
// TODO: Implement scene listing
|
||||
return "{\"scenes\":[]}";
|
||||
}
|
||||
|
||||
bool MixerApi::deleteScene(const std::string& sceneId)
|
||||
{
|
||||
// TODO: Implement scene deletion
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
// Copyright (c) 2026 Ourpad Network
|
||||
// See LICENSE file in the project root for full license text.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
namespace pipedal {
|
||||
|
||||
class MixerEngine;
|
||||
|
||||
/// Mixer API — bridges WebSocket messages to the MixerEngine.
|
||||
///
|
||||
/// Follows the existing PiPedalSocket pattern where handlers are registered
|
||||
/// via REGISTER_MESSAGE_HANDLER and dispatched by message name.
|
||||
///
|
||||
/// This class provides the model-level methods that the socket handlers call.
|
||||
class MixerApi {
|
||||
public:
|
||||
MixerApi();
|
||||
~MixerApi();
|
||||
|
||||
/// Set the mixer engine this API talks to.
|
||||
void setMixerEngine(MixerEngine* engine) { mixerEngine_ = engine; }
|
||||
MixerEngine* mixerEngine() const { return mixerEngine_; }
|
||||
|
||||
/// --- Channel Control ---
|
||||
|
||||
/// Set channel volume in dB (-inf to +12)
|
||||
void setChannelVolume(int channelIndex, float volumeDb);
|
||||
|
||||
/// Set channel pan (-1.0 left to +1.0 right)
|
||||
void setChannelPan(int channelIndex, float pan);
|
||||
|
||||
/// Set channel mute state
|
||||
void setChannelMute(int channelIndex, bool mute);
|
||||
|
||||
/// Set channel solo state
|
||||
void setChannelSolo(int channelIndex, bool solo);
|
||||
|
||||
/// Set channel label
|
||||
void setChannelLabel(int channelIndex, const std::string& label);
|
||||
|
||||
/// Set channel type (Instrument, Mic, Line)
|
||||
void setChannelType(int channelIndex, const std::string& type);
|
||||
|
||||
/// Set channel HPF state
|
||||
void setChannelHpf(int channelIndex, bool enabled, float frequency);
|
||||
|
||||
/// --- Channel Lifecycle ---
|
||||
|
||||
/// Add a new channel for the given physical input
|
||||
int addChannel(int physicalInputIndex);
|
||||
|
||||
/// Remove a channel
|
||||
void removeChannel(int channelIndex);
|
||||
|
||||
/// --- Bus Control ---
|
||||
|
||||
/// Set bus volume
|
||||
void setBusVolume(int64_t busId, float volumeDb);
|
||||
|
||||
/// Set bus mute
|
||||
void setBusMute(int64_t busId, bool mute);
|
||||
|
||||
/// Add a new bus
|
||||
int64_t addBus(const std::string& type, const std::string& name, int channels);
|
||||
|
||||
/// Remove a bus
|
||||
void removeBus(int64_t busId);
|
||||
|
||||
/// --- Routing ---
|
||||
|
||||
/// Route a channel to a bus
|
||||
void routeChannelToBus(int channelIndex, int64_t busId, float levelDb);
|
||||
|
||||
/// Route a bus to another bus
|
||||
void routeBusToBus(int64_t sourceBusId, int64_t targetBusId, float levelDb);
|
||||
|
||||
/// Remove a route
|
||||
void removeRoute(int64_t sourceId, int64_t targetBusId);
|
||||
|
||||
/// --- State Queries ---
|
||||
|
||||
/// Get the full mixer state as a JSON string
|
||||
std::string getStateJson() const;
|
||||
|
||||
/// --- Scenes ---
|
||||
|
||||
/// Save current mixer state as a scene
|
||||
std::string saveScene(const std::string& name);
|
||||
|
||||
/// Load a scene by name
|
||||
bool loadScene(const std::string& sceneId);
|
||||
|
||||
/// List available scenes
|
||||
std::string listScenes() const;
|
||||
|
||||
/// Delete a scene
|
||||
bool deleteScene(const std::string& sceneId);
|
||||
|
||||
private:
|
||||
MixerEngine* mixerEngine_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace pipedal
|
||||
@@ -3081,6 +3081,15 @@ std::shared_ptr<Lv2Pedalboard> PiPedalModel::GetLv2Pedalboard()
|
||||
return lv2Pedalboard;
|
||||
}
|
||||
|
||||
void PiPedalModel::SetMixerEngine(const std::shared_ptr<MixerEngine>& engine)
|
||||
{
|
||||
this->mixerEngine = engine;
|
||||
if (this->audioHost)
|
||||
{
|
||||
this->audioHost->SetMixerEngine(engine);
|
||||
}
|
||||
}
|
||||
|
||||
void PiPedalModel::SetSelectedPedalboardPlugin(uint64_t clientId, uint64_t pedalboardId)
|
||||
{
|
||||
// Thinking on this:
|
||||
|
||||
@@ -210,6 +210,7 @@ namespace pipedal
|
||||
std::unique_ptr<AudioHost> audioHost;
|
||||
JackConfiguration jackConfiguration;
|
||||
std::shared_ptr<Lv2Pedalboard> lv2Pedalboard;
|
||||
std::shared_ptr<MixerEngine> mixerEngine;
|
||||
std::filesystem::path webRoot;
|
||||
|
||||
using SubscriberList = std::vector<std::shared_ptr<IPiPedalModelSubscriber>>;
|
||||
@@ -401,6 +402,8 @@ namespace pipedal
|
||||
void SetPedalboard(int64_t clientId, Pedalboard &pedalboard);
|
||||
Pedalboard &GetPedalboard();
|
||||
std::shared_ptr<Lv2Pedalboard> GetLv2Pedalboard();
|
||||
std::shared_ptr<MixerEngine> GetMixerEngine() { return mixerEngine; }
|
||||
void SetMixerEngine(const std::shared_ptr<MixerEngine>& engine);
|
||||
|
||||
void UpdateCurrentPedalboard(int64_t clientId, Pedalboard &pedalboard);
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "Curl.hpp"
|
||||
#include "PiPedalSocket.hpp"
|
||||
#include "MixerApi.hpp"
|
||||
#include "Updater.hpp"
|
||||
#include "json.hpp"
|
||||
#include "viewstream.hpp"
|
||||
@@ -707,6 +708,7 @@ private:
|
||||
|
||||
std::recursive_mutex writeMutex;
|
||||
PiPedalModel &model;
|
||||
MixerApi mixerApi;
|
||||
static std::atomic<uint64_t> nextClientId;
|
||||
std::string imageList;
|
||||
|
||||
@@ -814,6 +816,12 @@ public:
|
||||
PiPedalSocketHandler(PiPedalModel &model)
|
||||
: model(model), clientId(++nextClientId)
|
||||
{
|
||||
// Wire MixerEngine to MixerApi if available
|
||||
auto engine = model.GetMixerEngine();
|
||||
if (engine) {
|
||||
this->mixerApi.setMixerEngine(engine.get());
|
||||
}
|
||||
|
||||
std::stringstream imageList;
|
||||
const std::filesystem::path &webRoot = model.GetWebRoot() / "img";
|
||||
bool firstTime = true;
|
||||
@@ -1217,6 +1225,149 @@ public:
|
||||
}
|
||||
REGISTER_MESSAGE_HANDLER(writeTone3000Readme)
|
||||
|
||||
/************************************************************************/
|
||||
/* Band-in-a-Box Mixer Messages */
|
||||
/************************************************************************/
|
||||
|
||||
void handle_mixerSetChannelVolume(int replyTo, json_reader *pReader)
|
||||
{
|
||||
int channelIndex;
|
||||
double volume;
|
||||
pReader->read(&channelIndex);
|
||||
pReader->read(&volume);
|
||||
this->mixerApi.setChannelVolume(channelIndex, (float)volume);
|
||||
}
|
||||
REGISTER_MESSAGE_HANDLER(mixerSetChannelVolume)
|
||||
|
||||
void handle_mixerSetChannelPan(int replyTo, json_reader *pReader)
|
||||
{
|
||||
int channelIndex;
|
||||
double pan;
|
||||
pReader->read(&channelIndex);
|
||||
pReader->read(&pan);
|
||||
this->mixerApi.setChannelPan(channelIndex, (float)pan);
|
||||
}
|
||||
REGISTER_MESSAGE_HANDLER(mixerSetChannelPan)
|
||||
|
||||
void handle_mixerSetChannelMute(int replyTo, json_reader *pReader)
|
||||
{
|
||||
int channelIndex;
|
||||
bool mute;
|
||||
pReader->read(&channelIndex);
|
||||
pReader->read(&mute);
|
||||
this->mixerApi.setChannelMute(channelIndex, mute);
|
||||
}
|
||||
REGISTER_MESSAGE_HANDLER(mixerSetChannelMute)
|
||||
|
||||
void handle_mixerSetChannelSolo(int replyTo, json_reader *pReader)
|
||||
{
|
||||
int channelIndex;
|
||||
bool solo;
|
||||
pReader->read(&channelIndex);
|
||||
pReader->read(&solo);
|
||||
this->mixerApi.setChannelSolo(channelIndex, solo);
|
||||
}
|
||||
REGISTER_MESSAGE_HANDLER(mixerSetChannelSolo)
|
||||
|
||||
void handle_mixerSetChannelLabel(int replyTo, json_reader *pReader)
|
||||
{
|
||||
int channelIndex;
|
||||
std::string label;
|
||||
pReader->read(&channelIndex);
|
||||
pReader->read(&label);
|
||||
this->mixerApi.setChannelLabel(channelIndex, label);
|
||||
}
|
||||
REGISTER_MESSAGE_HANDLER(mixerSetChannelLabel)
|
||||
|
||||
void handle_mixerSetChannelHpf(int replyTo, json_reader *pReader)
|
||||
{
|
||||
int channelIndex;
|
||||
bool enabled;
|
||||
double frequency;
|
||||
pReader->read(&channelIndex);
|
||||
pReader->read(&enabled);
|
||||
pReader->read(&frequency);
|
||||
this->mixerApi.setChannelHpf(channelIndex, enabled, (float)frequency);
|
||||
}
|
||||
REGISTER_MESSAGE_HANDLER(mixerSetChannelHpf)
|
||||
|
||||
void handle_mixerGetState(int replyTo, json_reader *pReader)
|
||||
{
|
||||
std::string stateJson = this->mixerApi.getStateJson();
|
||||
this->JsonReply(replyTo, "mixerState", stateJson.c_str());
|
||||
}
|
||||
REGISTER_MESSAGE_HANDLER(mixerGetState)
|
||||
|
||||
void handle_mixerAddChannel(int replyTo, json_reader *pReader)
|
||||
{
|
||||
int physicalInputIndex;
|
||||
pReader->read(&physicalInputIndex);
|
||||
int channelIndex = this->mixerApi.addChannel(physicalInputIndex);
|
||||
this->Reply(replyTo, "mixerAddChannel", (int64_t)channelIndex);
|
||||
}
|
||||
REGISTER_MESSAGE_HANDLER(mixerAddChannel)
|
||||
|
||||
void handle_mixerRemoveChannel(int replyTo, json_reader *pReader)
|
||||
{
|
||||
int channelIndex;
|
||||
pReader->read(&channelIndex);
|
||||
this->mixerApi.removeChannel(channelIndex);
|
||||
}
|
||||
REGISTER_MESSAGE_HANDLER(mixerRemoveChannel)
|
||||
|
||||
void handle_mixerSetBusVolume(int replyTo, json_reader *pReader)
|
||||
{
|
||||
int64_t busId;
|
||||
double volume;
|
||||
pReader->read(&busId);
|
||||
pReader->read(&volume);
|
||||
this->mixerApi.setBusVolume(busId, (float)volume);
|
||||
}
|
||||
REGISTER_MESSAGE_HANDLER(mixerSetBusVolume)
|
||||
|
||||
void handle_mixerSetBusMute(int replyTo, json_reader *pReader)
|
||||
{
|
||||
int64_t busId;
|
||||
bool mute;
|
||||
pReader->read(&busId);
|
||||
pReader->read(&mute);
|
||||
this->mixerApi.setBusMute(busId, mute);
|
||||
}
|
||||
REGISTER_MESSAGE_HANDLER(mixerSetBusMute)
|
||||
|
||||
void handle_mixerRouteChannelToBus(int replyTo, json_reader *pReader)
|
||||
{
|
||||
int channelIndex;
|
||||
int64_t busId;
|
||||
double level;
|
||||
pReader->read(&channelIndex);
|
||||
pReader->read(&busId);
|
||||
pReader->read(&level);
|
||||
this->mixerApi.routeChannelToBus(channelIndex, busId, (float)level);
|
||||
}
|
||||
REGISTER_MESSAGE_HANDLER(mixerRouteChannelToBus)
|
||||
|
||||
void handle_mixerAddBus(int replyTo, json_reader *pReader)
|
||||
{
|
||||
std::string type;
|
||||
std::string name;
|
||||
int channels;
|
||||
pReader->read(&type);
|
||||
pReader->read(&name);
|
||||
pReader->read(&channels);
|
||||
int64_t busId = this->mixerApi.addBus(type, name, channels);
|
||||
this->Reply(replyTo, "mixerAddBus", busId);
|
||||
}
|
||||
REGISTER_MESSAGE_HANDLER(mixerAddBus)
|
||||
|
||||
void handle_mixerRemoveBus(int replyTo, json_reader *pReader)
|
||||
{
|
||||
int64_t busId;
|
||||
pReader->read(&busId);
|
||||
this->mixerApi.removeBus(busId);
|
||||
}
|
||||
REGISTER_MESSAGE_HANDLER(mixerRemoveBus)
|
||||
|
||||
void handle_sha256Base64url(int replyTo, json_reader *pReader)
|
||||
{
|
||||
std::string input;
|
||||
|
||||
Reference in New Issue
Block a user