Skip to content

Commit

Permalink
update odin plugin to version 1.8.1
Browse files Browse the repository at this point in the history
  • Loading branch information
SFuhrmann committed Jan 2, 2024
1 parent 8d7c9c1 commit 8a70f72
Show file tree
Hide file tree
Showing 26 changed files with 819 additions and 340 deletions.
6 changes: 3 additions & 3 deletions Plugins/Odin/Odin.uplugin
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"FileVersion": 2,
"EngineVersion": "4.26.0",
"Version": 18,
"Version": 324,
"WhitelistPlatforms": [ "Win64", "Mac", "IOS", "Linux", "Android" ],
"VersionName": "1.5.8",
"VersionName": "1.8.1",
"FriendlyName": "4Players ODIN",
"Description": "Unreal integration plugin to integrate real-time chat technology into your game",
"Category": "Other",
Expand All @@ -12,7 +12,7 @@
"DocsURL": "https://www.4players.io/odin/sdk/unreal/",
"MarketplaceURL": "com.epicgames.launcher://ue/marketplace/product/f45b045efc62416e9f6e6858519ab999",
"SupportURL": "",
"CanContainContent": true,
"CanContainContent": false,
"IsBetaVersion": false,
"IsExperimentalVersion": false,
"Installed": false,
Expand Down
1 change: 1 addition & 0 deletions Plugins/Odin/Source/Odin/Odin.Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public Odin(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PrecompileForTargets = PrecompileTargetsType.Any;
DefaultBuildSettings = BuildSettingsVersion.Latest;

// List of all paths to include files that are exposed to other modules
PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "Public"));
Expand Down
2 changes: 1 addition & 1 deletion Plugins/Odin/Source/Odin/Private/Odin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void FOdinModule::StartupModule()
[[IOSAppDelegate GetDelegate] SetFeature:EAudioFeature::Record Active:true];
[[IOSAppDelegate GetDelegate] SetFeature:EAudioFeature::VoiceChat Active:true];
#endif

#if PLATFORM_WINDOWS || PLATFORM_LINUX
FString BaseDir = IPluginManager::Get().FindPlugin("Odin")->GetBaseDir();
FString LibraryPath;
Expand Down
145 changes: 119 additions & 26 deletions Plugins/Odin/Source/Odin/Private/OdinAudioCapture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
void UOdinAudioCapture::BeginDestroy()
{
Super::BeginDestroy();
AudioCapture.CloseStream();
StopCapturingAudio();
}

Expand Down Expand Up @@ -45,7 +46,7 @@ void UOdinAudioCapture::HandleDefaultDeviceChanged(EAudioDeviceChangedRole Audio
UE_LOG(Odin, Display,
TEXT("Recognized change in default capture device, reconnecting to new default "
"device."));
RestartStream();
RestartCapturing();
OnDefaultDeviceChanged.Broadcast();
}
}
Expand All @@ -69,7 +70,7 @@ void UOdinAudioCapture::HandleDefaultDeviceChanged(FString DeviceId)
UE_LOG(Odin, Display,
TEXT("Recognized change in default capture device, reconnecting to new default "
"device."));
RestartStream();
RestartCapturing();
OnDefaultDeviceChanged.Broadcast();
}
}
Expand Down Expand Up @@ -106,7 +107,9 @@ void UOdinAudioCapture::AsyncGetCaptureDevicesAvailable(FGetCaptureDeviceDelegat
// We schedule back to the main thread and pass in our params
AsyncTask(ENamedThreads::GameThread, [Devices, CurrentDevice, Out]() {
// We execute the delegate along with the param
Out.Execute(Devices, CurrentDevice);
if (Out.IsBound()) {
Out.Execute(Devices, CurrentDevice);
}
});
});
}
Expand Down Expand Up @@ -142,14 +145,10 @@ void UOdinAudioCapture::ChangeCaptureDeviceById(FString NewDeviceId, bool& bSucc
void UOdinAudioCapture::AsyncChangeCaptureDeviceById(FString NewDeviceId,
FChangeCaptureDeviceDelegate OnChangeCompleted)
{
AsyncTask(ENamedThreads::AnyHiPriThreadNormalTask, [this, NewDeviceId, OnChangeCompleted]() {
TryRunAsyncChangeDeviceRequest(OnChangeCompleted, [this, NewDeviceId, OnChangeCompleted]() {
bool bSuccess;
ChangeCaptureDeviceById(NewDeviceId, bSuccess);

AsyncTask(ENamedThreads::GameThread, [OnChangeCompleted, bSuccess]() {
// We execute the delegate along with the param.
OnChangeCompleted.Execute(bSuccess);
});
FinalizeCaptureDeviceChange(OnChangeCompleted, bSuccess);
});
}

Expand All @@ -170,14 +169,35 @@ void UOdinAudioCapture::ChangeCaptureDeviceByName(FName DeviceName, bool& bSucce
void UOdinAudioCapture::AsyncChangeCaptureDeviceByName(
FName DeviceName, FChangeCaptureDeviceDelegate OnChangeCompleted)
{
AsyncTask(ENamedThreads::AnyHiPriThreadNormalTask, [this, DeviceName, OnChangeCompleted]() {
TryRunAsyncChangeDeviceRequest(OnChangeCompleted, [this, DeviceName, OnChangeCompleted]() {
bool bSuccess;
ChangeCaptureDeviceByName(DeviceName, bSuccess);
FinalizeCaptureDeviceChange(OnChangeCompleted, bSuccess);
});
}

AsyncTask(ENamedThreads::GameThread, [OnChangeCompleted, bSuccess]() {
// We execute the delegate along with the param
void UOdinAudioCapture::TryRunAsyncChangeDeviceRequest(
FChangeCaptureDeviceDelegate OnChangeCompleted, TFunction<void()> ChangeDeviceFunction)
{
if (IsCurrentlyChangingDevice) {
if (OnChangeCompleted.IsBound()) {
OnChangeCompleted.Execute(false);
}
return;
}
IsCurrentlyChangingDevice = true;
AsyncTask(ENamedThreads::AnyHiPriThreadNormalTask, ChangeDeviceFunction);
}

void UOdinAudioCapture::FinalizeCaptureDeviceChange(FChangeCaptureDeviceDelegate OnChangeCompleted,
bool& bSuccess)
{
AsyncTask(ENamedThreads::GameThread, [OnChangeCompleted, bSuccess, this]() {
IsCurrentlyChangingDevice = false;
// We execute the delegate along with the param
if (OnChangeCompleted.IsBound()) {
OnChangeCompleted.Execute(bSuccess);
});
}
});
}

Expand All @@ -203,7 +223,7 @@ bool UOdinAudioCapture::ChangeCaptureDevice(const DeviceCheck& DeviceCheckFuncti
if (bSuccess) {
UE_LOG(Odin, VeryVerbose, TEXT("Selected index: %d with device id: %s"),
CurrentSelectedDeviceIndex, *CustomSelectedDevice.DeviceId);
RestartStream();
RestartCapturing();
}
return bSuccess;
}
Expand Down Expand Up @@ -243,36 +263,109 @@ void UOdinAudioCapture::Tick(float DeltaTime)
TimeWithoutStreamUpdate = 0.0f;
LastStreamTime = 0.0f;
CurrentSelectedDeviceIndex = INDEX_NONE;
RestartStream();
RestartCapturing();
OnCaptureDeviceReset.Broadcast();
}
}
}
}

void UOdinAudioCapture::RestartStream()
void UOdinAudioCapture::InitializeGenerator()
{
TArray<FOdinCaptureDeviceInfo> Devices;
GetCaptureDevicesAvailable(Devices);
if (Devices.Num() > 0) {
FOdinCaptureDeviceInfo CurrentDevice;
if (CurrentSelectedDeviceIndex >= 0 && CurrentSelectedDeviceIndex < Devices.Num()) {
CurrentDevice = Devices[CurrentSelectedDeviceIndex];
} else {
CurrentDevice = Devices[0];
}
const FAudioCaptureDeviceInfo AudioCaptureDeviceInfo = CurrentDevice.AudioCaptureInfo;
Init(AudioCaptureDeviceInfo.SampleRate, AudioCaptureDeviceInfo.NumInputChannels);
UE_LOG(Odin, Display, TEXT("Switched to input device %s, Sample Rate: %d, Channels: %d"),
*AudioCaptureDeviceInfo.DeviceName.ToString(), AudioCaptureDeviceInfo.SampleRate,
AudioCaptureDeviceInfo.NumInputChannels);
}
}

void UOdinAudioCapture::RetrieveCurrentSelectedDeviceIndex()
{
Audio::FCaptureDeviceInfo Current;
AudioCapture.GetCaptureDeviceInfo(Current);
UE_LOG(
Odin, Warning,
TEXT("Using Default Device during Restart Stream, name: %s, samplerate: %d, channels: %d"),
*Current.DeviceName, Current.PreferredSampleRate, Current.InputChannels);

TArray<Audio::FCaptureDeviceInfo> OutDevices;
AudioCapture.GetCaptureDevicesAvailable(OutDevices);
for (int i = 0; i < OutDevices.Num(); ++i) {
if (OutDevices[i].DeviceId == Current.DeviceId) {
CurrentSelectedDeviceIndex = i;
}
}
}

bool UOdinAudioCapture::GetIsPaused() const
{
return bIsCapturingPaused;
}

void UOdinAudioCapture::SetIsPaused(bool newValue)
{
bIsCapturingPaused = newValue;
}

bool UOdinAudioCapture::RestartCapturing(bool bAutomaticallyStartCapture)
{
if (AudioCapture.IsStreamOpen()) {
AudioCapture.CloseStream();
}
// Below here is basically a copy of the UAudioCapture::OpenDefaultAudioStream() implementation,
// except for setting the Params.DeviceIndex.

#if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 3

Audio::FOnAudioCaptureFunction OnCapture = [this](const void* AudioData, int32 NumFrames,
int32 InNumChannels, int32 InSampleRate,
double StreamTime, bool bOverFlow) {
if (!bIsCapturingPaused) {
OnGeneratedAudio((const float*)AudioData, NumFrames * InNumChannels);
}
};
#else
// Below here is basically a copy of the UAudioCapture::OpenDefaultAudioStream() implementation,
// except for setting the Params.DeviceIndex.
Audio::FOnCaptureFunction OnCapture = [this](const float* AudioData, int32 NumFrames,
int32 InNumChannels, int32 InSampleRate,
double StreamTime, bool bOverFlow) {
OnGeneratedAudio(AudioData, NumFrames * InNumChannels);
if (!bIsCapturingPaused) {
OnGeneratedAudio(AudioData, NumFrames * InNumChannels);
}
};
#endif

if (CurrentSelectedDeviceIndex < 0) {
RetrieveCurrentSelectedDeviceIndex();
}

Audio::FAudioCaptureDeviceParams Params;
Params.DeviceIndex = CurrentSelectedDeviceIndex;
#if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 3
bool bSuccess = AudioCapture.OpenAudioCaptureStream(Params, MoveTemp(OnCapture), 1024);
#else
bool bSuccess = AudioCapture.OpenCaptureStream(Params, MoveTemp(OnCapture), 1024);
#endif
// OpenCaptureStream automatically closes the capture stream, if it's already active.
if (AudioCapture.OpenCaptureStream(Params, MoveTemp(OnCapture), 1024)) {
if (bSuccess) {
// If we opened the capture stream successfully, get the capture device info and initialize
// the UAudioGenerator.
Audio::FCaptureDeviceInfo Info;
if (AudioCapture.GetCaptureDeviceInfo(Info, CurrentSelectedDeviceIndex)) {
Init(Info.PreferredSampleRate, Info.InputChannels);
UE_LOG(Odin, Display, TEXT("Switched to input device %s"), *Info.DeviceName);
InitializeGenerator();
// Restart the audio capture stream.
if (bAutomaticallyStartCapture) {
AudioCapture.StartStream();
}
}

// Restart the audio capture stream.
AudioCapture.StartStream();
}
return bSuccess;
}
Loading

0 comments on commit 8a70f72

Please sign in to comment.