diff --git a/Source/DTFluxRemote/DTFluxRemote.Build.cs b/Source/DTFluxRemote/DTFluxRemote.Build.cs index d144e4c..5241f76 100644 --- a/Source/DTFluxRemote/DTFluxRemote.Build.cs +++ b/Source/DTFluxRemote/DTFluxRemote.Build.cs @@ -23,6 +23,8 @@ public class DTFluxRemote : ModuleRules "HttpServer", "JsonUtilities", "Json", + "DTFluxProjectSettings", + "AvalancheMedia" } ); } diff --git a/Source/DTFluxRemote/Private/DTFluxRemoteSubsystem.cpp b/Source/DTFluxRemote/Private/DTFluxRemoteSubsystem.cpp index fe48c70..4a6ad93 100644 --- a/Source/DTFluxRemote/Private/DTFluxRemoteSubsystem.cpp +++ b/Source/DTFluxRemote/Private/DTFluxRemoteSubsystem.cpp @@ -3,10 +3,13 @@ #include "DTFluxRemoteSubsystem.h" #include "DTFluxRemoteSubsystem.h" + +#include "DTFluxGeneralSettings.h" #include "DTFluxRemoteModule.h" #include "DTFluxRemoteModule.h" #include "HttpServerModule.h" #include "IHttpRouter.h" +#include "Rundown/AvaRundown.h" #include "Json.h" #include "Engine/Engine.h" #include "Misc/DateTime.h" @@ -18,6 +21,16 @@ void UDTFluxRemoteSubsystem::Initialize(FSubsystemCollectionBase& Collection) UE_LOG(logDTFluxRemote, Log, TEXT("DTFlux API Subsystem Initialized")); +#if WITH_EDITOR + // S'abonner aux changements de settings + if (UDTFluxGeneralSettings* Settings = GetMutableDefault()) + { + SettingsRundownChangedHandle = Settings->OnRemoteRundownChanged.AddUObject( + this, &UDTFluxRemoteSubsystem::OnSettingsRundownChanged + ); + } +#endif + LoadRundownFromSettings(); // Auto-start server (optionnel) StartHTTPServer(63350); } @@ -25,7 +38,22 @@ void UDTFluxRemoteSubsystem::Initialize(FSubsystemCollectionBase& Collection) void UDTFluxRemoteSubsystem::Deinitialize() { StopHTTPServer(); + +#if WITH_EDITOR + // Se désabonner du delegate + if (UDTFluxGeneralSettings* Settings = GetMutableDefault()) + { + if (SettingsRundownChangedHandle.IsValid()) + { + Settings->OnRemoteRundownChanged.Remove(SettingsRundownChangedHandle); + SettingsRundownChangedHandle.Reset(); + } + } +#endif + + // Décharger proprement le rundown + UnloadCurrentRundown(); UE_LOG(logDTFluxRemote, Log, TEXT("DTFlux API Subsystem Deinitialized")); Super::Deinitialize(); @@ -64,9 +92,9 @@ bool UDTFluxRemoteSubsystem::StartHTTPServer(int32 Port) UE_LOG(logDTFluxRemote, Log, TEXT("DTFlux HTTP API Server started on port %d"), ServerPort); UE_LOG(logDTFluxRemote, Log, TEXT("Base URL: http://localhost:%d/dtflux/api/v1"), ServerPort); UE_LOG(logDTFluxRemote, Log, TEXT("Available routes:")); - UE_LOG(logDTFluxRemote, Log, TEXT(" POST /dtflux/api/v1/title")); - UE_LOG(logDTFluxRemote, Log, TEXT(" POST /dtflux/api/v1/title-bib")); - UE_LOG(logDTFluxRemote, Log, TEXT(" POST /dtflux/api/v1/commands")); + UE_LOG(logDTFluxRemote, Log, TEXT(" PUT /dtflux/api/v1/title")); + UE_LOG(logDTFluxRemote, Log, TEXT(" PUT /dtflux/api/v1/title-bib")); + UE_LOG(logDTFluxRemote, Log, TEXT(" PUT /dtflux/api/v1/commands")); return true; } @@ -111,21 +139,21 @@ void UDTFluxRemoteSubsystem::SetupRoutes() // Route: POST /dtflux/api/v1/title TitleRouteHandle = HttpRouter->BindRoute( FHttpPath(TEXT("/dtflux/api/v1/title")), - EHttpServerRequestVerbs::VERB_GET, + EHttpServerRequestVerbs::VERB_PUT, FHttpRequestHandler::CreateUObject(this, &UDTFluxRemoteSubsystem::HandleTitleRequest) ); // Route: POST /dtflux/api/v1/title-bib TitleBibRouteHandle = HttpRouter->BindRoute( FHttpPath(TEXT("/dtflux/api/v1/title-bib")), - EHttpServerRequestVerbs::VERB_GET, + EHttpServerRequestVerbs::VERB_PUT, FHttpRequestHandler::CreateUObject(this, &UDTFluxRemoteSubsystem::HandleTitleBibRequest) - ); + ); // Route: POST /dtflux/api/v1/commands CommandsRouteHandle = HttpRouter->BindRoute( FHttpPath(TEXT("/dtflux/api/v1/commands")), - EHttpServerRequestVerbs::VERB_GET, + EHttpServerRequestVerbs::VERB_PUT, FHttpRequestHandler::CreateUObject(this, &UDTFluxRemoteSubsystem::HandleCommandsRequest) ); @@ -316,6 +344,56 @@ bool UDTFluxRemoteSubsystem::ParseCommandData(const TSharedPtr& Jso return true; } +void UDTFluxRemoteSubsystem::UnloadCurrentRundown() +{ +} + +void UDTFluxRemoteSubsystem::LoadRundownFromSettings() +{ + const UDTFluxGeneralSettings* Settings = GetDefault(); + if (!Settings) + { + UE_LOG(logDTFluxRemote, Warning, TEXT("Cannot access DTFlux settings")); + return; + } + + TSoftObjectPtr RundownAsset = Settings->RemoteTargetRundown; + + if (RundownAsset.IsNull()) + { + UE_LOG(logDTFluxRemote, Log, TEXT("No rundown specified in settings")); + UnloadCurrentRundown(); + return; + } + + // Si c'est le même rundown, pas besoin de recharger + if (RemotedRundown && RemotedRundown == RundownAsset.LoadSynchronous()) + { + UE_LOG(logDTFluxRemote, Log, TEXT("Rundown already loaded: %s"), *RundownAsset.ToString()); + return; + } + + // Décharger l'ancien rundown d'abord + UnloadCurrentRundown(); + + // Charger le nouveau rundown + if (LoadRundown(RundownAsset)) + { + UE_LOG(logDTFluxRemote, Log, TEXT("Successfully loaded rundown from settings: %s"), *RundownAsset.ToString()); + } + else + { + UE_LOG(logDTFluxRemote, Error, TEXT("Failed to load rundown from settings: %s"), *RundownAsset.ToString()); + } +} + +#if WITH_EDITOR +void UDTFluxRemoteSubsystem::OnSettingsRundownChanged(const TSoftObjectPtr& NewRundown) +{ +} +#endif + + // Manual processing functions for testing bool UDTFluxRemoteSubsystem::ProcessTitleData(const FString& JsonString) { @@ -373,4 +451,7 @@ bool UDTFluxRemoteSubsystem::ProcessCommandData(const FString& JsonString) } return false; -} \ No newline at end of file +} + +void UDTFluxRemoteSubsystem::LoadRundown + diff --git a/Source/DTFluxRemote/Public/DTFluxRemoteSubsystem.h b/Source/DTFluxRemote/Public/DTFluxRemoteSubsystem.h index 6fcfbf8..8aae921 100644 --- a/Source/DTFluxRemote/Public/DTFluxRemoteSubsystem.h +++ b/Source/DTFluxRemote/Public/DTFluxRemoteSubsystem.h @@ -9,6 +9,7 @@ #include "IHttpRouter.h" #include "DTFluxRemoteSubsystem.generated.h" +class UAvaRundown; DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnTitleReceived, const FDTFluxRemoteTitleData&, TitleData); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnTitleBibReceived, const FDTFluxRemoteBibData&, TitleBibData); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnCommandReceived, const FDTFluxRemoteCommandData&, CommandData); @@ -73,10 +74,26 @@ private: private: TSharedPtr HttpRouter; + TSoftObjectPtr RemotedRundown; int32 ServerPort = 63350; bool bServerRunning = false; FHttpRouteHandle TitleRouteHandle; FHttpRouteHandle TitleBibRouteHandle; FHttpRouteHandle CommandsRouteHandle; + + void UnloadCurrentRundown(); + void LoadRundownFromSettings(); + void LoadRundown(); + +#if WITH_EDITOR + FDelegateHandle SettingsRundownChangedHandle; +#endif + + +#if WITH_EDITOR + // Callback pour les changements de settings + UFUNCTION() + void OnSettingsRundownChanged(const TSoftObjectPtr& NewRundown); +#endif }; diff --git a/Source/DTFluxUtilities/Private/DTFluxUtils.cpp b/Source/DTFluxUtilities/Private/DTFluxUtils.cpp index 837ac20..55af051 100644 --- a/Source/DTFluxUtilities/Private/DTFluxUtils.cpp +++ b/Source/DTFluxUtilities/Private/DTFluxUtils.cpp @@ -56,10 +56,11 @@ void UFTDFluxUtils::GetFullName(const int Bib, FText& OutFullName) UE_LOG(logDTFluxUtilities, Error, TEXT("DTFluxCoreSubsystem not available")); } -void UFTDFluxUtils::SortSplitRankingsByRank(TArray& Rankings) +void UFTDFluxUtils::SortSplitRankingsByRank(TArray& Rankings, TArray& OutRankings) { Rankings.Sort([](const FDTFluxSplitRanking& A, const FDTFluxSplitRanking& B) { return A.Rank < B.Rank; }); + OutRankings = Rankings; } \ No newline at end of file diff --git a/Source/DTFluxUtilities/Public/DTFluxUtils.h b/Source/DTFluxUtilities/Public/DTFluxUtils.h index 15cf5bb..75eeb1c 100644 --- a/Source/DTFluxUtilities/Public/DTFluxUtils.h +++ b/Source/DTFluxUtilities/Public/DTFluxUtils.h @@ -71,7 +71,7 @@ public: static void GetFullName(const int Bib, FText& OutFullName); UFUNCTION(BlueprintCallable, Category="DTFlux|Utils") - static void SortSplitRankingsByRank(TArray& Rankings); + static void SortSplitRankingsByRank(TArray& Rankings, TArray& OutRankings); };