mirror of
https://github.com/storytold/UE4-OSC.git
synced 2026-10-23 08:05:29 +00:00
add multicast
This commit is contained in:
@@ -16,11 +16,9 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto settings = GetMutableDefault<UOscSettings>();
|
|
||||||
|
|
||||||
_dispatcher = UOscDispatcher::Get();
|
_dispatcher = UOscDispatcher::Get();
|
||||||
_dispatcher->Listen(settings->ReceivePort);
|
|
||||||
settings->UpdateSendAddresses();
|
HandleSettingsSaved();
|
||||||
|
|
||||||
// register settings
|
// register settings
|
||||||
ISettingsModule* settingsModule = ISettingsModule::Get();
|
ISettingsModule* settingsModule = ISettingsModule::Get();
|
||||||
@@ -29,6 +27,7 @@ public:
|
|||||||
FSettingsSectionDelegates settingsDelegates;
|
FSettingsSectionDelegates settingsDelegates;
|
||||||
settingsDelegates.ModifiedDelegate = FOnSettingsSectionModified::CreateRaw(this, &FOscModule::HandleSettingsSaved);
|
settingsDelegates.ModifiedDelegate = FOnSettingsSectionModified::CreateRaw(this, &FOscModule::HandleSettingsSaved);
|
||||||
|
|
||||||
|
auto settings = GetMutableDefault<UOscSettings>();
|
||||||
settingsModule->RegisterSettings("Project", "Plugins", "OSC",
|
settingsModule->RegisterSettings("Project", "Plugins", "OSC",
|
||||||
LOCTEXT("OscSettingsName", "OSC"),
|
LOCTEXT("OscSettingsName", "OSC"),
|
||||||
LOCTEXT("OscSettingsDescription", "Configure the OSC plug-in."),
|
LOCTEXT("OscSettingsDescription", "Configure the OSC plug-in."),
|
||||||
@@ -54,13 +53,31 @@ public:
|
|||||||
|
|
||||||
bool HandleSettingsSaved()
|
bool HandleSettingsSaved()
|
||||||
{
|
{
|
||||||
UE_LOG(LogOSC, Display, TEXT("Update settings"));
|
if(!_dispatcher.IsValid())
|
||||||
UOscSettings* settings = GetMutableDefault<UOscSettings>();
|
|
||||||
if(_dispatcher.IsValid())
|
|
||||||
{
|
{
|
||||||
_dispatcher->Listen(settings->ReceivePort);
|
UE_LOG(LogOSC, Warning, TEXT("Cannot update settings"));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UE_LOG(LogOSC, Display, TEXT("Update settings"));
|
||||||
|
|
||||||
|
auto settings = GetMutableDefault<UOscSettings>();
|
||||||
|
|
||||||
|
// receive settings
|
||||||
|
FIPv4Address receiveAddress(0);
|
||||||
|
uint32_t receivePort;
|
||||||
|
if(UOscSettings::Parse(settings->ReceiveFrom, &receiveAddress, &receivePort))
|
||||||
|
{
|
||||||
|
_dispatcher->Listen(receiveAddress, receivePort);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UE_LOG(LogOSC, Warning, TEXT("Fail to parse receive address: %s"), *settings->ReceiveFrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// send settings
|
||||||
settings->UpdateSendAddresses();
|
settings->UpdateSendAddresses();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
UOscSettings::UOscSettings( const class FPostConstructInitializeProperties& PCIP )
|
UOscSettings::UOscSettings( const class FPostConstructInitializeProperties& PCIP )
|
||||||
: Super(PCIP),
|
: Super(PCIP),
|
||||||
ReceivePort(8000),
|
ReceiveFrom("8000"),
|
||||||
_sendSocket(FUdpSocketBuilder(TEXT("OscSender")).Build())
|
_sendSocket(FUdpSocketBuilder(TEXT("OscSender")).Build())
|
||||||
{
|
{
|
||||||
SendTargets.Add(TEXT("127.0.0.1:8000"));
|
SendTargets.Add(TEXT("127.0.0.1:8000"));
|
||||||
@@ -21,18 +21,18 @@ void UOscSettings::UpdateSendAddresses()
|
|||||||
|
|
||||||
if(_sendAddresses[i].first != SendTargets[i])
|
if(_sendAddresses[i].first != SendTargets[i])
|
||||||
{
|
{
|
||||||
int32 sep = 0;
|
FIPv4Address address(0);
|
||||||
bool isValid = false;
|
uint32_t port;
|
||||||
if(SendTargets[i].FindChar(TEXT(':'), sep))
|
if(Parse(SendTargets[i], &address, &port) && address != FIPv4Address::Any)
|
||||||
{
|
{
|
||||||
const FString ip = SendTargets[i].Left(sep).Trim();
|
_sendAddresses[i].second->SetIp(address.GetValue());
|
||||||
_sendAddresses[i].second->SetIp(&ip.GetCharArray()[0], isValid);
|
_sendAddresses[i].second->SetPort(port);
|
||||||
if(isValid)
|
|
||||||
{
|
_sendAddresses[i].first = SendTargets[i];
|
||||||
const int32 port = FCString::Atoi(&SendTargets[i].GetCharArray()[sep+1]);
|
}
|
||||||
_sendAddresses[i].second->SetPort(port);
|
else
|
||||||
_sendAddresses[i].first = SendTargets[i];
|
{
|
||||||
}
|
UE_LOG(LogOSC, Warning, TEXT("Fail to parse or invalid send address: %s"), *SendTargets[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -56,3 +56,34 @@ void UOscSettings::Send(const uint8 *buffer, int32 length, int32 targetIndex)
|
|||||||
UE_LOG(LogOSC, Warning, TEXT("Cannot send OSC: invalid targetIndex %d"), targetIndex);
|
UE_LOG(LogOSC, Warning, TEXT("Cannot send OSC: invalid targetIndex %d"), targetIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UOscSettings::Parse(const FString & address_port, FIPv4Address * address, uint32_t * port)
|
||||||
|
{
|
||||||
|
if(address_port.IsEmpty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FIPv4Address addressResult(0);
|
||||||
|
uint32_t portResult;
|
||||||
|
|
||||||
|
int32 sep = -1;
|
||||||
|
if(address_port.FindChar(TEXT(':'), sep))
|
||||||
|
{
|
||||||
|
const auto ip = address_port.Left(sep).Trim();
|
||||||
|
if(!FIPv4Address::Parse(ip, addressResult))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
portResult = FCString::Atoi(&address_port.GetCharArray()[sep+1]);
|
||||||
|
if(portResult == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*address = addressResult;
|
||||||
|
*port = portResult;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,8 +13,16 @@ class UOscSettings : public UObject
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify the [address:]port to listen to.
|
||||||
|
*
|
||||||
|
* e.g.
|
||||||
|
* - "8000" listen to messages from any sender on port 8000. [default]
|
||||||
|
* - "224.0.0.100:8000" listen multi-cast messages of group 224.0.0.100 on port 8000.
|
||||||
|
* - "192.168.0.1:8000" listen messages addressed specifically to 192.168.0.1 on port 8000, useful if there are several addresses for this machine.
|
||||||
|
*/
|
||||||
UPROPERTY(Config, EditAnywhere, Category=Receive)
|
UPROPERTY(Config, EditAnywhere, Category=Receive)
|
||||||
int32 ReceivePort;
|
FString ReceiveFrom;
|
||||||
|
|
||||||
UPROPERTY(Config, EditAnywhere, Category=Send)
|
UPROPERTY(Config, EditAnywhere, Category=Send)
|
||||||
TArray<FString> SendTargets;
|
TArray<FString> SendTargets;
|
||||||
@@ -24,6 +32,14 @@ public:
|
|||||||
|
|
||||||
void Send(const uint8 *buffer, int32 length, int32 targetIndex);
|
void Send(const uint8 *buffer, int32 length, int32 targetIndex);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Parse "8000" and "192.168.0.12" to IP and port values.
|
||||||
|
* @return true if succeed
|
||||||
|
*/
|
||||||
|
static bool Parse(const FString & address_port, FIPv4Address * address, uint32_t * port);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TSharedRef<FSocket> _sendSocket;
|
TSharedRef<FSocket> _sendSocket;
|
||||||
TArray<std::pair<FString, TSharedRef<FInternetAddr>>> _sendAddresses;
|
TArray<std::pair<FString, TSharedRef<FInternetAddr>>> _sendAddresses;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
UOscDispatcher::UOscDispatcher(const class FPostConstructInitializeProperties& PCIP)
|
UOscDispatcher::UOscDispatcher(const class FPostConstructInitializeProperties& PCIP)
|
||||||
: Super(PCIP),
|
: Super(PCIP),
|
||||||
_currentPort(0),
|
_listening(FIPv4Address(0), 0),
|
||||||
_socket(nullptr),
|
_socket(nullptr),
|
||||||
_socketReceiver(nullptr),
|
_socketReceiver(nullptr),
|
||||||
_pendingMessages(64)
|
_pendingMessages(64)
|
||||||
@@ -23,19 +23,30 @@ UOscDispatcher * UOscDispatcher::Get()
|
|||||||
return UOscDispatcher::StaticClass()->GetDefaultObject<UOscDispatcher>();
|
return UOscDispatcher::StaticClass()->GetDefaultObject<UOscDispatcher>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UOscDispatcher::Listen(uint32_t port)
|
void UOscDispatcher::Listen(FIPv4Address address, uint32_t port)
|
||||||
{
|
{
|
||||||
if(_currentPort != port)
|
if(_listening != std::make_pair(address, port))
|
||||||
{
|
{
|
||||||
Stop();
|
Stop();
|
||||||
|
|
||||||
_socket = FUdpSocketBuilder(TEXT("OscListener")).AsNonBlocking().BoundToAddress(FIPv4Address::Any).BoundToPort(port).Build();
|
FUdpSocketBuilder builder(TEXT("OscListener"));
|
||||||
|
builder.BoundToPort(port);
|
||||||
|
if(address.IsMulticastAddress())
|
||||||
|
{
|
||||||
|
builder.JoinedToGroup(address);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
builder.BoundToAddress(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
_socket = builder.Build();
|
||||||
if(_socket)
|
if(_socket)
|
||||||
{
|
{
|
||||||
_socketReceiver = new FUdpSocketReceiver(_socket, FTimespan::FromMilliseconds(100), TEXT("OSCListener"));
|
_socketReceiver = new FUdpSocketReceiver(_socket, FTimespan::FromMilliseconds(100), TEXT("OSCListener"));
|
||||||
_socketReceiver->OnDataReceived().BindUObject(this, &UOscDispatcher::Callback);
|
_socketReceiver->OnDataReceived().BindUObject(this, &UOscDispatcher::Callback);
|
||||||
|
|
||||||
_currentPort = port;
|
_listening = std::make_pair(address, port);
|
||||||
UE_LOG(LogOSC, Display, TEXT("Listen to port %d"), port);
|
UE_LOG(LogOSC, Display, TEXT("Listen to port %d"), port);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -58,7 +69,7 @@ void UOscDispatcher::Stop()
|
|||||||
_socket = nullptr;
|
_socket = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentPort = 0;
|
_listening = std::make_pair(FIPv4Address(0), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UOscDispatcher::RegisterReceiver(IOscReceiverInterface * receiver)
|
void UOscDispatcher::RegisterReceiver(IOscReceiverInterface * receiver)
|
||||||
@@ -133,35 +144,27 @@ static void SendBundle(TCircularQueue<std::pair<FName, FOscDataStruct>> & _pendi
|
|||||||
void UOscDispatcher::Callback(const FArrayReaderPtr& data, const FIPv4Endpoint&)
|
void UOscDispatcher::Callback(const FArrayReaderPtr& data, const FIPv4Endpoint&)
|
||||||
{
|
{
|
||||||
UE_LOG(LogOSC, Verbose, TEXT("OSC Received"));
|
UE_LOG(LogOSC, Verbose, TEXT("OSC Received"));
|
||||||
try
|
const osc::ReceivedPacket packet((const char *)data->GetData(), data->Num());
|
||||||
|
if(packet.IsBundle())
|
||||||
{
|
{
|
||||||
const osc::ReceivedPacket packet((const char *)data->GetData(), data->Num());
|
SendBundle(_pendingMessages, osc::ReceivedBundle(packet));
|
||||||
|
|
||||||
if(packet.IsBundle())
|
|
||||||
{
|
|
||||||
SendBundle(_pendingMessages, osc::ReceivedBundle(packet));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SendMessage(_pendingMessages, osc::ReceivedMessage(packet));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!_pendingMessages.IsEmpty())
|
|
||||||
{
|
|
||||||
FSimpleDelegateGraphTask::CreateAndDispatchWhenReady(
|
|
||||||
FSimpleDelegateGraphTask::FDelegate::CreateUObject(this, &UOscDispatcher::CallbackMainThread),
|
|
||||||
#if OSC_ENGINE_VERSION < 40500
|
|
||||||
TEXT("OscDispatcherProcessMessages"),
|
|
||||||
#else
|
|
||||||
TStatId(),
|
|
||||||
#endif
|
|
||||||
nullptr,
|
|
||||||
ENamedThreads::GameThread);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch(osc::MalformedPacketException &e)
|
else
|
||||||
{
|
{
|
||||||
UE_LOG(LogOSC, Warning, TEXT("Malformed OSC message: %s"), e.what());
|
SendMessage(_pendingMessages, osc::ReceivedMessage(packet));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!_pendingMessages.IsEmpty())
|
||||||
|
{
|
||||||
|
FSimpleDelegateGraphTask::CreateAndDispatchWhenReady(
|
||||||
|
FSimpleDelegateGraphTask::FDelegate::CreateUObject(this, &UOscDispatcher::CallbackMainThread),
|
||||||
|
#if OSC_ENGINE_VERSION < 40500
|
||||||
|
TEXT("OscDispatcherProcessMessages"),
|
||||||
|
#else
|
||||||
|
TStatId(),
|
||||||
|
#endif
|
||||||
|
nullptr,
|
||||||
|
ENamedThreads::GameThread);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class UOscDispatcher : public UObject
|
|||||||
|
|
||||||
friend class OscModule;
|
friend class OscModule;
|
||||||
|
|
||||||
void Listen(uint32_t port);
|
void Listen(FIPv4Address address, uint32_t port);
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -41,7 +41,7 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
TArray<IOscReceiverInterface *> _receivers;
|
TArray<IOscReceiverInterface *> _receivers;
|
||||||
uint32_t _currentPort;
|
std::pair<FIPv4Address, uint32_t> _listening;
|
||||||
FSocket * _socket;
|
FSocket * _socket;
|
||||||
FUdpSocketReceiver * _socketReceiver;
|
FUdpSocketReceiver * _socketReceiver;
|
||||||
TCircularQueue<std::pair<FName, FOscDataStruct>> _pendingMessages;
|
TCircularQueue<std::pair<FName, FOscDataStruct>> _pendingMessages;
|
||||||
|
|||||||
Reference in New Issue
Block a user