mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 18:34:58 +01:00
Initial implementation of Control manager
Control manager will handle control actions, recorded or from OSC. Here skeleton for receiving OSC messages is in place. Cleanup of includes for NetworkToolkit. Touched a bit the BaseToolkit.
This commit is contained in:
@@ -141,16 +141,26 @@ std::string BaseToolkit::bits_to_string(long b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string BaseToolkit::trunc_string(const std::string& path, int N)
|
std::string BaseToolkit::truncated(const std::string& str, int N)
|
||||||
{
|
{
|
||||||
std::string trunc = path;
|
std::string trunc = str;
|
||||||
int l = path.size();
|
int l = str.size();
|
||||||
if ( l > N ) {
|
if ( l > N ) {
|
||||||
trunc = std::string("...") + path.substr( l - N + 3 );
|
trunc = std::string("...") + str.substr( l - N + 3 );
|
||||||
}
|
}
|
||||||
return trunc;
|
return trunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::list<std::string> BaseToolkit::splitted(const std::string& str, char delim) {
|
||||||
|
std::list<std::string> strings;
|
||||||
|
size_t start;
|
||||||
|
size_t end = 0;
|
||||||
|
while ((start = str.find_first_not_of(delim, end)) != std::string::npos) {
|
||||||
|
end = str.find(delim, start);
|
||||||
|
strings.push_back(str.substr(start, end - start));
|
||||||
|
}
|
||||||
|
return strings;
|
||||||
|
}
|
||||||
|
|
||||||
std::string BaseToolkit::common_prefix( const std::list<std::string> & allStrings )
|
std::string BaseToolkit::common_prefix( const std::list<std::string> & allStrings )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,8 +22,11 @@ std::string byte_to_string(long b);
|
|||||||
// get a string to display bit size with unit Kbit, MBit, Gbit, Tbit
|
// get a string to display bit size with unit Kbit, MBit, Gbit, Tbit
|
||||||
std::string bits_to_string(long b);
|
std::string bits_to_string(long b);
|
||||||
|
|
||||||
// Truncate a string to display the right most N characters (e.g. ./home/me/toto.mpg -> ...ome/me/toto.mpg)
|
// cut a string to display the right most N characters (e.g. /home/me/toto.mpg -> ...ome/me/toto.mpg)
|
||||||
std::string trunc_string(const std::string& path, int N);
|
std::string truncated(const std::string& str, int N);
|
||||||
|
|
||||||
|
// split a string into list of strings separated by delimitor (e.g. /home/me/toto.mpg -> {home, me, toto.mpg} )
|
||||||
|
std::list<std::string> splitted(const std::string& str, char delim);
|
||||||
|
|
||||||
// find common parts in a list of strings
|
// find common parts in a list of strings
|
||||||
std::string common_prefix(const std::list<std::string> &allStrings);
|
std::string common_prefix(const std::list<std::string> &allStrings);
|
||||||
|
|||||||
@@ -337,6 +337,7 @@ set(VMIX_SRCS
|
|||||||
ActionManager.cpp
|
ActionManager.cpp
|
||||||
Overlay.cpp
|
Overlay.cpp
|
||||||
Metronome.cpp
|
Metronome.cpp
|
||||||
|
ControlManager.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,28 +19,26 @@
|
|||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <vector>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "osc/OscOutboundPacketStream.h"
|
#include "osc/OscOutboundPacketStream.h"
|
||||||
|
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "Connection.h"
|
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "Streamer.h"
|
#include "Streamer.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
|
||||||
|
#include "Connection.h"
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
#define CONNECTION_DEBUG
|
#define CONNECTION_DEBUG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
Connection::Connection()
|
Connection::Connection() : receiver_(nullptr)
|
||||||
{
|
{
|
||||||
receiver_ = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Connection::~Connection()
|
Connection::~Connection()
|
||||||
{
|
{
|
||||||
if (receiver_!=nullptr) {
|
if (receiver_!=nullptr) {
|
||||||
@@ -226,7 +224,7 @@ void Connection::ask()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionRequestListener::ProcessMessage( const osc::ReceivedMessage& m,
|
void Connection::RequestListener::ProcessMessage( const osc::ReceivedMessage& m,
|
||||||
const IpEndpointName& remoteEndpoint )
|
const IpEndpointName& remoteEndpoint )
|
||||||
{
|
{
|
||||||
char sender[IpEndpointName::ADDRESS_AND_PORT_STRING_LENGTH];
|
char sender[IpEndpointName::ADDRESS_AND_PORT_STRING_LENGTH];
|
||||||
|
|||||||
27
Connection.h
27
Connection.h
@@ -1,22 +1,17 @@
|
|||||||
#ifndef CONNECTION_H
|
#ifndef CONNECTION_H
|
||||||
#define CONNECTION_H
|
#define CONNECTION_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "osc/OscReceivedElements.h"
|
|
||||||
#include "osc/OscPacketListener.h"
|
|
||||||
#include "ip/UdpSocket.h"
|
|
||||||
|
|
||||||
#include "NetworkToolkit.h"
|
#include "NetworkToolkit.h"
|
||||||
|
|
||||||
|
#define MAX_HANDSHAKE 20
|
||||||
|
#define HANDSHAKE_PORT 71310
|
||||||
|
#define STREAM_REQUEST_PORT 71510
|
||||||
|
#define OSC_DIALOG_PORT 71010
|
||||||
#define ALIVE 3
|
#define ALIVE 3
|
||||||
|
|
||||||
class ConnectionRequestListener : public osc::OscPacketListener {
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void ProcessMessage( const osc::ReceivedMessage& m,
|
|
||||||
const IpEndpointName& remoteEndpoint );
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ConnectionInfo {
|
struct ConnectionInfo {
|
||||||
|
|
||||||
@@ -58,8 +53,6 @@ struct ConnectionInfo {
|
|||||||
|
|
||||||
class Connection
|
class Connection
|
||||||
{
|
{
|
||||||
friend class ConnectionRequestListener;
|
|
||||||
|
|
||||||
// Private Constructor
|
// Private Constructor
|
||||||
Connection();
|
Connection();
|
||||||
Connection(Connection const& copy) = delete;
|
Connection(Connection const& copy) = delete;
|
||||||
@@ -82,11 +75,19 @@ public:
|
|||||||
int index(const std::string &name) const;
|
int index(const std::string &name) const;
|
||||||
ConnectionInfo info(int index = 0); // index 0 for self
|
ConnectionInfo info(int index = 0); // index 0 for self
|
||||||
|
|
||||||
|
protected:
|
||||||
|
class RequestListener : public osc::OscPacketListener {
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void ProcessMessage( const osc::ReceivedMessage& m,
|
||||||
|
const IpEndpointName& remoteEndpoint );
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static void ask();
|
static void ask();
|
||||||
static void listen();
|
static void listen();
|
||||||
ConnectionRequestListener listener_;
|
RequestListener listener_;
|
||||||
UdpListeningReceiveSocket *receiver_;
|
UdpListeningReceiveSocket *receiver_;
|
||||||
|
|
||||||
std::vector< ConnectionInfo > connections_;
|
std::vector< ConnectionInfo > connections_;
|
||||||
|
|||||||
110
ControlManager.cpp
Normal file
110
ControlManager.cpp
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of vimix - video live mixer
|
||||||
|
*
|
||||||
|
* **Copyright** (C) 2020-2021 Bruno Herbelin <bruno.herbelin@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "osc/OscOutboundPacketStream.h"
|
||||||
|
|
||||||
|
#include "Log.h"
|
||||||
|
#include "Settings.h"
|
||||||
|
#include "BaseToolkit.h"
|
||||||
|
|
||||||
|
#include "ControlManager.h"
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#define CONTROL_DEBUG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void Control::RequestListener::ProcessMessage( const osc::ReceivedMessage& m,
|
||||||
|
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());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::list<std::string> address = BaseToolkit::splitted(m.AddressPattern(), '/');
|
||||||
|
|
||||||
|
if (address.size() == 3 && address.front().compare(APP_NAME) == 0 ){
|
||||||
|
address.pop_front();
|
||||||
|
Log::Info("Wellformed vimix message %s.", address.front().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Control::listen()
|
||||||
|
{
|
||||||
|
#ifdef CONTROL_DEBUG
|
||||||
|
Log::Info("Accepting OSC messages on port %d", Settings::application.control.osc_port);
|
||||||
|
#endif
|
||||||
|
if (Control::manager().receiver_)
|
||||||
|
Control::manager().receiver_->Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Control::Control() : receiver_(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Control::~Control()
|
||||||
|
{
|
||||||
|
if (receiver_!=nullptr) {
|
||||||
|
receiver_->Break();
|
||||||
|
delete receiver_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Control::init()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// try to create listenning socket
|
||||||
|
// through exception runtime if fails
|
||||||
|
receiver_ = new UdpListeningReceiveSocket( IpEndpointName( IpEndpointName::ANY_ADDRESS,
|
||||||
|
Settings::application.control.osc_port ), &listener_ );
|
||||||
|
}
|
||||||
|
catch (const std::runtime_error&) {
|
||||||
|
// arg, the receiver could not be initialized
|
||||||
|
// because the port was not available
|
||||||
|
receiver_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// listen for answers
|
||||||
|
std::thread(listen).detach();
|
||||||
|
|
||||||
|
return receiver_ != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Control::terminate()
|
||||||
|
{
|
||||||
|
if (receiver_!=nullptr)
|
||||||
|
receiver_->AsynchronousBreak();
|
||||||
|
}
|
||||||
43
ControlManager.h
Normal file
43
ControlManager.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#ifndef CONTROL_H
|
||||||
|
#define CONTROL_H
|
||||||
|
|
||||||
|
#include "NetworkToolkit.h"
|
||||||
|
|
||||||
|
class Control
|
||||||
|
{
|
||||||
|
// Private Constructor
|
||||||
|
Control();
|
||||||
|
Control(Control const& copy) = delete;
|
||||||
|
Control& operator=(Control const& copy) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static Control& manager ()
|
||||||
|
{
|
||||||
|
// The only instance
|
||||||
|
static Control _instance;
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
~Control();
|
||||||
|
|
||||||
|
bool init();
|
||||||
|
void terminate();
|
||||||
|
|
||||||
|
// void setOscPort(int P);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
class RequestListener : public osc::OscPacketListener {
|
||||||
|
protected:
|
||||||
|
virtual void ProcessMessage( const osc::ReceivedMessage& m,
|
||||||
|
const IpEndpointName& remoteEndpoint );
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static void listen();
|
||||||
|
RequestListener listener_;
|
||||||
|
UdpListeningReceiveSocket *receiver_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONTROL_H
|
||||||
@@ -582,7 +582,7 @@ void ImGuiVisitor::visit (MediaSource& s)
|
|||||||
|
|
||||||
// folder
|
// folder
|
||||||
std::string path = SystemToolkit::path_filename(s.path());
|
std::string path = SystemToolkit::path_filename(s.path());
|
||||||
std::string label = BaseToolkit::trunc_string(path, 25);
|
std::string label = BaseToolkit::truncated(path, 25);
|
||||||
label = BaseToolkit::transliterate(label);
|
label = BaseToolkit::transliterate(label);
|
||||||
ImGuiToolkit::ButtonOpenUrl( label.c_str(), path.c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0) );
|
ImGuiToolkit::ButtonOpenUrl( label.c_str(), path.c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0) );
|
||||||
|
|
||||||
@@ -637,7 +637,7 @@ void ImGuiVisitor::visit (SessionFileSource& s)
|
|||||||
ImGui::Text("File");
|
ImGui::Text("File");
|
||||||
|
|
||||||
std::string path = SystemToolkit::path_filename(s.path());
|
std::string path = SystemToolkit::path_filename(s.path());
|
||||||
std::string label = BaseToolkit::trunc_string(path, 25);
|
std::string label = BaseToolkit::truncated(path, 25);
|
||||||
label = BaseToolkit::transliterate(label);
|
label = BaseToolkit::transliterate(label);
|
||||||
ImGuiToolkit::ButtonOpenUrl( label.c_str(), path.c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0) );
|
ImGuiToolkit::ButtonOpenUrl( label.c_str(), path.c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0) );
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
@@ -864,7 +864,7 @@ void ImGuiVisitor::visit (MultiFileSource& s)
|
|||||||
|
|
||||||
// offer to open file browser at location
|
// offer to open file browser at location
|
||||||
std::string path = SystemToolkit::path_filename(s.sequence().location);
|
std::string path = SystemToolkit::path_filename(s.sequence().location);
|
||||||
std::string label = BaseToolkit::trunc_string(path, 25);
|
std::string label = BaseToolkit::truncated(path, 25);
|
||||||
label = BaseToolkit::transliterate(label);
|
label = BaseToolkit::transliterate(label);
|
||||||
ImGuiToolkit::ButtonOpenUrl( label.c_str(), path.c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0) );
|
ImGuiToolkit::ButtonOpenUrl( label.c_str(), path.c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0) );
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|||||||
@@ -27,13 +27,14 @@
|
|||||||
#include <gst/pbutils/pbutils.h>
|
#include <gst/pbutils/pbutils.h>
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
#include "osc/OscOutboundPacketStream.h"
|
||||||
|
|
||||||
#include "SystemToolkit.h"
|
#include "SystemToolkit.h"
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "Stream.h"
|
#include "Stream.h"
|
||||||
#include "Decorations.h"
|
#include "Decorations.h"
|
||||||
#include "Visitor.h"
|
#include "Visitor.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "Connection.h"
|
|
||||||
|
|
||||||
#include "NetworkSource.h"
|
#include "NetworkSource.h"
|
||||||
|
|
||||||
@@ -43,7 +44,7 @@
|
|||||||
|
|
||||||
|
|
||||||
// this is called when receiving an answer for streaming request
|
// this is called when receiving an answer for streaming request
|
||||||
void StreamerResponseListener::ProcessMessage( const osc::ReceivedMessage& m,
|
void NetworkStream::ResponseListener::ProcessMessage( const osc::ReceivedMessage& m,
|
||||||
const IpEndpointName& remoteEndpoint )
|
const IpEndpointName& remoteEndpoint )
|
||||||
{
|
{
|
||||||
char sender[IpEndpointName::ADDRESS_AND_PORT_STRING_LENGTH];
|
char sender[IpEndpointName::ADDRESS_AND_PORT_STRING_LENGTH];
|
||||||
|
|||||||
@@ -1,33 +1,13 @@
|
|||||||
#ifndef NETWORKSOURCE_H
|
#ifndef NETWORKSOURCE_H
|
||||||
#define NETWORKSOURCE_H
|
#define NETWORKSOURCE_H
|
||||||
|
|
||||||
#include "osc/OscReceivedElements.h"
|
|
||||||
#include "osc/OscPacketListener.h"
|
|
||||||
#include "osc/OscOutboundPacketStream.h"
|
|
||||||
#include "ip/UdpSocket.h"
|
|
||||||
|
|
||||||
#include "NetworkToolkit.h"
|
#include "NetworkToolkit.h"
|
||||||
#include "Connection.h"
|
#include "Connection.h"
|
||||||
#include "StreamSource.h"
|
#include "StreamSource.h"
|
||||||
|
|
||||||
class NetworkStream;
|
|
||||||
|
|
||||||
class StreamerResponseListener : public osc::OscPacketListener
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
class NetworkStream *parent_;
|
|
||||||
virtual void ProcessMessage( const osc::ReceivedMessage& m,
|
|
||||||
const IpEndpointName& remoteEndpoint );
|
|
||||||
public:
|
|
||||||
inline void setParent(NetworkStream *s) { parent_ = s; }
|
|
||||||
StreamerResponseListener() : parent_(nullptr) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class NetworkStream : public Stream
|
class NetworkStream : public Stream
|
||||||
{
|
{
|
||||||
friend class StreamerResponseListener;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
NetworkStream();
|
NetworkStream();
|
||||||
@@ -43,10 +23,22 @@ public:
|
|||||||
std::string clientAddress() const;
|
std::string clientAddress() const;
|
||||||
std::string serverAddress() const;
|
std::string serverAddress() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
class ResponseListener : public osc::OscPacketListener
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
class NetworkStream *parent_;
|
||||||
|
virtual void ProcessMessage( const osc::ReceivedMessage& m,
|
||||||
|
const IpEndpointName& remoteEndpoint );
|
||||||
|
public:
|
||||||
|
inline void setParent(NetworkStream *s) { parent_ = s; }
|
||||||
|
ResponseListener() : parent_(nullptr) {}
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// connection information
|
// connection information
|
||||||
ConnectionInfo streamer_;
|
ConnectionInfo streamer_;
|
||||||
StreamerResponseListener listener_;
|
ResponseListener listener_;
|
||||||
UdpListeningReceiveSocket *receiver_;
|
UdpListeningReceiveSocket *receiver_;
|
||||||
std::atomic<bool> received_config_;
|
std::atomic<bool> received_config_;
|
||||||
std::atomic<bool> connected_;
|
std::atomic<bool> connected_;
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "osc/OscReceivedElements.h"
|
||||||
|
#include "osc/OscPacketListener.h"
|
||||||
|
#include "ip/UdpSocket.h"
|
||||||
|
|
||||||
#define OSC_PREFIX "/vimix"
|
#define OSC_PREFIX "/vimix"
|
||||||
#define OSC_PING "/ping"
|
#define OSC_PING "/ping"
|
||||||
#define OSC_PONG "/pong"
|
#define OSC_PONG "/pong"
|
||||||
@@ -12,11 +16,6 @@
|
|||||||
#define OSC_STREAM_REJECT "/reject"
|
#define OSC_STREAM_REJECT "/reject"
|
||||||
#define OSC_STREAM_DISCONNECT "/disconnect"
|
#define OSC_STREAM_DISCONNECT "/disconnect"
|
||||||
|
|
||||||
#define STREAMING_FPS 30
|
|
||||||
#define MAX_HANDSHAKE 20
|
|
||||||
#define HANDSHAKE_PORT 71310
|
|
||||||
#define STREAM_REQUEST_PORT 71510
|
|
||||||
#define OSC_DIALOG_PORT 71010
|
|
||||||
#define IP_MTU_SIZE 1536
|
#define IP_MTU_SIZE 1536
|
||||||
|
|
||||||
namespace NetworkToolkit
|
namespace NetworkToolkit
|
||||||
|
|||||||
12
Settings.h
12
Settings.h
@@ -189,6 +189,15 @@ struct TimerConfig
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ControllerConfig
|
||||||
|
{
|
||||||
|
int osc_port;
|
||||||
|
|
||||||
|
ControllerConfig() {
|
||||||
|
osc_port = OSC_DEFAULT_PORT;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct Application
|
struct Application
|
||||||
{
|
{
|
||||||
// instance check
|
// instance check
|
||||||
@@ -237,6 +246,9 @@ struct Application
|
|||||||
// settings transition
|
// settings transition
|
||||||
TransitionConfig transition;
|
TransitionConfig transition;
|
||||||
|
|
||||||
|
// settings controller
|
||||||
|
ControllerConfig control;
|
||||||
|
|
||||||
// multiple windows handling
|
// multiple windows handling
|
||||||
std::vector<WindowConfig> windows;
|
std::vector<WindowConfig> windows;
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,8 @@
|
|||||||
// gstreamer
|
// gstreamer
|
||||||
#include <gst/gstformat.h>
|
#include <gst/gstformat.h>
|
||||||
#include <gst/video/video.h>
|
#include <gst/video/video.h>
|
||||||
|
#include <gst/app/gstappsrc.h>
|
||||||
|
#include <gst/pbutils/pbutils.h>
|
||||||
|
|
||||||
//osc
|
//osc
|
||||||
#include "osc/OscOutboundPacketStream.h"
|
#include "osc/OscOutboundPacketStream.h"
|
||||||
@@ -52,7 +54,7 @@
|
|||||||
#define STREAMER_DEBUG
|
#define STREAMER_DEBUG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void StreamingRequestListener::ProcessMessage( const osc::ReceivedMessage& m,
|
void Streaming::RequestListener::ProcessMessage( const osc::ReceivedMessage& m,
|
||||||
const IpEndpointName& remoteEndpoint )
|
const IpEndpointName& remoteEndpoint )
|
||||||
{
|
{
|
||||||
char sender[IpEndpointName::ADDRESS_AND_PORT_STRING_LENGTH];
|
char sender[IpEndpointName::ADDRESS_AND_PORT_STRING_LENGTH];
|
||||||
|
|||||||
27
Streamer.h
27
Streamer.h
@@ -3,31 +3,15 @@
|
|||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include <gst/pbutils/pbutils.h>
|
|
||||||
#include <gst/app/gstappsrc.h>
|
|
||||||
|
|
||||||
#include "osc/OscReceivedElements.h"
|
|
||||||
#include "osc/OscPacketListener.h"
|
|
||||||
#include "ip/UdpSocket.h"
|
|
||||||
|
|
||||||
#include "NetworkToolkit.h"
|
#include "NetworkToolkit.h"
|
||||||
#include "FrameGrabber.h"
|
#include "FrameGrabber.h"
|
||||||
|
|
||||||
|
#define STREAMING_FPS 30
|
||||||
|
|
||||||
class Session;
|
|
||||||
class VideoStreamer;
|
class VideoStreamer;
|
||||||
|
|
||||||
class StreamingRequestListener : public osc::OscPacketListener {
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void ProcessMessage( const osc::ReceivedMessage& m,
|
|
||||||
const IpEndpointName& remoteEndpoint );
|
|
||||||
};
|
|
||||||
|
|
||||||
class Streaming
|
class Streaming
|
||||||
{
|
{
|
||||||
friend class StreamingRequestListener;
|
|
||||||
|
|
||||||
// Private Constructor
|
// Private Constructor
|
||||||
Streaming();
|
Streaming();
|
||||||
Streaming(Streaming const& copy) = delete;
|
Streaming(Streaming const& copy) = delete;
|
||||||
@@ -53,13 +37,20 @@ public:
|
|||||||
std::vector<std::string> listStreams();
|
std::vector<std::string> listStreams();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
class RequestListener : public osc::OscPacketListener {
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void ProcessMessage( const osc::ReceivedMessage& m,
|
||||||
|
const IpEndpointName& remoteEndpoint );
|
||||||
|
};
|
||||||
void addStream(const std::string &sender, int reply_to, const std::string &clientname);
|
void addStream(const std::string &sender, int reply_to, const std::string &clientname);
|
||||||
void refuseStream(const std::string &sender, int reply_to);
|
void refuseStream(const std::string &sender, int reply_to);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool enabled_;
|
bool enabled_;
|
||||||
StreamingRequestListener listener_;
|
RequestListener listener_;
|
||||||
UdpListeningReceiveSocket *receiver_;
|
UdpListeningReceiveSocket *receiver_;
|
||||||
|
|
||||||
std::vector<VideoStreamer *> streamers_;
|
std::vector<VideoStreamer *> streamers_;
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ bool SystemToolkit::file_exists(const string& path)
|
|||||||
|
|
||||||
|
|
||||||
// tests if dir is a directory and return its path, empty string otherwise
|
// tests if dir is a directory and return its path, empty string otherwise
|
||||||
std::string SystemToolkit::path_directory(const std::string& path)
|
string SystemToolkit::path_directory(const string& path)
|
||||||
{
|
{
|
||||||
string directorypath = "";
|
string directorypath = "";
|
||||||
|
|
||||||
@@ -359,13 +359,13 @@ void SystemToolkit::execute(const string& command)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
vector<string> split(const string& str, char delim) {
|
vector<string> split_path(const string& path) {
|
||||||
vector<string> strings;
|
vector<string> strings;
|
||||||
size_t start;
|
size_t start;
|
||||||
size_t end = 0;
|
size_t end = 0;
|
||||||
while ((start = str.find_first_not_of(delim, end)) != string::npos) {
|
while ((start = path.find_first_not_of(PATH_SEP, end)) != string::npos) {
|
||||||
end = str.find(delim, start);
|
end = path.find(PATH_SEP, start);
|
||||||
strings.push_back(str.substr(start, end - start));
|
strings.push_back(path.substr(start, end - start));
|
||||||
}
|
}
|
||||||
return strings;
|
return strings;
|
||||||
}
|
}
|
||||||
@@ -376,8 +376,8 @@ vector<string> split(const string& str, char delim) {
|
|||||||
string SystemToolkit::path_relative_to_path( const string& absolutePath, const string& relativeTo )
|
string SystemToolkit::path_relative_to_path( const string& absolutePath, const string& relativeTo )
|
||||||
{
|
{
|
||||||
string relativePath = "";
|
string relativePath = "";
|
||||||
vector<string> absoluteDirectories = split(absolutePath, PATH_SEP);
|
vector<string> absoluteDirectories = split_path(absolutePath);
|
||||||
vector<string> relativeToDirectories = split(relativeTo, PATH_SEP);
|
vector<string> relativeToDirectories = split_path(relativeTo);
|
||||||
|
|
||||||
// Get the shortest of the two paths
|
// Get the shortest of the two paths
|
||||||
size_t length = MINI( absoluteDirectories.size(), relativeToDirectories.size() );
|
size_t length = MINI( absoluteDirectories.size(), relativeToDirectories.size() );
|
||||||
@@ -415,11 +415,11 @@ string SystemToolkit::path_relative_to_path( const string& absolutePath, const s
|
|||||||
return relativePath;
|
return relativePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SystemToolkit::path_absolute_from_path(const std::string& relativePath, const std::string& relativeTo)
|
string SystemToolkit::path_absolute_from_path(const string& relativePath, const string& relativeTo)
|
||||||
{
|
{
|
||||||
string absolutePath = string(1, PATH_SEP);
|
string absolutePath = string(1, PATH_SEP);
|
||||||
vector<string> relativeDirectories = split(relativePath, PATH_SEP);
|
vector<string> relativeDirectories = split_path(relativePath);
|
||||||
vector<string> relativeToDirectories = split(relativeTo, PATH_SEP);
|
vector<string> relativeToDirectories = split_path(relativeTo);
|
||||||
|
|
||||||
// how many ".."
|
// how many ".."
|
||||||
size_t count_relative = 0;
|
size_t count_relative = 0;
|
||||||
|
|||||||
@@ -4349,7 +4349,7 @@ void Navigator::RenderNewPannel()
|
|||||||
|
|
||||||
// combo to offer lists
|
// combo to offer lists
|
||||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||||
if (ImGui::BeginCombo("##SelectionNewMedia", BaseToolkit::trunc_string(Settings::application.recentImportFolders.path, 25).c_str() ))
|
if (ImGui::BeginCombo("##SelectionNewMedia", BaseToolkit::truncated(Settings::application.recentImportFolders.path, 25).c_str() ))
|
||||||
{
|
{
|
||||||
// Mode MEDIA_RECENT : recent files
|
// Mode MEDIA_RECENT : recent files
|
||||||
if (ImGui::Selectable( ICON_FA_LIST_OL IMGUI_LABEL_RECENT_FILES) ) {
|
if (ImGui::Selectable( ICON_FA_LIST_OL IMGUI_LABEL_RECENT_FILES) ) {
|
||||||
@@ -4362,7 +4362,7 @@ void Navigator::RenderNewPannel()
|
|||||||
// Mode MEDIA_FOLDER : known folders
|
// Mode MEDIA_FOLDER : known folders
|
||||||
for(auto foldername = Settings::application.recentImportFolders.filenames.begin();
|
for(auto foldername = Settings::application.recentImportFolders.filenames.begin();
|
||||||
foldername != Settings::application.recentImportFolders.filenames.end(); foldername++) {
|
foldername != Settings::application.recentImportFolders.filenames.end(); foldername++) {
|
||||||
std::string f = std::string(ICON_FA_FOLDER) + " " + BaseToolkit::trunc_string( *foldername, 40);
|
std::string f = std::string(ICON_FA_FOLDER) + " " + BaseToolkit::truncated( *foldername, 40);
|
||||||
if (ImGui::Selectable( f.c_str() )) {
|
if (ImGui::Selectable( f.c_str() )) {
|
||||||
setNewMedia(MEDIA_FOLDER, *foldername);
|
setNewMedia(MEDIA_FOLDER, *foldername);
|
||||||
}
|
}
|
||||||
@@ -4458,7 +4458,7 @@ void Navigator::RenderNewPannel()
|
|||||||
for(auto it = sourceMediaFiles.begin(); it != sourceMediaFiles.end(); ++it) {
|
for(auto it = sourceMediaFiles.begin(); it != sourceMediaFiles.end(); ++it) {
|
||||||
// build displayed file name
|
// build displayed file name
|
||||||
std::string filename = BaseToolkit::transliterate(*it);
|
std::string filename = BaseToolkit::transliterate(*it);
|
||||||
std::string label = BaseToolkit::trunc_string(SystemToolkit::filename(filename), 25);
|
std::string label = BaseToolkit::truncated(SystemToolkit::filename(filename), 25);
|
||||||
// add selectable item to ListBox; open if clickec
|
// add selectable item to ListBox; open if clickec
|
||||||
if (ImGui::Selectable( label.c_str(), sourceMediaFileCurrent.compare(*it) == 0 )) {
|
if (ImGui::Selectable( label.c_str(), sourceMediaFileCurrent.compare(*it) == 0 )) {
|
||||||
// set new source preview
|
// set new source preview
|
||||||
@@ -4721,7 +4721,7 @@ void Navigator::RenderMainPannelVimix()
|
|||||||
|
|
||||||
// Show combo box of quick selection modes
|
// Show combo box of quick selection modes
|
||||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||||
if (ImGui::BeginCombo("##SelectionSession", BaseToolkit::trunc_string(Settings::application.recentFolders.path, 25).c_str() )) {
|
if (ImGui::BeginCombo("##SelectionSession", BaseToolkit::truncated(Settings::application.recentFolders.path, 25).c_str() )) {
|
||||||
|
|
||||||
// Mode 0 : recent files
|
// Mode 0 : recent files
|
||||||
if (ImGui::Selectable( ICON_FA_LIST_OL IMGUI_LABEL_RECENT_FILES) ) {
|
if (ImGui::Selectable( ICON_FA_LIST_OL IMGUI_LABEL_RECENT_FILES) ) {
|
||||||
@@ -4732,7 +4732,7 @@ void Navigator::RenderMainPannelVimix()
|
|||||||
// Mode 1 : known folders
|
// Mode 1 : known folders
|
||||||
for(auto foldername = Settings::application.recentFolders.filenames.begin();
|
for(auto foldername = Settings::application.recentFolders.filenames.begin();
|
||||||
foldername != Settings::application.recentFolders.filenames.end(); foldername++) {
|
foldername != Settings::application.recentFolders.filenames.end(); foldername++) {
|
||||||
std::string f = std::string(ICON_FA_FOLDER) + " " + BaseToolkit::trunc_string( *foldername, 40);
|
std::string f = std::string(ICON_FA_FOLDER) + " " + BaseToolkit::truncated( *foldername, 40);
|
||||||
if (ImGui::Selectable( f.c_str() )) {
|
if (ImGui::Selectable( f.c_str() )) {
|
||||||
// remember which path was selected
|
// remember which path was selected
|
||||||
Settings::application.recentFolders.path.assign(*foldername);
|
Settings::application.recentFolders.path.assign(*foldername);
|
||||||
@@ -5017,7 +5017,7 @@ void Navigator::RenderMainPannelVimix()
|
|||||||
{
|
{
|
||||||
// Folder
|
// Folder
|
||||||
std::string path = SystemToolkit::path_filename(sessionfilename);
|
std::string path = SystemToolkit::path_filename(sessionfilename);
|
||||||
std::string label = BaseToolkit::trunc_string(path, 23);
|
std::string label = BaseToolkit::truncated(path, 23);
|
||||||
label = BaseToolkit::transliterate(label);
|
label = BaseToolkit::transliterate(label);
|
||||||
ImGuiToolkit::ButtonOpenUrl( label.c_str(), path.c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0) );
|
ImGuiToolkit::ButtonOpenUrl( label.c_str(), path.c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0) );
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
@@ -5607,7 +5607,7 @@ void SourcePreview::setSource(Source *s, const string &label)
|
|||||||
delete source_;
|
delete source_;
|
||||||
|
|
||||||
source_ = s;
|
source_ = s;
|
||||||
label_ = BaseToolkit::trunc_string(label, 35);
|
label_ = BaseToolkit::truncated(label, 35);
|
||||||
reset_ = true;
|
reset_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -105,4 +105,6 @@
|
|||||||
|
|
||||||
#define USE_GST_APPSINK_CALLBACKS
|
#define USE_GST_APPSINK_CALLBACKS
|
||||||
|
|
||||||
|
#define OSC_DEFAULT_PORT 7000
|
||||||
|
|
||||||
#endif // VMIX_DEFINES_H
|
#endif // VMIX_DEFINES_H
|
||||||
|
|||||||
12
main.cpp
12
main.cpp
@@ -27,6 +27,7 @@
|
|||||||
#include "Mixer.h"
|
#include "Mixer.h"
|
||||||
#include "RenderingManager.h"
|
#include "RenderingManager.h"
|
||||||
#include "UserInterfaceManager.h"
|
#include "UserInterfaceManager.h"
|
||||||
|
#include "ControlManager.h"
|
||||||
#include "Connection.h"
|
#include "Connection.h"
|
||||||
#include "Metronome.h"
|
#include "Metronome.h"
|
||||||
|
|
||||||
@@ -91,6 +92,12 @@ int main(int argc, char *argv[])
|
|||||||
if ( !Connection::manager().init() )
|
if ( !Connection::manager().init() )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// CONTROLLER INIT
|
||||||
|
///
|
||||||
|
if ( !Control::manager().init() )
|
||||||
|
return 1;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// METRONOME INIT
|
/// METRONOME INIT
|
||||||
///
|
///
|
||||||
@@ -151,6 +158,11 @@ int main(int argc, char *argv[])
|
|||||||
///
|
///
|
||||||
Metronome::manager().terminate();
|
Metronome::manager().terminate();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// CONTROLLER TERMINATE
|
||||||
|
///
|
||||||
|
Control::manager().terminate();
|
||||||
|
|
||||||
///
|
///
|
||||||
/// CONNECTION TERMINATE
|
/// CONNECTION TERMINATE
|
||||||
///
|
///
|
||||||
|
|||||||
Reference in New Issue
Block a user