2020-09-08 14:13:51 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "MetasoundRouter.h"
2021-03-05 20:06:54 -04:00
# include "MetasoundFrontendRegistries.h"
2020-09-08 14:13:51 -04:00
# include "MetasoundOperatorInterface.h"
# include "CoreMinimal.h"
# include "HAL/IConsoleManager.h"
2021-03-12 00:09:21 -04:00
2020-09-08 14:13:51 -04:00
// Convenience exec commands to push values to global params.
static FAutoConsoleCommand GPushFloatCommand (
2021-04-02 02:09:50 -04:00
TEXT ( " au.MetaSound.SetFloat " ) ,
TEXT ( " Use this with au.MetaSound.SetFloat [type] [address] [value]. Pushes a parameter value directly to a global address, which can then be received by Metasounds using a Receive node. " ) ,
2020-09-08 14:13:51 -04:00
FConsoleCommandWithArgsDelegate : : CreateStatic (
[ ] ( const TArray < FString > & Args )
{
2021-03-12 00:09:21 -04:00
if ( Args . Num ( ) < 3 )
2020-09-08 14:13:51 -04:00
{
2021-04-02 03:03:27 -04:00
UE_LOG ( LogMetaSound , Warning , TEXT ( " au.MetaSound.Set* should be called with three args- the data type of the channel, the address to send to and the value to send. " ) ) ;
2020-09-08 14:13:51 -04:00
return ;
}
2021-03-12 00:09:21 -04:00
FName DataType = FName ( * Args [ 0 ] ) ;
FName ChannelName = FName ( * Args [ 1 ] ) ;
float ValueToPush = TCString < TCHAR > : : Atof ( * Args [ 2 ] ) ;
2020-09-08 14:13:51 -04:00
2021-01-13 10:48:59 -04:00
Metasound : : FLiteral LiteralParam ( ValueToPush ) ;
2020-09-08 14:13:51 -04:00
2021-03-12 00:09:21 -04:00
Metasound : : FDataTransmissionCenter : : Get ( ) . PushLiteral ( DataType , ChannelName , LiteralParam ) ;
2020-09-08 14:13:51 -04:00
} )
) ;
static FAutoConsoleCommand GPushBoolCommand (
2021-04-02 02:09:50 -04:00
TEXT ( " au.MetaSound.SetBool " ) ,
TEXT ( " Use this with au.MetaSound.SetBool [address] [value]. Pushes a parameter value directly to a global address, which can then be received by Metasounds using a Receive node. " ) ,
2020-09-08 14:13:51 -04:00
FConsoleCommandWithArgsDelegate : : CreateStatic (
[ ] ( const TArray < FString > & Args )
{
if ( Args . Num ( ) < 2 )
{
2021-04-02 03:03:27 -04:00
UE_LOG ( LogMetaSound , Warning , TEXT ( " au.MetaSound.SetBool should be called with two args- the address to send to and the value to send. " ) ) ;
UE_LOG ( LogMetaSound , Warning , TEXT ( " au.MetaSound.Set* should be called with three args- the data type of the channel, the address to send to and the value to send. " ) ) ;
2020-09-08 14:13:51 -04:00
return ;
}
2021-03-12 00:09:21 -04:00
FName DataType = FName ( * Args [ 0 ] ) ;
FName ChannelName = FName ( * Args [ 1 ] ) ;
int32 ValueAsInt = TCString < TCHAR > : : Atoi ( * Args [ 2 ] ) ;
2020-09-08 14:13:51 -04:00
bool ValueToPush = ValueAsInt ! = 0 ;
2021-01-13 10:48:59 -04:00
Metasound : : FLiteral LiteralParam ( ValueToPush ) ;
2020-09-08 14:13:51 -04:00
2021-03-12 00:09:21 -04:00
Metasound : : FDataTransmissionCenter : : Get ( ) . PushLiteral ( DataType , ChannelName , LiteralParam ) ;
2020-09-08 14:13:51 -04:00
} )
) ;
static FAutoConsoleCommand GPushIntCommand (
2021-04-02 02:09:50 -04:00
TEXT ( " au.MetaSound.SetInt " ) ,
TEXT ( " Use this with au.MetaSound.SetInt [address] [value]. Pushes a parameter value directly to a global address, which can then be received by Metasounds using a Receive node. " ) ,
2020-09-08 14:13:51 -04:00
FConsoleCommandWithArgsDelegate : : CreateStatic (
[ ] ( const TArray < FString > & Args )
{
if ( Args . Num ( ) < 2 )
{
2021-04-02 03:03:27 -04:00
UE_LOG ( LogMetaSound , Warning , TEXT ( " au.MetaSound.Set* should be called with three args- the data type of the channel, the address to send to and the value to send. " ) ) ;
2020-09-08 14:13:51 -04:00
return ;
}
2021-03-12 00:09:21 -04:00
FName DataType = FName ( * Args [ 0 ] ) ;
FName ChannelName = FName ( * Args [ 1 ] ) ;
int32 ValueToPush = TCString < TCHAR > : : Atoi ( * Args [ 2 ] ) ;
2020-09-08 14:13:51 -04:00
2021-01-13 10:48:59 -04:00
Metasound : : FLiteral LiteralParam ( ValueToPush ) ;
2020-09-08 14:13:51 -04:00
2021-03-12 00:09:21 -04:00
Metasound : : FDataTransmissionCenter : : Get ( ) . PushLiteral ( DataType , ChannelName , LiteralParam ) ;
2020-09-08 14:13:51 -04:00
} )
) ;
static FAutoConsoleCommand GPushStringCommand (
2021-04-02 02:09:50 -04:00
TEXT ( " au.MetaSound.SetString " ) ,
TEXT ( " Use this with au.MetaSound.SetString [address] [value]. Pushes a parameter value directly to a global address, which can then be received by Metasounds using a Receive node. " ) ,
2020-09-08 14:13:51 -04:00
FConsoleCommandWithArgsDelegate : : CreateStatic (
[ ] ( const TArray < FString > & Args )
{
2021-03-12 00:09:21 -04:00
if ( Args . Num ( ) < 3 )
2020-09-08 14:13:51 -04:00
{
2021-04-02 03:03:27 -04:00
UE_LOG ( LogMetaSound , Warning , TEXT ( " au.MetaSound.SetBool should be called with three args- the data type of the channel, the address to send to and the value to send. " ) ) ;
UE_LOG ( LogMetaSound , Warning , TEXT ( " au.MetaSound.Set* should be called with three args- the data type of the channel, the address to send to and the value to send. " ) ) ;
2020-09-08 14:13:51 -04:00
return ;
}
2021-03-12 00:09:21 -04:00
FName DataType = FName ( * Args [ 0 ] ) ;
FName ChannelName = FName ( * Args [ 1 ] ) ;
2020-09-08 14:13:51 -04:00
2021-03-12 00:09:21 -04:00
Metasound : : FLiteral LiteralParam ( Args [ 2 ] ) ;
2020-09-08 14:13:51 -04:00
2021-03-12 00:09:21 -04:00
Metasound : : FDataTransmissionCenter : : Get ( ) . PushLiteral ( DataType , ChannelName , LiteralParam ) ;
2020-09-08 14:13:51 -04:00
} )
) ;
namespace Metasound
{
IReceiver : : ~ IReceiver ( )
{
DataChannel - > OnReceiverDestroyed ( ) ;
}
ISender : : ~ ISender ( )
{
DataChannel - > OnSenderDestroyed ( ) ;
}
ITransmissionSubsystem : : ITransmissionSubsystem ( FName InSubsystemName )
: SubsystemName ( InSubsystemName )
{
FDataTransmissionCenter : : Get ( ) . RegisterSubsystem ( this , SubsystemName ) ;
}
ITransmissionSubsystem : : ~ ITransmissionSubsystem ( )
{
FDataTransmissionCenter : : Get ( ) . UnregisterSubsystem ( SubsystemName ) ;
}
2021-03-05 20:06:54 -04:00
FDataTransmissionCenter & FDataTransmissionCenter : : Get ( )
2020-09-08 14:13:51 -04:00
{
static FDataTransmissionCenter Singleton ;
return Singleton ;
}
2021-03-05 20:06:54 -04:00
TUniquePtr < ISender > FDataTransmissionCenter : : RegisterNewSender ( const FName & InDataTypeName , const FSendAddress & InAddress , const FSenderInitParams & InitParams )
2020-09-08 14:13:51 -04:00
{
2021-03-05 20:06:54 -04:00
TUniquePtr < ISender > Sender ;
if ( InAddress . Subsystem = = GetSubsystemNameForSendScope ( ETransmissionScope : : ThisInstanceOnly ) )
{
Sender = InstanceRouter . RegisterNewSender ( InAddress . MetasoundInstanceID , InDataTypeName , InAddress . ChannelName , InitParams ) ;
}
else if ( InAddress . Subsystem = = GetSubsystemNameForSendScope ( ETransmissionScope : : Global ) )
{
Sender = GlobalRouter . RegisterNewSender ( InDataTypeName , InAddress . ChannelName , InitParams ) ;
}
else if ( FSubsystemData * FoundSubsystem = SubsystemRouters . Find ( InAddress . Subsystem ) )
{
ITransmissionSubsystem * SubsystemInterface = FoundSubsystem - > SubsystemPtr ;
// Ensure that this subsystem can support this send type.
if ( ensureAlways ( SubsystemInterface & & SubsystemInterface - > CanSupportDataType ( InDataTypeName ) ) )
{
FScopeLock ScopeLock ( & SubsystemRoutersMutationLock ) ;
Sender = FoundSubsystem - > AddressRouter . RegisterNewSender ( InDataTypeName , InAddress . ChannelName , InitParams ) ;
FoundSubsystem - > SubsystemPtr - > OnNewSendRegistered ( InAddress , InDataTypeName ) ;
}
}
else
{
// Otherwise, the subsystem FName was invalid.
2021-04-02 03:03:27 -04:00
UE_LOG ( LogMetaSound , Error , TEXT ( " Cannot create Sender. Did not find transmission subsystem [Name:%s] " ) , * InAddress . Subsystem . ToString ( ) ) ;
2021-03-05 20:06:54 -04:00
}
return MoveTemp ( Sender ) ;
}
TUniquePtr < IReceiver > FDataTransmissionCenter : : RegisterNewReceiver ( const FName & InDataTypeName , const FSendAddress & InAddress , const FReceiverInitParams & InitParams )
{
TUniquePtr < IReceiver > Receiver ;
if ( InAddress . Subsystem = = GetSubsystemNameForSendScope ( ETransmissionScope : : ThisInstanceOnly ) )
{
Receiver = InstanceRouter . RegisterNewReceiver ( InAddress . MetasoundInstanceID , InDataTypeName , InAddress . ChannelName , InitParams ) ;
}
else if ( InAddress . Subsystem = = GetSubsystemNameForSendScope ( ETransmissionScope : : Global ) )
{
Receiver = GlobalRouter . RegisterNewReceiver ( InDataTypeName , InAddress . ChannelName , InitParams ) ;
}
else if ( FSubsystemData * FoundSubsystem = SubsystemRouters . Find ( InAddress . Subsystem ) )
{
ITransmissionSubsystem * SubsystemInterface = FoundSubsystem - > SubsystemPtr ;
// Ensure that this subsystem can support this send type.
if ( ensureAlways ( SubsystemInterface & & SubsystemInterface - > CanSupportDataType ( InDataTypeName ) ) )
{
FScopeLock ScopeLock ( & SubsystemRoutersMutationLock ) ;
Receiver = FoundSubsystem - > AddressRouter . RegisterNewReceiver ( InDataTypeName , InAddress . ChannelName , InitParams ) ;
FoundSubsystem - > SubsystemPtr - > OnNewReceiverRegistered ( InAddress , InDataTypeName ) ;
}
}
else
{
// Otherwise, the subsystem FName was invalid.
2021-04-02 03:03:27 -04:00
UE_LOG ( LogMetaSound , Error , TEXT ( " Cannot create Receiver. Did not find transmission subsystem [Name:%s] " ) , * InAddress . Subsystem . ToString ( ) ) ;
2021-03-05 20:06:54 -04:00
}
return MoveTemp ( Receiver ) ;
}
2021-04-07 22:12:28 -04:00
bool FDataTransmissionCenter : : UnregisterDataChannel ( const FName & InDataTypeName , const FSendAddress & InAddress )
2021-04-06 01:41:29 -04:00
{
2021-04-07 22:12:28 -04:00
// Only supporting global router. Other subsystems are not used and will be reworked.
if ( ensure ( InAddress . Subsystem = = GetSubsystemNameForSendScope ( ETransmissionScope : : Global ) ) )
{
return GlobalRouter . UnregisterDataChannel ( InDataTypeName , InAddress . ChannelName ) ;
}
return false ;
}
bool FDataTransmissionCenter : : UnregisterDataChannelIfUnconnected ( const FName & InDataTypeName , const FSendAddress & InAddress )
{
// Only supporting global router. Other subsystems are not used and will be reworked.
if ( ensure ( InAddress . Subsystem = = GetSubsystemNameForSendScope ( ETransmissionScope : : Global ) ) )
{
return GlobalRouter . UnregisterDataChannelIfUnconnected ( InDataTypeName , InAddress . ChannelName ) ;
}
return false ;
2021-04-06 01:41:29 -04:00
}
2021-03-12 00:09:21 -04:00
bool FDataTransmissionCenter : : PushLiteral ( FName DataType , FName GlobalChannelName , const FLiteral & InParam )
2021-03-05 20:06:54 -04:00
{
2021-03-12 00:09:21 -04:00
return GlobalRouter . PushLiteral ( DataType , GlobalChannelName , InParam ) ;
2021-03-05 20:06:54 -04:00
}
void FDataTransmissionCenter : : RegisterSubsystem ( ITransmissionSubsystem * InSystem , FName InSubsytemName )
{
FScopeLock ScopeLock ( & SubsystemRoutersMutationLock ) ;
//check to make sure we're not adding a subsystem twice.
check ( ! SubsystemRouters . Contains ( InSubsytemName ) ) ;
SubsystemRouters . Emplace ( InSubsytemName , InSystem ) ;
}
void FDataTransmissionCenter : : UnregisterSubsystem ( FName InSubsystemName )
{
FScopeLock ScopeLock ( & SubsystemRoutersMutationLock ) ;
//check to make sure we're not adding a subsystem twice.
check ( SubsystemRouters . Contains ( InSubsystemName ) ) ;
SubsystemRouters . Remove ( InSubsystemName ) ;
2020-09-08 14:13:51 -04:00
}
2021-03-12 00:09:21 -04:00
FAddressRouter : : FDataChannelKey FAddressRouter : : GetDataChannelKey ( const FName & InDataTypeName , const FName & InChannelName ) const
2020-09-08 14:13:51 -04:00
{
2021-03-12 00:09:21 -04:00
return FString : : Format ( TEXT ( " {0}[{1}] " ) , { InChannelName . ToString ( ) , InDataTypeName . ToString ( ) } ) ;
2020-09-08 14:13:51 -04:00
}
2021-03-12 00:09:21 -04:00
TSharedPtr < IDataChannel , ESPMode : : ThreadSafe > FAddressRouter : : FindDataChannel ( const FName & InDataTypeName , const FName & InChannelName )
2020-09-08 14:13:51 -04:00
{
2021-03-12 00:09:21 -04:00
TSharedPtr < IDataChannel , ESPMode : : ThreadSafe > Channel ;
2020-09-08 14:13:51 -04:00
2021-03-12 00:09:21 -04:00
const FDataChannelKey ChannelKey = GetDataChannelKey ( InDataTypeName , InChannelName ) ;
2021-03-05 20:06:54 -04:00
{
FScopeLock ScopeLock ( & DataChannelMapMutationLock ) ;
2021-03-12 00:09:21 -04:00
if ( TSharedRef < IDataChannel , ESPMode : : ThreadSafe > * ExistingChannelPtr = DataChannelMap . Find ( ChannelKey ) )
2021-03-05 20:06:54 -04:00
{
2021-03-12 00:09:21 -04:00
Channel = * ExistingChannelPtr ;
2021-03-05 20:06:54 -04:00
}
2021-03-12 00:09:21 -04:00
}
2021-03-05 20:06:54 -04:00
2021-03-12 00:09:21 -04:00
return Channel ;
}
TSharedPtr < IDataChannel , ESPMode : : ThreadSafe > FAddressRouter : : GetDataChannel ( const FName & InDataTypeName , const FName & InChannelName , const FOperatorSettings & InOperatorSettings )
{
TSharedPtr < IDataChannel , ESPMode : : ThreadSafe > DataChannel = FindDataChannel ( InDataTypeName , InChannelName ) ;
if ( ! DataChannel . IsValid ( ) )
{
FScopeLock ScopeLock ( & DataChannelMapMutationLock ) ;
const FDataChannelKey ChannelKey = GetDataChannelKey ( InDataTypeName , InChannelName ) ;
// This is the first time we're seeing this, add it to the map.
FMetasoundFrontendRegistryContainer * Registry = FMetasoundFrontendRegistryContainer : : Get ( ) ;
if ( ensure ( nullptr ! = Registry ) )
{
DataChannel = Registry - > CreateDataChannelForDataType ( InDataTypeName , InOperatorSettings ) ;
if ( DataChannel . IsValid ( ) )
2021-03-05 20:06:54 -04:00
{
2021-03-12 00:09:21 -04:00
DataChannelMap . Add ( ChannelKey , DataChannel . ToSharedRef ( ) ) ;
2021-03-05 20:06:54 -04:00
}
}
}
return DataChannel ;
}
TUniquePtr < ISender > FAddressRouter : : RegisterNewSender ( const FName & InDataTypeName , const FName & InChannelName , const FSenderInitParams & InitParams )
{
TSharedPtr < IDataChannel , ESPMode : : ThreadSafe > DataChannel = GetDataChannel ( InDataTypeName , InChannelName , InitParams . OperatorSettings ) ;
if ( DataChannel . IsValid ( ) )
{
return DataChannel - > NewSender ( InitParams ) ;
}
else
{
return TUniquePtr < ISender > ( nullptr ) ;
}
}
2021-04-06 01:41:29 -04:00
bool FAddressRouter : : UnregisterDataChannel ( const FName & InDataTypeName , const FName & InChannelName )
{
FScopeLock ScopeLock ( & DataChannelMapMutationLock ) ;
const FDataChannelKey ChannelKey = GetDataChannelKey ( InDataTypeName , InChannelName ) ;
if ( TSharedRef < IDataChannel , ESPMode : : ThreadSafe > * Channel = DataChannelMap . Find ( ChannelKey ) )
{
if ( const int32 NumReceiversActive = Channel - > Get ( ) . GetNumActiveReceivers ( ) )
{
UE_LOG ( LogMetaSound , Verbose , TEXT ( " DataChannel '%s' of type '%s' shutting down with %d receivers active. " ) , * InChannelName . ToString ( ) , * InDataTypeName . ToString ( ) , NumReceiversActive ) ;
}
if ( const int32 NumSendersActive = Channel - > Get ( ) . GetNumActiveSenders ( ) )
{
UE_LOG ( LogMetaSound , Verbose , TEXT ( " DataChannel '%s' of type '%s' shutting down with %d senders active. " ) , * InChannelName . ToString ( ) , * InDataTypeName . ToString ( ) , NumSendersActive ) ;
}
}
return DataChannelMap . Remove ( ChannelKey ) > 0 ;
}
2021-04-07 22:12:28 -04:00
bool FAddressRouter : : UnregisterDataChannelIfUnconnected ( const FName & InDataTypeName , const FName & InChannelName )
{
FScopeLock ScopeLock ( & DataChannelMapMutationLock ) ;
const FDataChannelKey ChannelKey = GetDataChannelKey ( InDataTypeName , InChannelName ) ;
if ( TSharedRef < IDataChannel , ESPMode : : ThreadSafe > * Channel = DataChannelMap . Find ( ChannelKey ) )
{
if ( 0 = = Channel - > Get ( ) . GetNumActiveReceivers ( ) )
{
if ( 0 = = Channel - > Get ( ) . GetNumActiveSenders ( ) )
{
return DataChannelMap . Remove ( ChannelKey ) > 0 ;
}
}
}
return false ;
}
2021-03-05 20:06:54 -04:00
TUniquePtr < IReceiver > FAddressRouter : : RegisterNewReceiver ( const FName & InDataTypeName , const FName & InChannelName , const FReceiverInitParams & InitParams )
{
TSharedPtr < IDataChannel , ESPMode : : ThreadSafe > DataChannel = GetDataChannel ( InDataTypeName , InChannelName , InitParams . OperatorSettings ) ;
if ( DataChannel . IsValid ( ) )
{
return DataChannel - > NewReceiver ( InitParams ) ;
}
else
{
return TUniquePtr < IReceiver > ( nullptr ) ;
}
}
TUniquePtr < IReceiver > FInstanceLocalRouter : : RegisterNewReceiver ( uint64 InInstanceID , const FName & InDataTypeName , const FName & InChannelName , const FReceiverInitParams & InitParams )
{
FScopeLock ScopeLock ( & InstanceRouterMapMutationLock ) ;
if ( FAddressRouter * AddressRouter = InstanceRouterMap . Find ( InInstanceID ) )
{
return AddressRouter - > RegisterNewReceiver ( InDataTypeName , InChannelName , InitParams ) ;
}
else
{
// This is the first time we're seeing this, add it to the map.
FAddressRouter & NewRouter = InstanceRouterMap . Add ( InInstanceID , FAddressRouter ( ) ) ;
return NewRouter . RegisterNewReceiver ( InDataTypeName , InChannelName , InitParams ) ;
}
}
TUniquePtr < ISender > FInstanceLocalRouter : : RegisterNewSender ( uint64 InInstanceID , const FName & InDataTypeName , const FName & InChannelName , const FSenderInitParams & InitParams )
{
FScopeLock ScopeLock ( & InstanceRouterMapMutationLock ) ;
if ( FAddressRouter * AddressRouter = InstanceRouterMap . Find ( InInstanceID ) )
{
return AddressRouter - > RegisterNewSender ( InDataTypeName , InChannelName , InitParams ) ;
}
else
{
// This is the first time we're seeing this, add it to the map.
FAddressRouter & NewRouter = InstanceRouterMap . Add ( InInstanceID , FAddressRouter ( ) ) ;
return NewRouter . RegisterNewSender ( InDataTypeName , InChannelName , InitParams ) ;
}
}
2020-09-08 14:13:51 -04:00
}