Fixed OSC feedback after source change. Added OSC command to lock source.

This commit is contained in:
Bruno Herbelin
2021-12-27 23:36:28 +01:00
parent 4b8efabc5f
commit ff48877d16
4 changed files with 84 additions and 43 deletions

View File

@@ -74,10 +74,10 @@ void Control::RequestListener::ProcessMessage( const osc::ReceivedMessage& m,
if ( target.compare(OSC_INFO) == 0 ) if ( target.compare(OSC_INFO) == 0 )
{ {
if ( attribute.compare(OSC_INFO_NOTIFY) == 0) { if ( attribute.compare(OSC_INFO_NOTIFY) == 0) {
Log::Notify(CONTROL_OSC_MSG "received '%s' from %s", FullMessage(m).c_str(), sender); Log::Notify(CONTROL_OSC_MSG "Received '%s' from %s", FullMessage(m).c_str(), sender);
} }
else if ( attribute.compare(OSC_INFO_LOG) == 0) { else if ( attribute.compare(OSC_INFO_LOG) == 0) {
Log::Info(CONTROL_OSC_MSG "received '%s' from %s", FullMessage(m).c_str(), sender); Log::Info(CONTROL_OSC_MSG "Received '%s' from %s", FullMessage(m).c_str(), sender);
} }
} }
// Output target: concerns attributes of the rendering output // Output target: concerns attributes of the rendering output
@@ -103,8 +103,10 @@ void Control::RequestListener::ProcessMessage( const osc::ReceivedMessage& m,
{ {
// Loop over selected sources // Loop over selected sources
for (SourceList::iterator it = Mixer::manager().session()->begin(); it != Mixer::manager().session()->end(); ++it) { for (SourceList::iterator it = Mixer::manager().session()->begin(); it != Mixer::manager().session()->end(); ++it) {
// attributes operate on current source // apply attributes
Control::manager().receiveSourceAttribute( *it, attribute, m.ArgumentStream()); if ( Control::manager().receiveSourceAttribute( *it, attribute, m.ArgumentStream()) && Mixer::manager().currentSource() == *it)
// and send back feedback if needed
Control::manager().sendSourceAttibutes(remoteEndpoint, OSC_CURRENT);
} }
} }
// Selected sources target: apply attribute to all sources of the selection // Selected sources target: apply attribute to all sources of the selection
@@ -112,8 +114,10 @@ void Control::RequestListener::ProcessMessage( const osc::ReceivedMessage& m,
{ {
// Loop over selected sources // Loop over selected sources
for (SourceList::iterator it = Mixer::selection().begin(); it != Mixer::selection().end(); ++it) { for (SourceList::iterator it = Mixer::selection().begin(); it != Mixer::selection().end(); ++it) {
// attributes operate on current source // apply attributes
Control::manager().receiveSourceAttribute( *it, attribute, m.ArgumentStream()); if ( Control::manager().receiveSourceAttribute( *it, attribute, m.ArgumentStream()) && Mixer::manager().currentSource() == *it)
// and send back feedback if needed
Control::manager().sendSourceAttibutes(remoteEndpoint, OSC_CURRENT);
} }
} }
// Current source target: apply attribute to the current sources // Current source target: apply attribute to the current sources
@@ -147,41 +151,35 @@ void Control::RequestListener::ProcessMessage( const osc::ReceivedMessage& m,
// apply attributes to current source // apply attributes to current source
if ( Control::manager().receiveSourceAttribute( Mixer::manager().currentSource(), attribute, m.ArgumentStream()) ) if ( Control::manager().receiveSourceAttribute( Mixer::manager().currentSource(), attribute, m.ArgumentStream()) )
// and send back feedback if needed // and send back feedback if needed
Control::manager().sendCurrentSourceAttibutes(remoteEndpoint); Control::manager().sendSourceAttibutes(remoteEndpoint, OSC_CURRENT);
} }
} }
// General case: try to identify the target // General case: try to identify the target
else { else {
// remove osc separator from the target string
target.erase(0,1);
// try to find source by index // try to find source by index
Source *s = nullptr; Source *s = nullptr;
int sourceid = -1; int sourceid = -1;
if ( BaseToolkit::is_a_number(target, &sourceid) ) if ( BaseToolkit::is_a_number(target.substr(1), &sourceid) )
s = Mixer::manager().sourceAtIndex(sourceid); s = Mixer::manager().sourceAtIndex(sourceid);
// if failed, try to find source by name // if failed, try to find source by name
if (s == nullptr) if (s == nullptr)
s = Mixer::manager().findSource(target); s = Mixer::manager().findSource(target.substr(1));
// if a source with the given target name or index was found // if a source with the given target name or index was found
if (s) { if (s) {
// apply attributes to source // apply attributes to source
if ( Control::manager().receiveSourceAttribute(s, attribute, m.ArgumentStream()) ) if ( Control::manager().receiveSourceAttribute(s, attribute, m.ArgumentStream()) )
// and send back feedback if needed // and send back feedback if needed
Control::manager().sendCurrentSourceAttibutes(remoteEndpoint); Control::manager().sendSourceAttibutes(remoteEndpoint, target, s);
} }
else else
Log::Info(CONTROL_OSC_MSG "Unknown target '%s' requested by %s.", target.c_str(), sender); Log::Info(CONTROL_OSC_MSG "Unknown target '%s' requested by %s.", target.c_str(), sender);
} }
} }
#ifdef CONTROL_DEBUG
else { else {
Log::Info(CONTROL_OSC_MSG "Ignoring malformed message '%s' from %s.", m.AddressPattern(), sender); Log::Info(CONTROL_OSC_MSG "Unknown osc message '%s' sent by %s.", m.AddressPattern(), sender);
} }
#endif
} }
catch( osc::Exception& e ){ catch( osc::Exception& e ){
// any parsing errors such as unexpected argument types, or // any parsing errors such as unexpected argument types, or
@@ -250,13 +248,11 @@ Control::~Control()
std::string Control::translate (std::string addresspattern) std::string Control::translate (std::string addresspattern)
{ {
std::string translation = addresspattern; auto it_translation = translation_.find(addresspattern);
auto it_translation = translation_.find(addresspattern);
if ( it_translation != translation_.end() ) if ( it_translation != translation_.end() )
translation = it_translation->second; return it_translation->second;
else
return translation; return addresspattern;
} }
void Control::loadOscConfig() void Control::loadOscConfig()
@@ -361,7 +357,6 @@ bool Control::init()
Settings::application.control.osc_port_receive )); Settings::application.control.osc_port_receive ));
static char *addresseip = (char *)malloc(IpEndpointName::ADDRESS_AND_PORT_STRING_LENGTH); static char *addresseip = (char *)malloc(IpEndpointName::ADDRESS_AND_PORT_STRING_LENGTH);
ip.AddressAndPortAsString(addresseip); ip.AddressAndPortAsString(addresseip);
Log::Info(CONTROL_OSC_MSG "Listening to UDP messages sent to %s", addresseip); Log::Info(CONTROL_OSC_MSG "Listening to UDP messages sent to %s", addresseip);
} }
catch (const std::runtime_error &e) { catch (const std::runtime_error &e) {
@@ -507,6 +502,12 @@ bool Control::receiveSourceAttribute(Source *target, const std::string &attribut
target->call( new RePlay() ); target->call( new RePlay() );
} }
/// e.g. '/vimix/current/alpha f 0.3' /// e.g. '/vimix/current/alpha f 0.3'
else if ( attribute.compare(OSC_SOURCE_LOCK) == 0) {
float x = 1.f;
arguments >> x >> osc::EndMessage;
target->call( new SetLock(x > 0.5f ? true : false) );
}
/// e.g. '/vimix/current/alpha f 0.3'
else if ( attribute.compare(OSC_SOURCE_ALPHA) == 0) { else if ( attribute.compare(OSC_SOURCE_ALPHA) == 0) {
float x = 1.f; float x = 1.f;
arguments >> x >> osc::EndMessage; arguments >> x >> osc::EndMessage;
@@ -564,6 +565,10 @@ bool Control::receiveSourceAttribute(Source *target, const std::string &attribut
} }
#endif #endif
// overwrite value if source locked
if (target->locked())
send_feedback = true;
} }
catch (osc::MissingArgumentException &e) { catch (osc::MissingArgumentException &e) {
Log::Info(CONTROL_OSC_MSG "Missing argument for attribute '%s' for target %s.", attribute.c_str(), target->name().c_str()); Log::Info(CONTROL_OSC_MSG "Missing argument for attribute '%s' for target %s.", attribute.c_str(), target->name().c_str());
@@ -583,11 +588,11 @@ bool Control::receiveSourceAttribute(Source *target, const std::string &attribut
bool Control::receiveSessionAttribute(const std::string &attribute, bool Control::receiveSessionAttribute(const std::string &attribute,
osc::ReceivedMessageArgumentStream arguments) osc::ReceivedMessageArgumentStream arguments)
{ {
bool need_feedback = false; bool send_feedback = false;
try { try {
if ( attribute.compare(OSC_SYNC) == 0) { if ( attribute.compare(OSC_SYNC) == 0) {
need_feedback = true; send_feedback = true;
} }
else if ( attribute.compare(OSC_SESSION_VERSION) == 0) { else if ( attribute.compare(OSC_SESSION_VERSION) == 0) {
float v = 0.f; float v = 0.f;
@@ -600,11 +605,11 @@ bool Control::receiveSessionAttribute(const std::string &attribute,
uint64_t snap = snapshots.back(); uint64_t snap = snapshots.back();
Action::manager().restore(snap); Action::manager().restore(snap);
} }
need_feedback = true; send_feedback = true;
} }
#ifdef CONTROL_DEBUG #ifdef CONTROL_DEBUG
else { else {
Log::Info(CONTROL_OSC_MSG "Ignoring attribute '%s' for target 'output'", attribute.c_str()); Log::Info(CONTROL_OSC_MSG "Ignoring attribute '%s' for target 'session'", attribute.c_str());
} }
#endif #endif
@@ -619,24 +624,30 @@ bool Control::receiveSessionAttribute(const std::string &attribute,
Log::Info(CONTROL_OSC_MSG "Invalid argument for attribute '%s' for target 'session'", attribute.c_str()); Log::Info(CONTROL_OSC_MSG "Invalid argument for attribute '%s' for target 'session'", attribute.c_str());
} }
return need_feedback; return send_feedback;
} }
void Control::sendCurrentSourceAttibutes(const IpEndpointName &remoteEndpoint) void Control::sendSourceAttibutes(const IpEndpointName &remoteEndpoint, std::string target, Source *s)
{ {
// default values // default values
char name[21] = {"\0"}; char name[21] = {"\0"};
float lock = 0.f;
float play = 0.f; float play = 0.f;
float depth = 0.f; float depth = 0.f;
float alpha = 0.f; float alpha = 0.f;
// fill values if the current source is valid // get source or current source
Source *s = Mixer::manager().currentSource(); Source *_s = s;
if (s!=nullptr) { if ( target.compare(OSC_CURRENT) == 0 )
strncpy(name, s->name().c_str(), 20); _s = Mixer::manager().currentSource();
play = s->playing() ? 1.f : 0.f;
depth = s->depth(); // fill values if the source is valid
alpha = s->alpha(); if (_s!=nullptr) {
strncpy(name, _s->name().c_str(), 20);
lock = _s->locked() ? 1.f : 0.f;
play = _s->playing() ? 1.f : 0.f;
depth = _s->depth();
alpha = _s->alpha();
} }
// build socket to send message to indicated endpoint // build socket to send message to indicated endpoint
@@ -651,13 +662,20 @@ void Control::sendCurrentSourceAttibutes(const IpEndpointName &remoteEndpoint)
p << osc::BeginBundle(); p << osc::BeginBundle();
/// name /// name
p << osc::BeginMessage( OSC_PREFIX OSC_CURRENT OSC_SOURCE_NAME ) << name << osc::EndMessage; std::string address = std::string(OSC_PREFIX) + target + OSC_SOURCE_NAME;
p << osc::BeginMessage( address.c_str() ) << name << osc::EndMessage;
/// Play status /// Play status
p << osc::BeginMessage( OSC_PREFIX OSC_CURRENT OSC_SOURCE_PLAY ) << play << osc::EndMessage; address = std::string(OSC_PREFIX) + target + OSC_SOURCE_LOCK;
p << osc::BeginMessage( address.c_str() ) << lock << osc::EndMessage;
/// Play status
address = std::string(OSC_PREFIX) + target + OSC_SOURCE_PLAY;
p << osc::BeginMessage( address.c_str() ) << play << osc::EndMessage;
/// Depth /// Depth
p << osc::BeginMessage( OSC_PREFIX OSC_CURRENT OSC_SOURCE_DEPTH ) << depth << osc::EndMessage; address = std::string(OSC_PREFIX) + target + OSC_SOURCE_DEPTH;
p << osc::BeginMessage( address.c_str() ) << depth << osc::EndMessage;
/// Alpha /// Alpha
p << osc::BeginMessage( OSC_PREFIX OSC_CURRENT OSC_SOURCE_ALPHA ) << alpha << osc::EndMessage; address = std::string(OSC_PREFIX) + target + OSC_SOURCE_ALPHA;
p << osc::BeginMessage( address.c_str() ) << alpha << osc::EndMessage;
// send bundle // send bundle
p << osc::EndBundle; p << osc::EndBundle;
@@ -709,7 +727,7 @@ void Control::sendSourcesStatus(const IpEndpointName &remoteEndpoint, osc::Recei
socket.Send( p.Data(), p.Size() ); socket.Send( p.Data(), p.Size() );
// send status of current source // send status of current source
sendCurrentSourceAttibutes(remoteEndpoint); sendSourceAttibutes(remoteEndpoint, OSC_CURRENT);
} }

View File

@@ -26,6 +26,7 @@
#define OSC_PREVIOUS "/previous" #define OSC_PREVIOUS "/previous"
#define OSC_SOURCE_NAME "/name" #define OSC_SOURCE_NAME "/name"
#define OSC_SOURCE_LOCK "/lock"
#define OSC_SOURCE_PLAY "/play" #define OSC_SOURCE_PLAY "/play"
#define OSC_SOURCE_PAUSE "/pause" #define OSC_SOURCE_PAUSE "/pause"
#define OSC_SOURCE_REPLAY "/replay" #define OSC_SOURCE_REPLAY "/replay"
@@ -84,7 +85,7 @@ protected:
bool receiveSessionAttribute(const std::string &attribute, bool receiveSessionAttribute(const std::string &attribute,
osc::ReceivedMessageArgumentStream arguments); osc::ReceivedMessageArgumentStream arguments);
void sendCurrentSourceAttibutes(const IpEndpointName& remoteEndpoint); void sendSourceAttibutes(const IpEndpointName& remoteEndpoint, std::string target, Source *s = nullptr);
void sendSourcesStatus(const IpEndpointName& remoteEndpoint, osc::ReceivedMessageArgumentStream arguments); void sendSourcesStatus(const IpEndpointName& remoteEndpoint, osc::ReceivedMessageArgumentStream arguments);
void sendOutputStatus(const IpEndpointName& remoteEndpoint); void sendOutputStatus(const IpEndpointName& remoteEndpoint);

View File

@@ -73,6 +73,17 @@ void SetAlpha::update(Source *s, float)
finished_ = true; finished_ = true;
} }
SetLock::SetLock(bool on) : SourceCallback(), lock_(on)
{
}
void SetLock::update(Source *s, float)
{
if (s)
s->setLocked(lock_);
finished_ = true;
}
Loom::Loom(float da, float duration) : SourceCallback(), speed_(da), Loom::Loom(float da, float duration) : SourceCallback(), speed_(da),
duration_(duration), progress_(0.f) duration_(duration), progress_(0.f)

View File

@@ -12,6 +12,7 @@ public:
typedef enum { typedef enum {
CALLBACK_GENERIC = 0, CALLBACK_GENERIC = 0,
CALLBACK_ALPHA, CALLBACK_ALPHA,
CALLBACK_LOCK,
CALLBACK_LOOM, CALLBACK_LOOM,
CALLBACK_DEPTH, CALLBACK_DEPTH,
CALLBACK_PLAY, CALLBACK_PLAY,
@@ -71,6 +72,16 @@ public:
CallbackType type () override { return CALLBACK_LOOM; } CallbackType type () override { return CALLBACK_LOOM; }
}; };
class SetLock : public SourceCallback
{
bool lock_;
public:
SetLock(bool on);
void update(Source *s, float) override;
CallbackType type () override { return CALLBACK_LOCK; }
};
class SetDepth : public SourceCallback class SetDepth : public SourceCallback
{ {
float duration_; float duration_;