Skip to content

Commit

Permalink
bitfocus: implement more of the API, show UI elements in the device s…
Browse files Browse the repository at this point in the history
…ettings and send the first osc message
  • Loading branch information
jcelerier committed Dec 31, 2024
1 parent 6a3273f commit ae209b9
Show file tree
Hide file tree
Showing 9 changed files with 910 additions and 437 deletions.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include "BitfocusContext.hpp"

namespace bitfocus
{

module_handler_base::module_handler_base(QString module_path)
{
// Create socketpair
socketpair(PF_LOCAL, SOCK_STREAM, 0, pfd);

// Create env
auto genv = QProcessEnvironment::systemEnvironment();
genv.insert("CONNECTION_ID", "connectionId");
genv.insert("VERIFICATION_TOKEN", "foobar");
genv.insert("MODULE_MANIFEST", module_path + "/companion/manifest.json");
genv.insert("NODE_CHANNEL_SERIALIZATION_MODE", "json");
genv.insert("NODE_CHANNEL_FD", QString::number(pfd[1]).toUtf8());

auto socket = new QSocketNotifier(pfd[0], QSocketNotifier::Read, this);
QObject::connect(
socket, &QSocketNotifier::activated, this, &module_handler_base::on_read);

process.setProcessChannelMode(QProcess::ForwardedChannels);
process.setProgram("node");
process.setArguments({"main.js"}); // FIXME entrypoint from spec
process.setWorkingDirectory(module_path);
process.setProcessEnvironment(genv);

process.start();

// See https://forum.qt.io/topic/33964/solved-child-qprocess-that-dies-with-parent/10

/// Connection flow:
// Create process
// <- register call
// -> register response

// -> init call
// <- upgradedItems
// <- setActionDefinitions
// <- setVariableDefinitions
// <- etc.
// <- init response
}

void module_handler_base::on_read(QSocketDescriptor, QSocketNotifier::Type)
{
ssize_t rl = ::read(pfd[0], buf, sizeof(buf));
if(rl <= 0)
return;
char* pos = buf;
char* idx = buf;
char* const end = pos + rl;
do
{
idx = std::find(pos, end, '\n');
if(idx < end)
{
std::ptrdiff_t diff = idx - pos;
std::string_view message(pos, diff);
this->processMessage(message);
pos = idx + 1;
continue;
}
} while(idx < end);
}

void module_handler_base::do_write(std::string_view res)
{
::write(pfd[0], res.data(), res.size());
}

void module_handler_base::do_write(const QByteArray& res)
{
::write(pfd[0], res.data(), res.size());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include "BitfocusContext.hpp"

namespace bitfocus
{

module_handler_base::module_handler_base(QString module_path)
{
// https://doc.qt.io/qt-6/qwineventnotifier.html
// https://forum.qt.io/topic/146343/qsocketnotifier-with-win32-namedpipes/9
// Or maybe QLocalSocket just works on windows?

// FIXME
}
void module_handler_base::do_write(std::string_view res)
{
// FIXME
}

void module_handler_base::do_write(const QByteArray& res)
{
// FIXME
}

}
133 changes: 110 additions & 23 deletions src/plugins/score-plugin-protocols/Protocols/Bitfocus/BitfocusDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <Explorer/DeviceLogging.hpp>
#include <Explorer/DocumentPlugin/DeviceDocumentPlugin.hpp>

#include <Protocols/Bitfocus/BitfocusContext.hpp>
#include <Protocols/Bitfocus/BitfocusSpecificSettings.hpp>

#include <score/application/ApplicationContext.hpp>
Expand All @@ -17,7 +18,101 @@
#include <ossia/network/generic/generic_parameter.hpp>
#include <ossia/network/rate_limiting_protocol.hpp>

#include <ossia-qt/js_utilities.hpp>

#include <memory>
namespace ossia::net
{
class bitfocus_protocol : public ossia::net::protocol_base
{
public:
bitfocus_protocol(
std::shared_ptr<bitfocus::module_handler> rc, ossia::net::network_context_ptr ctx)
: m_rc{rc}
, m_context{ctx}
{
}

bool pull(ossia::net::parameter_base&) override { return true; }
bool push(const ossia::net::parameter_base& p, const ossia::value& v) override
{
auto parent = p.get_node().get_parent();
if(parent == nodes.actions)
{
QMetaObject::invokeMethod(m_rc.get(), [m = m_rc, name = p.get_node().get_name()] {
m->actionRun(name);
});
}
else if(parent == nodes.presets)
{
}
else if(parent == nodes.feedbacks)
{
}
return true;
}
bool push_raw(const ossia::net::full_parameter_data&) override { return true; }
bool observe(ossia::net::parameter_base&, bool) override { return true; }
bool update(ossia::net::node_base& node_base) override { return true; }

void set_device(ossia::net::device_base& dev) override
{
// Start creating the tree
nodes.actions = dev.get_root_node().create_child("action");
nodes.presets = dev.get_root_node().create_child("presets");
nodes.feedbacks = dev.get_root_node().create_child("feedback");
nodes.variables = dev.get_root_node().create_child("variable");

for(auto& v : m_rc->model().actions)
{
auto node = nodes.actions->create_child(v.first.toStdString());
ossia::net::set_description(*node, v.second.name.toStdString());
auto param = node->create_parameter(ossia::val_type::IMPULSE);
}

for(auto& v : m_rc->model().presets)
{
auto node = nodes.presets->create_child(v.first.toStdString());
ossia::net::set_description(*node, v.second.name.toStdString());
auto param = node->create_parameter(ossia::val_type::IMPULSE);
}

for(auto& v : m_rc->model().feedbacks)
{
auto node = nodes.feedbacks->create_child(v.first.toStdString());
ossia::net::set_description(*node, v.second.name.toStdString());
auto param = node->create_parameter(ossia::val_type::IMPULSE);
}

for(auto& v : m_rc->model().variables)
{
auto node = nodes.variables->create_child(v.first.toStdString());
ossia::net::set_description(*node, v.second.name.toStdString());
auto val = ossia::qt::qt_to_ossia{}(v.second.value);

if(val.get_type() != ossia::val_type::NONE)
{
auto param = node->create_parameter(val.get_type());
param->set_value(val);
}
}
}

std::shared_ptr<bitfocus::module_handler> m_rc;
ossia::net::network_context_ptr m_context;
struct
{
ossia::net::node_base* actions{};
ossia::net::node_base* presets{};
ossia::net::node_base* feedbacks{};
ossia::net::node_base* variables{};
} nodes;

ossia::flat_map<ossia::net::parameter_base*, QString> m_actions;
ossia::flat_map<ossia::net::parameter_base*, QString> m_presets;
ossia::flat_map<ossia::net::parameter_base*, QString> m_variables;
};
}
namespace Protocols
{

Expand All @@ -26,33 +121,34 @@ BitfocusDevice::BitfocusDevice(
: OwningDeviceInterface{settings}
, m_ctx{ctx}
{
m_capas.canLearn = true;
m_capas.canRefreshTree = true;
m_capas.canAddNode = false;
m_capas.canRemoveNode = false;
m_capas.canRenameNode = false;
m_capas.canSetProperties = false;
m_capas.canSerialize = false;
m_capas.canLearn = false;
m_capas.hasCallbacks = false;
}

bool BitfocusDevice::reconnect()
{
disconnect();

/*
try
{
const BitfocusSpecificSettings& stgs
= settings().deviceSpecificSettings.value<BitfocusSpecificSettings>();
if(!stgs.handler)
{
qDebug("oh noes");
return false;
;
}
const auto& name = settings().name.toStdString();
if(auto proto
= std::make_unique<ossia::net::bitfocus5_protocol>(m_ctx, stgs.configuration))
if(auto proto = std::make_unique<ossia::net::bitfocus_protocol>(stgs.handler, m_ctx))
{
if(stgs.rate)
{
auto rate = std::make_unique<ossia::net::rate_limiting_protocol>(
std::chrono::milliseconds{*stgs.rate}, std::move(proto));
m_dev = std::make_unique<ossia::net::generic_device>(std::move(rate), name);
}
else
{
m_dev = std::make_unique<ossia::net::generic_device>(std::move(proto), name);
}
m_dev = std::make_unique<ossia::net::generic_device>(std::move(proto), name);

deviceChanged(nullptr, m_dev.get());
setLogging_impl(Device::get_cur_logging(isLogging()));
Expand All @@ -70,18 +166,9 @@ bool BitfocusDevice::reconnect()
{
SCORE_TODO;
}
*/
return connected();
}

void BitfocusDevice::recreate(const Device::Node& n)
{
for(auto& child : n)
{
addNode(child);
}
}

bool BitfocusDevice::isLearning() const
{
/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ class BitfocusDevice final : public Device::OwningDeviceInterface
const Device::DeviceSettings& stngs, const ossia::net::network_context_ptr& ctx);

bool reconnect() override;
void recreate(const Device::Node&) final override;

bool isLearning() const final override;
void setLearning(bool) final override;
Expand Down
Loading

0 comments on commit ae209b9

Please sign in to comment.