add SendOscBundle blueprint function

This commit is contained in:
monsieurgustav
2016-03-02 00:30:59 +01:00
parent fbc613cf94
commit 88a093b486
3 changed files with 156 additions and 48 deletions
@@ -135,68 +135,148 @@ FOscDataElemStruct UOscFunctionLibrary::FromString(FName input)
}
void UOscFunctionLibrary::SendOsc(FName Address, const TArray<FOscDataElemStruct> & Data, int32 TargetIndex)
namespace
{
if(!Address.IsValid())
bool isValidAddress(const FName & Address)
{
UE_LOG(LogOSC, Error, TEXT("Empty OSC address"));
return;
if(!Address.IsValid())
{
UE_LOG(LogOSC, Error, TEXT("Empty OSC address"));
return false;
}
if(Address.GetDisplayNameEntry()->IsWide())
{
const auto tmp = Address.GetPlainNameString();
UE_LOG(LogOSC, Error, TEXT("Invalid OSC address \"%s\": ASCII only"), *tmp);
return false;
}
if(Address.GetPlainANSIString()[0] != '/')
{
const auto tmp = Address.GetPlainNameString();
UE_LOG(LogOSC, Error, TEXT("Invalid OSC address \"%s\": must start with '/'"), *tmp);
return false;
}
return true;
}
if(Address.GetDisplayNameEntry()->IsWide())
void appendMessage(osc::OutboundPacketStream & output, FName Address, const TArray<FOscDataElemStruct> & Data)
{
const auto tmp = Address.GetPlainNameString();
UE_LOG(LogOSC, Error, TEXT("Invalid OSC address \"%s\": ASCII only"), *tmp);
return;
}
if(Address.GetPlainANSIString()[0] != '/')
{
const auto tmp = Address.GetPlainNameString();
UE_LOG(LogOSC, Error, TEXT("Invalid OSC address \"%s\": must start with '/'"), *tmp);
return;
}
static_assert(sizeof(uint8) == sizeof(char), "Cannot cast uint8 to char");
uint8 buffer[1024];
osc::OutboundPacketStream output((char *)buffer, sizeof(buffer));
output << osc::BeginMessage(Address.GetPlainANSIString());
for(const auto & elem : Data)
{
if(elem.IsFloat())
{
output << (float)elem.AsFloatValue();
}
else if(elem.IsInt())
{
output << (int32)elem.AsIntValue();
}
else if(elem.IsBool())
{
output << elem.AsBoolValue();
}
else if(elem.IsString())
{
output << elem.AsStringValue().GetPlainANSIString();
}
output << osc::BeginMessage(Address.GetPlainANSIString());
if(output.State() != osc::SUCCESS)
{
UE_LOG(LogOSC, Error, TEXT("OSC Send Message Error: %s"), osc::errorString(output.State()));
return;
}
for(const auto & elem : Data)
{
if(elem.IsFloat())
{
output << (float)elem.AsFloatValue();
}
else if(elem.IsInt())
{
output << (int32)elem.AsIntValue();
}
else if(elem.IsBool())
{
output << elem.AsBoolValue();
}
else if(elem.IsString())
{
output << elem.AsStringValue().GetPlainANSIString();
}
if(output.State() != osc::SUCCESS)
{
return;
}
}
output << osc::EndMessage;
}
TArray<uint8> GlobalBuffer(TArray<uint8>(), 1024);
}
void UOscFunctionLibrary::SendOsc(FName Address, const TArray<FOscDataElemStruct> & Data, int32 TargetIndex)
{
if(!isValidAddress(Address))
{
return;
}
static_assert(sizeof(uint8) == sizeof(char), "Cannot cast uint8 to char");
osc::OutboundPacketStream output((char *)GlobalBuffer.GetData(), GlobalBuffer.Max());
check(reinterpret_cast<const void *>(GlobalBuffer.GetData()) == reinterpret_cast<const void *>(output.Data()));
appendMessage(output, Address, Data);
if(output.State() == osc::OUT_OF_BUFFER_MEMORY_ERROR)
{
GlobalBuffer.Reserve(GlobalBuffer.Max() * 2); // not enough memory: double the size
SendOsc(Address, Data, TargetIndex); // try again
return;
}
if(output.State() == osc::SUCCESS)
{
GetMutableDefault<UOscSettings>()->Send(GlobalBuffer.GetData(), output.Size(), TargetIndex);
}
else
{
UE_LOG(LogOSC, Error, TEXT("OSC Send Message Error: %s"), osc::errorString(output.State()));
}
}
void UOscFunctionLibrary::SendOscBundle(const TArray<FOscMessageStruct> & Messages, int32 TargetIndex)
{
static_assert(sizeof(uint8) == sizeof(char), "Cannot cast uint8 to char");
osc::OutboundPacketStream output((char *)GlobalBuffer.GetData(), GlobalBuffer.Max());
check(reinterpret_cast<const void *>(GlobalBuffer.GetData()) == reinterpret_cast<const void *>(output.Data()));
output << osc::BeginBundle();
for(const auto & message : Messages)
{
if(!isValidAddress(message.Address))
{
return;
}
appendMessage(output, message.Address, message.Data);
if(output.State() == osc::OUT_OF_BUFFER_MEMORY_ERROR)
{
GlobalBuffer.Reserve(GlobalBuffer.Max() * 2); // not enough memory: double the size
SendOscBundle(Messages, TargetIndex); // try again
return;
}
if(output.State() != osc::SUCCESS)
{
UE_LOG(LogOSC, Error, TEXT("OSC Send Bundle Error: %s"), osc::errorString(output.State()));
return;
}
}
output << osc::EndMessage;
output << osc::EndBundle;
if(output.State() != osc::SUCCESS)
if(output.State() == osc::OUT_OF_BUFFER_MEMORY_ERROR)
{
UE_LOG(LogOSC, Error, TEXT("OSC Send Message Error: %s"), osc::errorString(output.State()));
GlobalBuffer.Reserve(GlobalBuffer.Max() * 2); // not enough memory: double the size
SendOscBundle(Messages, TargetIndex); // try again
return;
}
check(reinterpret_cast<const void *>(buffer) == reinterpret_cast<const void *>(output.Data()));
GetMutableDefault<UOscSettings>()->Send(buffer, output.Size(), TargetIndex);
if(output.State() == osc::SUCCESS)
{
GetMutableDefault<UOscSettings>()->Send(GlobalBuffer.GetData(), output.Size(), TargetIndex);
}
else
{
UE_LOG(LogOSC, Error, TEXT("OSC Send Bundle Error: %s"), osc::errorString(output.State()));
}
}
int32 UOscFunctionLibrary::AddSendOscTarget(FString IpPort)
@@ -1,6 +1,7 @@
#pragma once
#include "OscDataElemStruct.h"
#include "OscMessageStruct.h"
#include "OscFunctionLibrary.generated.h"
@@ -88,6 +89,14 @@ public:
UFUNCTION(BlueprintCallable, Category=OSC, meta=(AutoCreateRefTerm = "Data"))
static void SendOsc(FName Address, const TArray<FOscDataElemStruct> & Data, int32 TargetIndex);
/**
* @brief Send several OSC messages in an OSC bundle.
* @param Messages of the bundle.
* @param Index index of the destination, -1 for all destinations. (SendTarget list of the plugin settings)
*/
UFUNCTION(BlueprintCallable, Category=OSC)
static void SendOscBundle(const TArray<FOscMessageStruct> & Messages, int32 TargetIndex);
/**
* @brief Add Ip:Port to the available OSC send targets.
* @param IpPort "ip:port". e.g. "192.168.0.1:7777"
@@ -321,7 +321,7 @@ bool OutboundPacketStream::IsBundleInProgress() const
OutboundPacketStream& OutboundPacketStream::operator<<( const BundleInitiator& rhs )
{
check( !IsMessageInProgress() )
check( state_ == SUCCESS )
state_ = CheckForAvailableBundleSpace();
if(state_ == SUCCESS)
{
@@ -344,6 +344,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const BundleTerminator&
check( IsBundleInProgress() )
check( !IsMessageInProgress() )
check( state_ == SUCCESS )
EndElement( messageCursor_ );
@@ -354,6 +355,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const BundleTerminator&
OutboundPacketStream& OutboundPacketStream::operator<<( const BeginMessage& rhs )
{
check( !IsMessageInProgress() )
check( state_ == SUCCESS )
state_ = CheckForAvailableMessageSpace( rhs.addressPattern );
@@ -387,6 +389,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const MessageTerminator&
(void) rhs;
check( IsMessageInProgress() )
check( state_ == SUCCESS )
std::size_t typeTagsCount = end_ - typeTagsCurrent_;
@@ -436,6 +439,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const MessageTerminator&
OutboundPacketStream& OutboundPacketStream::operator<<( bool rhs )
{
check( state_ == SUCCESS )
state_ = CheckForAvailableArgumentSpace(0);
if(state_ == SUCCESS)
{
@@ -449,6 +453,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( bool rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const NilType& rhs )
{
(void) rhs;
check( state_ == SUCCESS )
state_ = CheckForAvailableArgumentSpace(0);
if(state_ == SUCCESS)
{
@@ -462,6 +467,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const NilType& rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const InfinitumType& rhs )
{
(void) rhs;
check( state_ == SUCCESS )
state_ = CheckForAvailableArgumentSpace(0);
if(state_ == SUCCESS)
{
@@ -474,6 +480,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const InfinitumType& rhs
OutboundPacketStream& OutboundPacketStream::operator<<( int32 rhs )
{
check( state_ == SUCCESS )
state_ = CheckForAvailableArgumentSpace(4);
if(state_ == SUCCESS)
{
@@ -488,6 +495,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( int32 rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( float rhs )
{
check( state_ == SUCCESS )
state_ = CheckForAvailableArgumentSpace(4);
if(state_ == SUCCESS)
{
@@ -518,6 +526,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( float rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( char rhs )
{
check( state_ == SUCCESS )
state_ = CheckForAvailableArgumentSpace(4);
if(state_ == SUCCESS)
{
@@ -532,6 +541,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( char rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const RgbaColor& rhs )
{
check( state_ == SUCCESS )
state_ = CheckForAvailableArgumentSpace(4);
if(state_ == SUCCESS)
{
@@ -546,6 +556,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const RgbaColor& rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const MidiMessage& rhs )
{
check( state_ == SUCCESS )
state_ = CheckForAvailableArgumentSpace(4);
if(state_ == SUCCESS)
{
@@ -560,6 +571,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const MidiMessage& rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( int64 rhs )
{
check( state_ == SUCCESS )
state_ = CheckForAvailableArgumentSpace(8);
if(state_ == SUCCESS)
{
@@ -574,6 +586,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( int64 rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const TimeTag& rhs )
{
check( state_ == SUCCESS )
state_ = CheckForAvailableArgumentSpace(8);
if(state_ == SUCCESS)
{
@@ -588,6 +601,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const TimeTag& rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( double rhs )
{
check( state_ == SUCCESS )
state_ = CheckForAvailableArgumentSpace(8);
if(state_ == SUCCESS)
{
@@ -622,6 +636,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( double rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs )
{
check( state_ == SUCCESS )
state_ = CheckForAvailableArgumentSpace( RoundUp4(std::strlen(rhs) + 1) );
if(state_ == SUCCESS)
{
@@ -644,6 +659,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const Symbol& rhs )
{
check( state_ == SUCCESS )
state_ = CheckForAvailableArgumentSpace( RoundUp4(std::strlen(rhs) + 1) );
if(state_ == SUCCESS)
{
@@ -666,6 +682,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const Symbol& rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const Blob& rhs )
{
check( state_ == SUCCESS )
state_ = CheckForAvailableArgumentSpace( 4 + RoundUp4(rhs.size) );
if(state_ == SUCCESS)
{
@@ -690,6 +707,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const Blob& rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const ArrayInitiator& rhs )
{
(void) rhs;
check( state_ == SUCCESS )
state_ = CheckForAvailableArgumentSpace(0);
if(state_ == SUCCESS)
{
@@ -702,6 +720,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const ArrayInitiator& rh
OutboundPacketStream& OutboundPacketStream::operator<<( const ArrayTerminator& rhs )
{
(void) rhs;
check( state_ == SUCCESS )
state_ = CheckForAvailableArgumentSpace(0);
if(state_ == SUCCESS)
{