mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 18:34:58 +01:00
Work in progress OSC Control manager
Support for log, output and source targets. Now needs to be developed for all attributes.
This commit is contained in:
@@ -19,12 +19,15 @@
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <sstream>
|
||||
|
||||
#include "osc/OscOutboundPacketStream.h"
|
||||
|
||||
#include "Log.h"
|
||||
#include "Settings.h"
|
||||
#include "BaseToolkit.h"
|
||||
#include "Mixer.h"
|
||||
#include "Source.h"
|
||||
|
||||
#include "ControlManager.h"
|
||||
|
||||
@@ -32,31 +35,88 @@
|
||||
#define CONTROL_DEBUG
|
||||
#endif
|
||||
|
||||
#define CONTROL_OSC_MSG "OSC: "
|
||||
|
||||
void Control::RequestListener::ProcessMessage( const osc::ReceivedMessage& m,
|
||||
const IpEndpointName& remoteEndpoint )
|
||||
const IpEndpointName& remoteEndpoint )
|
||||
{
|
||||
char sender[IpEndpointName::ADDRESS_AND_PORT_STRING_LENGTH];
|
||||
remoteEndpoint.AddressAndPortAsString(sender);
|
||||
|
||||
try{
|
||||
|
||||
#ifdef CONTROL_DEBUG
|
||||
Log::Info("%s sent an OSC message %s.", sender, m.AddressPattern());
|
||||
Log::Info(CONTROL_OSC_MSG "received '%s' from %s", m.AddressPattern(), sender);
|
||||
#endif
|
||||
// TODO Preprocessing with Translator
|
||||
|
||||
std::list<std::string> address = BaseToolkit::splitted(m.AddressPattern(), '/');
|
||||
|
||||
// structured OSC address
|
||||
std::list<std::string> address = BaseToolkit::splitted(m.AddressPattern(), OSC_SEPARATOR);
|
||||
//
|
||||
// A wellformed OSC address is in the form '/vimix/target/attribute {arguments}'
|
||||
// First test: should have 3 elements and start with APP_NAME ('vimix')
|
||||
//
|
||||
if (address.size() == 3 && address.front().compare(APP_NAME) == 0 ){
|
||||
// done with the first part of the OSC address
|
||||
address.pop_front();
|
||||
Log::Info("Wellformed vimix message %s.", address.front().c_str());
|
||||
// execute next part of the OSC message
|
||||
std::string target = address.front();
|
||||
std::string attribute = address.back();
|
||||
// Log target
|
||||
if ( target.compare(OSC_LOG) == 0 )
|
||||
{
|
||||
if ( attribute.compare(OSC_LOG_INFO) == 0)
|
||||
Log::Info(CONTROL_OSC_MSG "received '%s' from %s", m.AddressPattern(), sender);
|
||||
}
|
||||
// Output target
|
||||
else if ( target.compare(OSC_OUTPUT) == 0 )
|
||||
{
|
||||
Control::manager().setOutputAttribute(attribute, m.ArgumentStream());
|
||||
}
|
||||
// Current source target
|
||||
else if ( target.compare(OSC_CURRENT) == 0 )
|
||||
{
|
||||
// attributes to change current
|
||||
if ( attribute.compare(OSC_CURRENT_NONE) == 0)
|
||||
Mixer::manager().unsetCurrentSource();
|
||||
else if ( attribute.compare(OSC_CURRENT_NEXT) == 0)
|
||||
Mixer::manager().setCurrentNext();
|
||||
else if ( attribute.compare(OSC_CURRENT_PREVIOUS) == 0)
|
||||
Mixer::manager().setCurrentPrevious();
|
||||
// all other attributes operate on current source
|
||||
else
|
||||
Control::manager().setSourceAttribute( Mixer::manager().currentSource(), attribute, m.ArgumentStream());
|
||||
}
|
||||
// General case: try to identify the target
|
||||
else {
|
||||
// try to find source by name
|
||||
Source *s = Mixer::manager().findSource(target);
|
||||
// if failed, try to find source by index
|
||||
if (s == nullptr) {
|
||||
int N = -1;
|
||||
try {
|
||||
N = std::stoi(target);
|
||||
} catch (const std::invalid_argument&) {
|
||||
N = -1;
|
||||
}
|
||||
if (N>=0)
|
||||
s = Mixer::manager().sourceAtIndex(N);
|
||||
}
|
||||
if (s)
|
||||
Control::manager().setSourceAttribute(s, attribute, m.ArgumentStream());
|
||||
else
|
||||
Log::Info(CONTROL_OSC_MSG "Unknown target '%s' requested by %s.", target.c_str(), sender);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONTROL_DEBUG
|
||||
else {
|
||||
Log::Info(CONTROL_OSC_MSG "Ignoring malformed message '%s' from %s.", m.AddressPattern(), sender);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
catch( osc::Exception& e ){
|
||||
// any parsing errors such as unexpected argument types, or
|
||||
// missing arguments get thrown as exceptions.
|
||||
Log::Info("error while parsing message '%s' from %s : %s", m.AddressPattern(), sender, e.what());
|
||||
Log::Info(CONTROL_OSC_MSG "Ignoring error in message '%s' from %s : %s", m.AddressPattern(), sender, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +124,7 @@ void Control::RequestListener::ProcessMessage( const osc::ReceivedMessage& m,
|
||||
void Control::listen()
|
||||
{
|
||||
#ifdef CONTROL_DEBUG
|
||||
Log::Info("Accepting OSC messages on port %d", Settings::application.control.osc_port);
|
||||
Log::Info(CONTROL_OSC_MSG "Accepting messages on port %d", Settings::application.control.osc_port_receive);
|
||||
#endif
|
||||
if (Control::manager().receiver_)
|
||||
Control::manager().receiver_->Run();
|
||||
@@ -89,7 +149,7 @@ bool Control::init()
|
||||
// try to create listenning socket
|
||||
// through exception runtime if fails
|
||||
receiver_ = new UdpListeningReceiveSocket( IpEndpointName( IpEndpointName::ANY_ADDRESS,
|
||||
Settings::application.control.osc_port ), &listener_ );
|
||||
Settings::application.control.osc_port_receive ), &listener_ );
|
||||
}
|
||||
catch (const std::runtime_error&) {
|
||||
// arg, the receiver could not be initialized
|
||||
@@ -108,3 +168,89 @@ void Control::terminate()
|
||||
if (receiver_!=nullptr)
|
||||
receiver_->AsynchronousBreak();
|
||||
}
|
||||
|
||||
void Control::setOutputAttribute(const std::string &attribute,
|
||||
osc::ReceivedMessageArgumentStream arguments)
|
||||
{
|
||||
try {
|
||||
/// '/vimix/output/enable' or '/vimix/output/enable T' or '/vimix/output/enable F'
|
||||
if ( attribute.compare(OSC_OUTPUT_ENABLE) == 0) {
|
||||
bool on = true;
|
||||
if ( !arguments.Eos()) {
|
||||
arguments >> on >> osc::EndMessage;
|
||||
}
|
||||
Settings::application.render.disabled = !on;
|
||||
}
|
||||
/// '/vimix/output/disable' or '/vimix/output/disable T' or '/vimix/output/disable F'
|
||||
else if ( attribute.compare(OSC_OUTPUT_DISABLE) == 0) {
|
||||
bool on = true;
|
||||
if ( !arguments.Eos()) {
|
||||
arguments >> on >> osc::EndMessage;
|
||||
}
|
||||
Settings::application.render.disabled = on;
|
||||
}
|
||||
/// '/vimix/output/fading f 0.2'
|
||||
else if ( attribute.compare(OSC_OUTPUT_FADING) == 0) {
|
||||
float fading = 0.f;
|
||||
arguments >> fading >> osc::EndMessage;
|
||||
Mixer::manager().session()->setFading(fading); // TODO move cursor when in Mixing view
|
||||
}
|
||||
#ifdef CONTROL_DEBUG
|
||||
else {
|
||||
Log::Info(CONTROL_OSC_MSG "Ignoring attribute '%s' for target 'output'", attribute.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
catch (osc::MissingArgumentException &e) {
|
||||
Log::Info(CONTROL_OSC_MSG "Missing argument for attribute '%s' for target 'output'", attribute.c_str());
|
||||
}
|
||||
catch (osc::ExcessArgumentException &e) {
|
||||
Log::Info(CONTROL_OSC_MSG "Too many arguments for attribute '%s' for target 'output'", attribute.c_str());
|
||||
}
|
||||
catch (osc::WrongArgumentTypeException &e) {
|
||||
Log::Info(CONTROL_OSC_MSG "Invalid argument for attribute '%s' for target 'output'", attribute.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void Control::setSourceAttribute(Source *target, const std::string &attribute,
|
||||
osc::ReceivedMessageArgumentStream arguments)
|
||||
{
|
||||
if (target == nullptr)
|
||||
return;
|
||||
|
||||
try {
|
||||
/// '/vimix/current/play' or '/vimix/current/play T' or '/vimix/current/play F'
|
||||
if ( attribute.compare(OSC_SOURCE_PLAY) == 0) {
|
||||
bool on = true;
|
||||
if ( !arguments.Eos()) {
|
||||
arguments >> on >> osc::EndMessage;
|
||||
}
|
||||
target->play(on);
|
||||
}
|
||||
/// '/vimix/current/pause' or '/vimix/current/pause T' or '/vimix/current/pause F'
|
||||
else if ( attribute.compare(OSC_SOURCE_PAUSE) == 0) {
|
||||
bool on = true;
|
||||
if ( !arguments.Eos()) {
|
||||
arguments >> on >> osc::EndMessage;
|
||||
}
|
||||
target->play(!on);
|
||||
}
|
||||
#ifdef CONTROL_DEBUG
|
||||
else {
|
||||
Log::Info(CONTROL_OSC_MSG "Ignoring attribute '%s' for target %s.", attribute.c_str(), target->name().c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
catch (osc::MissingArgumentException &e) {
|
||||
Log::Info(CONTROL_OSC_MSG "Missing argument for attribute '%s' for target %s.", attribute.c_str(), target->name().c_str());
|
||||
}
|
||||
catch (osc::ExcessArgumentException &e) {
|
||||
Log::Info(CONTROL_OSC_MSG "Too many arguments for attribute '%s' for target %s.", attribute.c_str(), target->name().c_str());
|
||||
}
|
||||
catch (osc::WrongArgumentTypeException &e) {
|
||||
Log::Info(CONTROL_OSC_MSG "Invalid argument for attribute '%s' for target %s.", attribute.c_str(), target->name().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user