diff --git a/ControlManager.cpp b/ControlManager.cpp index 42fcff9..ca9d4db 100644 --- a/ControlManager.cpp +++ b/ControlManager.cpp @@ -68,18 +68,11 @@ void Control::RequestListener::ProcessMessage( const osc::ReceivedMessage& m, // Log target: just print text in log window if ( target.compare(OSC_INFO) == 0 ) { - if ( attribute.compare(OSC_INFO_SYNC) == 0) { + if ( attribute.compare(OSC_SYNC) == 0) { // send the global status - Control::manager().sendStatus(remoteEndpoint); - // + Control::manager().sendOutputStatus(remoteEndpoint); // send the status of all sources - // - // (if an argument is given, it indicates the number of sources to update) - float N = 0.f; - if ( !m.ArgumentStream().Eos()) - m.ArgumentStream() >> N >> osc::EndMessage; - // send the status of all sources - Control::manager().sendSourcesStatus(remoteEndpoint, N); + Control::manager().sendSourcesStatus(remoteEndpoint, m.ArgumentStream()); } else if ( attribute.compare(OSC_INFO_LOG) == 0) { Log::Info(CONTROL_OSC_MSG "received '%s' from %s", FullMessage(m).c_str(), sender); @@ -88,7 +81,12 @@ void Control::RequestListener::ProcessMessage( const osc::ReceivedMessage& m, // Output target: concerns attributes of the rendering output else if ( target.compare(OSC_OUTPUT) == 0 ) { - Control::manager().receiveOutputAttribute(attribute, m.ArgumentStream()); + if ( attribute.compare(OSC_SYNC) == 0) { + // send the global status + Control::manager().sendOutputStatus(remoteEndpoint); + } + else + Control::manager().receiveOutputAttribute(attribute, m.ArgumentStream()); } // ALL sources target: apply attribute to all sources of the session else if ( target.compare(OSC_ALL) == 0 ) @@ -112,51 +110,36 @@ void Control::RequestListener::ProcessMessage( const osc::ReceivedMessage& m, else if ( target.compare(OSC_CURRENT) == 0 ) { int sourceid = -1; - if ( attribute.compare(OSC_NEXT) == 0) { + if ( attribute.compare(OSC_SYNC) == 0) { + // send the status of all sources + Control::manager().sendSourcesStatus(remoteEndpoint, m.ArgumentStream()); + } + else if ( attribute.compare(OSC_NEXT) == 0) { // set current to NEXT Mixer::manager().setCurrentNext(); - // confirm by sending back the current source attributes - Control::manager().sendCurrentSourceAttibutes(remoteEndpoint); - // // send the status of all sources - // - // (if an argument is given, it indicates the number of sources to update) - float N = 0.f; - if ( !m.ArgumentStream().Eos()) - m.ArgumentStream() >> N >> osc::EndMessage; - Control::manager().sendSourcesStatus(remoteEndpoint, N); + Control::manager().sendSourcesStatus(remoteEndpoint, m.ArgumentStream()); } else if ( attribute.compare(OSC_PREVIOUS) == 0) { // set current to PREVIOUS Mixer::manager().setCurrentPrevious(); - // confirm by sending back the current source attributes - Control::manager().sendCurrentSourceAttibutes(remoteEndpoint); - // // send the status of all sources - // - // (if an argument is given, it indicates the number of sources to update) - float N = 0.f; - if ( !m.ArgumentStream().Eos()) - m.ArgumentStream() >> N >> osc::EndMessage; - Control::manager().sendSourcesStatus(remoteEndpoint, N); + Control::manager().sendSourcesStatus(remoteEndpoint, m.ArgumentStream()); } else if ( BaseToolkit::is_a_number( attribute.substr(1), &sourceid) ){ // set current to given INDEX Mixer::manager().setCurrentIndex(sourceid); - // confirm by sending back the current source attributes - Control::manager().sendCurrentSourceAttibutes(remoteEndpoint); - // // send the status of all sources - // - // (if an argument is given, it indicates the number of sources to update) - float N = 0.f; - if ( !m.ArgumentStream().Eos()) - m.ArgumentStream() >> N >> osc::EndMessage; - Control::manager().sendSourcesStatus(remoteEndpoint, N); + Control::manager().sendSourcesStatus(remoteEndpoint, m.ArgumentStream()); } // all other attributes operate on current source - else - Control::manager().receiveSourceAttribute( Mixer::manager().currentSource(), attribute, m.ArgumentStream()); + else { + // apply attributes + if ( Control::manager().receiveSourceAttribute( Mixer::manager().currentSource(), attribute, m.ArgumentStream()) ) + // and send back feedback if needed + Control::manager().sendCurrentSourceAttibutes(remoteEndpoint); + + } } // General case: try to identify the target else { @@ -329,11 +312,13 @@ void Control::receiveOutputAttribute(const std::string &attribute, } } -void Control::receiveSourceAttribute(Source *target, const std::string &attribute, +bool Control::receiveSourceAttribute(Source *target, const std::string &attribute, osc::ReceivedMessageArgumentStream arguments) { + bool send_feedback = false; + if (target == nullptr) - return; + return send_feedback; try { /// e.g. '/vimix/current/play' or '/vimix/current/play T' or '/vimix/current/play F' @@ -362,6 +347,14 @@ void Control::receiveSourceAttribute(Source *target, const std::string &attribut arguments >> x >> osc::EndMessage; target->call( new SetAlpha(x), true ); } + /// e.g. '/vimix/current/alpha f 0.3' + else if ( attribute.compare(OSC_SOURCE_LOOM) == 0) { + float x = 1.f; + arguments >> x >> osc::EndMessage; + target->call( new Loom(x), true ); + // this will require to send feedback status about source + send_feedback = true; + } /// e.g. '/vimix/current/transparency f 0.7' else if ( attribute.compare(OSC_SOURCE_TRANSPARENCY) == 0) { float x = 0.f; @@ -388,8 +381,12 @@ void Control::receiveSourceAttribute(Source *target, const std::string &attribut } /// e.g. '/vimix/current/turn f 1.0' else if ( attribute.compare(OSC_SOURCE_TURN) == 0) { - float x = 0.f; - arguments >> x >> osc::EndMessage; + float x = 0.f, y = 0.f; + arguments >> x; + if (arguments.Eos()) + arguments >> osc::EndMessage; + else // ignore second argument + arguments >> y >> osc::EndMessage; target->call( new Turn( x ), true ); } /// e.g. '/vimix/current/reset' @@ -412,6 +409,8 @@ void Control::receiveSourceAttribute(Source *target, const std::string &attribut catch (osc::WrongArgumentTypeException &e) { Log::Info(CONTROL_OSC_MSG "Invalid argument for attribute '%s' for target %s.", attribute.c_str(), target->name().c_str()); } + + return send_feedback; } @@ -458,8 +457,13 @@ void Control::sendCurrentSourceAttibutes(const IpEndpointName &remoteEndpoint) } -void Control::sendSourcesStatus(const IpEndpointName &remoteEndpoint, float max_count) +void Control::sendSourcesStatus(const IpEndpointName &remoteEndpoint, osc::ReceivedMessageArgumentStream arguments) { + // (if an argument is given, it indicates the number of sources to update) + float N = 0.f; + if ( !arguments.Eos()) + arguments >> N >> osc::EndMessage; + // build socket to send message to indicated endpoint UdpTransmitSocket socket( IpEndpointName( remoteEndpoint.address, Settings::application.control.osc_port_send ) ); @@ -483,7 +487,7 @@ void Control::sendSourcesStatus(const IpEndpointName &remoteEndpoint, float max_ p << osc::BeginMessage( oscaddr ) << Mixer::manager().sourceAtIndex(i)->alpha() << osc::EndMessage; } - for (; i < max_count; ++i) { + for (; i < (int) N ; ++i) { // reset status of currently selected sprintf(oscaddr, OSC_PREFIX OSC_CURRENT "/%d", i); p << osc::BeginMessage( oscaddr ) << 0.f << osc::EndMessage; @@ -495,10 +499,13 @@ void Control::sendSourcesStatus(const IpEndpointName &remoteEndpoint, float max_ p << osc::EndBundle; socket.Send( p.Data(), p.Size() ); + + // send status of current source + sendCurrentSourceAttibutes(remoteEndpoint); } -void Control::sendStatus(const IpEndpointName &remoteEndpoint) +void Control::sendOutputStatus(const IpEndpointName &remoteEndpoint) { // build socket to send message to indicated endpoint UdpTransmitSocket socket( IpEndpointName( remoteEndpoint.address, Settings::application.control.osc_port_send ) ); @@ -510,12 +517,6 @@ void Control::sendStatus(const IpEndpointName &remoteEndpoint) p.Clear(); p << osc::BeginBundle(); - /// - /// messages - /// - /// Agree to test - p << osc::BeginMessage( OSC_PREFIX OSC_INFO OSC_INFO_SYNC ); - p << osc::EndMessage; /// output attributes p << osc::BeginMessage( OSC_PREFIX OSC_OUTPUT OSC_OUTPUT_ENABLE ); p << (Settings::application.render.disabled ? 0.f : 1.f); diff --git a/ControlManager.h b/ControlManager.h index e560be0..d95f5da 100644 --- a/ControlManager.h +++ b/ControlManager.h @@ -3,8 +3,9 @@ #include "NetworkToolkit.h" +#define OSC_SYNC "/sync" + #define OSC_INFO "/info" -#define OSC_INFO_SYNC "/sync" #define OSC_INFO_LOG "/log" #define OSC_OUTPUT "/output" @@ -24,6 +25,7 @@ #define OSC_SOURCE_PAUSE "/pause" #define OSC_SOURCE_REPLAY "/replay" #define OSC_SOURCE_ALPHA "/alpha" +#define OSC_SOURCE_LOOM "/loom" #define OSC_SOURCE_TRANSPARENCY "/transparency" #define OSC_SOURCE_DEPTH "/depth" #define OSC_SOURCE_GRAB "/grab" @@ -69,12 +71,12 @@ protected: void receiveOutputAttribute(const std::string &attribute, osc::ReceivedMessageArgumentStream arguments); - void receiveSourceAttribute(Source *target, const std::string &attribute, + bool receiveSourceAttribute(Source *target, const std::string &attribute, osc::ReceivedMessageArgumentStream arguments); void sendCurrentSourceAttibutes(const IpEndpointName& remoteEndpoint); - void sendSourcesStatus(const IpEndpointName& remoteEndpoint, float max_count = 0.f); - void sendStatus(const IpEndpointName& remoteEndpoint); + void sendSourcesStatus(const IpEndpointName& remoteEndpoint, osc::ReceivedMessageArgumentStream arguments); + void sendOutputStatus(const IpEndpointName& remoteEndpoint); private: diff --git a/SourceCallback.cpp b/SourceCallback.cpp index 3dad7e7..5fcf19b 100644 --- a/SourceCallback.cpp +++ b/SourceCallback.cpp @@ -39,6 +39,7 @@ void ResetGeometry::update(Source *s, float) SetAlpha::SetAlpha(float alpha) : SourceCallback(), alpha_(CLAMP(alpha, 0.f, 1.f)) { + pos_ = glm::vec2(); step_ = glm::normalize(glm::vec2(1.f, 1.f)); // step in diagonal by default } @@ -49,7 +50,6 @@ void SetAlpha::update(Source *s, float) if (!initialized_){ // initial position pos_ = glm::vec2(s->group(View::MIXING)->translation_); - // step in direction of source translation if possible if ( glm::length(pos_) > DELTA_ALPHA) step_ = glm::normalize(pos_); @@ -73,6 +73,53 @@ void SetAlpha::update(Source *s, float) finished_ = true; } + +Loom::Loom(float da, float duration) : SourceCallback(), speed_(da), + duration_(duration), progress_(0.f) +{ + pos_ = glm::vec2(); + step_ = glm::normalize(glm::vec2(1.f, 1.f)); // step in diagonal by default +} + +void Loom::update(Source *s, float dt) +{ + if (s && !s->locked()) { + // reset on first run or upon call of reset() + if (!initialized_){ + // start animation + progress_ = 0.f; + // initial position + pos_ = glm::vec2(s->group(View::MIXING)->translation_); + // step in direction of source translation if possible + if ( glm::length(pos_) > DELTA_ALPHA) + step_ = glm::normalize(pos_); + + initialized_ = true; + } + + // calculate amplitude of movement + progress_ += dt; + + // perform movement + pos_ += step_ * ( speed_ * dt * 0.001f); + + // apply alpha if valid in range [0 1] + float alpha = SourceCore::alphaFromCordinates(pos_.x, pos_.y); + if ( alpha > DELTA_ALPHA && alpha < 1.0 - DELTA_ALPHA ) + s->group(View::MIXING)->translation_ = glm::vec3(pos_, s->group(View::MIXING)->translation_.z); + + // timeout + if ( progress_ > duration_ ) { + // done + finished_ = true; + } + } + else + finished_ = true; +} + + + SetDepth::SetDepth(float target, float duration) : SourceCallback(), duration_(duration), progress_(0.f), start_(0.f), target_(CLAMP(target, MIN_DEPTH, MAX_DEPTH)) { @@ -194,8 +241,8 @@ void Resize::update(Source *s, float dt) progress_ += dt; // perform movement - glm::vec2 pos = start_ + speed_ * ( dt * 0.001f); - s->group(View::GEOMETRY)->scale_ = glm::vec3(pos, s->group(View::GEOMETRY)->scale_.z); + glm::vec2 scale = start_ + speed_ * ( dt * 0.001f); + s->group(View::GEOMETRY)->scale_ = glm::vec3(scale, s->group(View::GEOMETRY)->scale_.z); // timeout if ( progress_ > duration_ ) { diff --git a/SourceCallback.h b/SourceCallback.h index 988261e..514e34d 100644 --- a/SourceCallback.h +++ b/SourceCallback.h @@ -12,6 +12,7 @@ public: typedef enum { CALLBACK_GENERIC = 0, CALLBACK_ALPHA, + CALLBACK_LOOM, CALLBACK_DEPTH, CALLBACK_PLAY, CALLBACK_REPLAY, @@ -56,6 +57,20 @@ public: CallbackType type () override { return CALLBACK_ALPHA; } }; +class Loom : public SourceCallback +{ + float speed_; + glm::vec2 pos_; + glm::vec2 step_; + float duration_; + float progress_; + +public: + Loom(float da, float duration = 0.f); + void update(Source *s, float) override; + CallbackType type () override { return CALLBACK_LOOM; } +}; + class SetDepth : public SourceCallback { float duration_; @@ -92,7 +107,6 @@ class Grab : public SourceCallback { glm::vec2 speed_; glm::vec2 start_; - glm::vec2 target_; float duration_; float progress_; @@ -106,7 +120,6 @@ class Resize : public SourceCallback { glm::vec2 speed_; glm::vec2 start_; - glm::vec2 target_; float duration_; float progress_; @@ -120,7 +133,6 @@ class Turn : public SourceCallback { float speed_; float start_; - float target_; float duration_; float progress_; diff --git a/rsc/osc/vimix.mk1.touchosc b/rsc/osc/vimix.mk1.touchosc index 8f5075d..33cd296 100644 Binary files a/rsc/osc/vimix.mk1.touchosc and b/rsc/osc/vimix.mk1.touchosc differ diff --git a/rsc/osc/vimix_vertical.mk1.touchosc b/rsc/osc/vimix_vertical.mk1.touchosc new file mode 100644 index 0000000..c3f9788 Binary files /dev/null and b/rsc/osc/vimix_vertical.mk1.touchosc differ