diff --git a/OSC/Source/OSC/Private/Common/OscFunctionLibrary.cpp b/OSC/Source/OSC/Private/Common/OscFunctionLibrary.cpp index 2b0bccd..2fae940 100644 --- a/OSC/Source/OSC/Private/Common/OscFunctionLibrary.cpp +++ b/OSC/Source/OSC/Private/Common/OscFunctionLibrary.cpp @@ -185,3 +185,8 @@ void UOscFunctionLibrary::SendOsc(FName Address, const TArray(buffer) == reinterpret_cast(output.Data())); GetMutableDefault()->Send(buffer, output.Size(), TargetIndex); } + +int32 UOscFunctionLibrary::AddSendOscTarget(FString IpPort) +{ + return GetMutableDefault()->GetOrAddSendTarget(IpPort); +} diff --git a/OSC/Source/OSC/Private/Common/OscFunctionLibrary.h b/OSC/Source/OSC/Private/Common/OscFunctionLibrary.h index 759c23d..56d5538 100644 --- a/OSC/Source/OSC/Private/Common/OscFunctionLibrary.h +++ b/OSC/Source/OSC/Private/Common/OscFunctionLibrary.h @@ -87,4 +87,17 @@ public: */ UFUNCTION(BlueprintCallable, Category=OSC, meta=(AutoCreateRefTerm = "Data")) static void SendOsc(FName Address, const TArray & Data, int32 TargetIndex); + + /** + * @brief Add Ip:Port to the available OSC send targets. + * @param IpPort "ip:port". e.g. "192.168.0.1:7777" + * @return The created TargetIndex to pass to the SendOsc function. + * + * Use this function to add target at runtime. Generally, it is best + * to define your targets in the OSC plugin settings. + * + * @see SendOsc + */ + UFUNCTION(BlueprintCallable, Category=OSC) + static int32 AddSendOscTarget(FString IpPort); }; diff --git a/OSC/Source/OSC/Private/OscModule.cpp b/OSC/Source/OSC/Private/OscModule.cpp index 86f3c7c..f142ec8 100644 --- a/OSC/Source/OSC/Private/OscModule.cpp +++ b/OSC/Source/OSC/Private/OscModule.cpp @@ -91,7 +91,7 @@ public: #endif // send settings - settings->UpdateSendAddresses(); + settings->InitSendTargets(); // input settings settings->UpdateKeyInputs(*_dispatcher); diff --git a/OSC/Source/OSC/Private/OscSettings.cpp b/OSC/Source/OSC/Private/OscSettings.cpp index f301894..c8d2559 100644 --- a/OSC/Source/OSC/Private/OscSettings.cpp +++ b/OSC/Source/OSC/Private/OscSettings.cpp @@ -17,35 +17,59 @@ UOscSettings::UOscSettings(FVTableHelper & helper) // Does not need to be a valid object. } -void UOscSettings::UpdateSendAddresses() +void UOscSettings::InitSendTargets() { + UE_LOG(LogOSC, Display, TEXT("Send targets cleared")); + FString addressStr, portStr; + + _sendAddresses.Empty(); + _sendAddresses.Reserve(SendTargets.Num()); + + _sendAddressesIndex.Empty(); + _sendAddressesIndex.Reserve(SendTargets.Num()); + for(int32 i=0, n=SendTargets.Num(); i!=n; ++i) { - if(i >= _sendAddresses.Num()) - { - _sendAddresses.Emplace(FString(), ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr()); - } - - if(_sendAddresses[i].first != SendTargets[i]) - { - FIPv4Address address(0); - uint32_t port; - if(Parse(SendTargets[i], &address, &port) && address != FIPv4Address::Any) - { - _sendAddresses[i].second->SetIp(address.GetValue()); - _sendAddresses[i].second->SetPort(port); - - _sendAddresses[i].first = SendTargets[i]; - } - else - { - UE_LOG(LogOSC, Error, TEXT("Fail to parse or invalid send address: %s"), *SendTargets[i]); - } - } + const auto result = AddSendTarget(SendTargets[i]); + check(result == i); } } +int32 UOscSettings::GetOrAddSendTarget(const FString & ip_port) +{ + const int32 * result = _sendAddressesIndex.Find(ip_port); + if(result) + { + return *result; + } + + return AddSendTarget(ip_port); +} + +int32 UOscSettings::AddSendTarget(const FString & ip_port) +{ + auto target = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr(); + + FIPv4Address address(0); + uint32_t port; + if(Parse(ip_port, &address, &port) && address != FIPv4Address::Any) + { + target->SetIp(address.GetValue()); + target->SetPort(port); + UE_LOG(LogOSC, Display, TEXT("Send target added: %s"), *ip_port); + } + else + { + UE_LOG(LogOSC, Error, TEXT("Fail to parse or invalid send target: %s"), *ip_port); + } + + const auto result = _sendAddresses.Num(); + _sendAddressesIndex.Emplace(ip_port, result); + _sendAddresses.Emplace(target); + return result; +} + static void SendImpl(FSocket *socket, const uint8 *buffer, int32 length, const FInternetAddr & target) { int32 bytesSent = 0; @@ -63,7 +87,7 @@ void UOscSettings::Send(const uint8 *buffer, int32 length, int32 targetIndex) { for(const auto & address : _sendAddresses) { - SendImpl(&_sendSocket.Get(), buffer, length, *address.second); + SendImpl(&_sendSocket.Get(), buffer, length, *address); } #if !NO_LOGGING @@ -79,7 +103,7 @@ void UOscSettings::Send(const uint8 *buffer, int32 length, int32 targetIndex) } else if(targetIndex < _sendAddresses.Num()) { - SendImpl(&_sendSocket.Get(), buffer, length, *_sendAddresses[targetIndex].second); + SendImpl(&_sendSocket.Get(), buffer, length, *_sendAddresses[targetIndex]); #if !NO_LOGGING // Log sent packet @@ -88,7 +112,7 @@ void UOscSettings::Send(const uint8 *buffer, int32 length, int32 targetIndex) TArray tmp; tmp.Append(buffer, length); const auto encoded = FBase64::Encode(tmp); - const auto target = _sendAddresses[targetIndex].second->ToString(true); + const auto target = _sendAddresses[targetIndex]->ToString(true); UE_LOG(LogOSC, Verbose, TEXT("SentTo %s: %s"), *target, *encoded); } #endif @@ -99,9 +123,9 @@ void UOscSettings::Send(const uint8 *buffer, int32 length, int32 targetIndex) } } -bool UOscSettings::Parse(const FString & address_port, FIPv4Address * address, uint32_t * port) +bool UOscSettings::Parse(const FString & ip_port, FIPv4Address * address, uint32_t * port) { - if(address_port.IsEmpty()) + if(ip_port.IsEmpty()) { return false; } @@ -110,16 +134,16 @@ bool UOscSettings::Parse(const FString & address_port, FIPv4Address * address, u uint32_t portResult; int32 sep = -1; - if(address_port.FindChar(TEXT(':'), sep)) + if(ip_port.FindChar(TEXT(':'), sep)) { - const auto ip = address_port.Left(sep).Trim(); + const auto ip = ip_port.Left(sep).Trim(); if(!FIPv4Address::Parse(ip, addressResult)) { return false; } } - portResult = FCString::Atoi(&address_port.GetCharArray()[sep+1]); + portResult = FCString::Atoi(&ip_port.GetCharArray()[sep+1]); if(portResult == 0) { return false; diff --git a/OSC/Source/OSC/Private/OscSettings.h b/OSC/Source/OSC/Private/OscSettings.h index 4df1f0a..5b8eeb7 100644 --- a/OSC/Source/OSC/Private/OscSettings.h +++ b/OSC/Source/OSC/Private/OscSettings.h @@ -45,7 +45,9 @@ public: TArray Inputs; public: - void UpdateSendAddresses(); + void InitSendTargets(); + + int32 GetOrAddSendTarget(const FString & ip_port); void Send(const uint8 *buffer, int32 length, int32 targetIndex); @@ -59,10 +61,14 @@ 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); + static bool Parse(const FString & ip_port, FIPv4Address * address, uint32_t * port); + +private: + int32 AddSendTarget(const FString & ip_port); private: TSharedRef _sendSocket; - TArray>> _sendAddresses; + TArray> _sendAddresses; + TMap _sendAddressesIndex; TArray _keyReceivers; };