├── Config ├── DefaultEditor.ini ├── DefaultGame.ini ├── PS4 │ └── PS4Engine.ini ├── IOS │ └── IOSEngine.ini ├── Mac │ └── MacEngine.ini ├── Linux │ └── LinuxEngine.ini ├── Android │ └── AndroidEngine.ini ├── Switch │ └── SwitchEngine.ini ├── Windows │ └── WindowsEngine.ini ├── XboxOne │ └── XboxOneEngine.ini ├── SteamVRBindings │ ├── rift.json │ ├── vive.json │ ├── gamepad.json │ ├── indexhmd.json │ ├── vive_pro.json │ ├── knuckles.json │ ├── oculus_touch.json │ ├── vive_controller.json │ ├── vive_cosmos_controller.json │ ├── holographic_controller.json │ ├── vive_tracker_camera.json │ └── steamvr_manifest.json ├── DefaultEngine.ini └── steamvr_ue_editor_app.json ├── Content ├── Untitled.umap └── MyMyActor.uasset ├── Source ├── UE4SpotifyApi │ ├── UE4SpotifyApi.h │ ├── UE4SpotifyApi.cpp │ ├── Private │ │ ├── SpotifyAPICredentials.cpp │ │ ├── Types.h │ │ ├── SpotifyAPICredentials.h │ │ ├── MyActor.cpp │ │ └── SpotifyAPIClient.cpp │ ├── Public │ │ ├── MyActor.h │ │ └── SpotifyAPIClient.h │ └── UE4SpotifyApi.Build.cs ├── UE4SpotifyApi.Target.cs └── UE4SpotifyApiEditor.Target.cs ├── readme.md ├── UE4SpotifyApi.uproject └── .gitignore /Config/DefaultEditor.ini: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Content/Untitled.umap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarkusTheOrt/UE4SpotifyWebAPI/HEAD/Content/Untitled.umap -------------------------------------------------------------------------------- /Content/MyMyActor.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarkusTheOrt/UE4SpotifyWebAPI/HEAD/Content/MyMyActor.uasset -------------------------------------------------------------------------------- /Config/DefaultGame.ini: -------------------------------------------------------------------------------- 1 | [/Script/EngineSettings.GeneralProjectSettings] 2 | ProjectID=9C5A2BB645FDA4DDA5F7DE8993B0F0D2 3 | -------------------------------------------------------------------------------- /Source/UE4SpotifyApi/UE4SpotifyApi.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | 7 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # DEPRECATED Repository. 2 | You can find a new version working in Unreal 4.26 and 5.0.0 Early Access [Here](https://github.com/MarkusTheOrt/Spotify-Unreal-Controls) 3 | --- 4 | -------------------------------------------------------------------------------- /Config/PS4/PS4Engine.ini: -------------------------------------------------------------------------------- 1 | [/Script/PS4PlatformEditor.PS4TargetSettings] 2 | ;AudioSampleRate=48000 3 | ;AudioMaxChannels=32 4 | AudioCallbackBufferFrameSize=256 5 | AudioNumBuffersToEnqueue=7 6 | AudioNumSourceWorkers=4 7 | 8 | -------------------------------------------------------------------------------- /Config/IOS/IOSEngine.ini: -------------------------------------------------------------------------------- 1 | [/Script/IOSRuntimeSettings.IOSRuntimeSettings] 2 | ;AudioSampleRate=48000 3 | AudioMaxChannels=16 4 | ;AudioCallbackBufferFrameSize=1024 5 | ;AudioNumBuffersToEnqueue=2 6 | ;AudioNumSourceWorkers=0 7 | 8 | -------------------------------------------------------------------------------- /Config/Mac/MacEngine.ini: -------------------------------------------------------------------------------- 1 | [/Script/MacTargetPlatform.MacTargetSettings] 2 | ;AudioSampleRate=48000 3 | ;AudioMaxChannels=32 4 | ;AudioCallbackBufferFrameSize=1024 5 | ;AudioNumBuffersToEnqueue=2 6 | ;AudioNumSourceWorkers=0 7 | 8 | -------------------------------------------------------------------------------- /Config/Linux/LinuxEngine.ini: -------------------------------------------------------------------------------- 1 | [/Script/LinuxTargetPlatform.LinuxTargetSettings] 2 | ;AudioSampleRate=48000 3 | AudioMaxChannels=16 4 | ;AudioCallbackBufferFrameSize=1024 5 | ;AudioNumBuffersToEnqueue=2 6 | ;AudioNumSourceWorkers=0 7 | 8 | -------------------------------------------------------------------------------- /Config/Android/AndroidEngine.ini: -------------------------------------------------------------------------------- 1 | [/Script/AndroidRuntimeSettings.AndroidRuntimeSettings] 2 | ;AudioSampleRate=48000 3 | AudioMaxChannels=12 4 | ;AudioCallbackBufferFrameSize=1024 5 | ;AudioNumBuffersToEnqueue=2 6 | ;AudioNumSourceWorkers=0 7 | 8 | -------------------------------------------------------------------------------- /Config/Switch/SwitchEngine.ini: -------------------------------------------------------------------------------- 1 | [/Script/SwitchRuntimeSettings.SwitchRuntimeSettings] 2 | ;AudioSampleRate=48000 3 | AudioMaxChannels=16 4 | ;AudioCallbackBufferFrameSize=1024 5 | ;AudioNumBuffersToEnqueue=2 6 | ;AudioNumSourceWorkers=0 7 | 8 | -------------------------------------------------------------------------------- /Config/Windows/WindowsEngine.ini: -------------------------------------------------------------------------------- 1 | [/Script/WindowsTargetPlatform.WindowsTargetSettings] 2 | ;AudioSampleRate=48000 3 | ;AudioMaxChannels=32 4 | AudioCallbackBufferFrameSize=256 5 | AudioNumBuffersToEnqueue=7 6 | ;AudioNumSourceWorkers=0 7 | 8 | -------------------------------------------------------------------------------- /Config/XboxOne/XboxOneEngine.ini: -------------------------------------------------------------------------------- 1 | [/Script/XboxOnePlatformEditor.XboxOneTargetSettings] 2 | ;AudioSampleRate=48000 3 | ;AudioMaxChannels=32 4 | AudioCallbackBufferFrameSize=256 5 | AudioNumBuffersToEnqueue=7 6 | ;AudioNumSourceWorkers=0 7 | 8 | -------------------------------------------------------------------------------- /Config/SteamVRBindings/rift.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Default bindings for Rift Headset", 3 | "controller_type": "rift", 4 | "last_edited_by": "UnrealEngine", 5 | "bindings": 6 | { 7 | "/actions/main": 8 | { 9 | "sources": [] 10 | } 11 | }, 12 | "description": "" 13 | } -------------------------------------------------------------------------------- /Config/SteamVRBindings/vive.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Default bindings for Vive Headset", 3 | "controller_type": "vive", 4 | "last_edited_by": "UnrealEngine", 5 | "bindings": 6 | { 7 | "/actions/main": 8 | { 9 | "sources": [] 10 | } 11 | }, 12 | "description": "" 13 | } -------------------------------------------------------------------------------- /Config/SteamVRBindings/gamepad.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Default bindings for Gamepads", 3 | "controller_type": "gamepad", 4 | "last_edited_by": "UnrealEngine", 5 | "bindings": 6 | { 7 | "/actions/main": 8 | { 9 | "sources": [] 10 | } 11 | }, 12 | "description": "" 13 | } -------------------------------------------------------------------------------- /Source/UE4SpotifyApi/UE4SpotifyApi.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "UE4SpotifyApi.h" 4 | #include "Modules/ModuleManager.h" 5 | 6 | IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, UE4SpotifyApi, "UE4SpotifyApi" ); 7 | -------------------------------------------------------------------------------- /Config/SteamVRBindings/indexhmd.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Default bindings for Valve Index Headset", 3 | "controller_type": "indexhmd", 4 | "last_edited_by": "UnrealEngine", 5 | "bindings": 6 | { 7 | "/actions/main": 8 | { 9 | "sources": [] 10 | } 11 | }, 12 | "description": "" 13 | } -------------------------------------------------------------------------------- /Config/SteamVRBindings/vive_pro.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Default bindings for Vive Pro Headset", 3 | "controller_type": "vive_pro", 4 | "last_edited_by": "UnrealEngine", 5 | "bindings": 6 | { 7 | "/actions/main": 8 | { 9 | "sources": [] 10 | } 11 | }, 12 | "description": "" 13 | } -------------------------------------------------------------------------------- /UE4SpotifyApi.uproject: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "EngineAssociation": "4.24", 4 | "Category": "", 5 | "Description": "", 6 | "Modules": [ 7 | { 8 | "Name": "UE4SpotifyApi", 9 | "Type": "Runtime", 10 | "LoadingPhase": "Default", 11 | "AdditionalDependencies": [ 12 | "Engine" 13 | ] 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /Config/DefaultEngine.ini: -------------------------------------------------------------------------------- 1 | [/Script/Engine.RendererSettings] 2 | r.DefaultFeature.AutoExposure.ExtendDefaultLuminanceRange=True 3 | 4 | [/Script/HardwareTargeting.HardwareTargetingSettings] 5 | TargetedHardwareClass=Desktop 6 | AppliedTargetedHardwareClass=Desktop 7 | DefaultGraphicsPerformance=Maximum 8 | AppliedDefaultGraphicsPerformance=Maximum 9 | 10 | 11 | -------------------------------------------------------------------------------- /Config/steamvr_ue_editor_app.json: -------------------------------------------------------------------------------- 1 | { 2 | "source": "UE", 3 | "applications": [ 4 | { 5 | "app_key": "application.generated.ue.ue4spotifyapi-11590370.ue4editor.exe", 6 | "launch_type": "url", 7 | "url": "steam://launch/", 8 | "action_manifest_path": "D:/UE4SpotifyApi/Config/SteamVRBindings/steamvr_manifest.json", 9 | "strings": 10 | { 11 | "en_us": 12 | { 13 | "name": "UE4SpotifyApi-11590370 [UE Editor]" 14 | } 15 | } 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /Source/UE4SpotifyApi.Target.cs: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class UE4SpotifyApiTarget : TargetRules 7 | { 8 | public UE4SpotifyApiTarget(TargetInfo Target) : base(Target) 9 | { 10 | Type = TargetType.Game; 11 | DefaultBuildSettings = BuildSettingsVersion.V2; 12 | 13 | ExtraModuleNames.AddRange( new string[] { "UE4SpotifyApi" } ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Source/UE4SpotifyApiEditor.Target.cs: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class UE4SpotifyApiEditorTarget : TargetRules 7 | { 8 | public UE4SpotifyApiEditorTarget(TargetInfo Target) : base(Target) 9 | { 10 | Type = TargetType.Editor; 11 | DefaultBuildSettings = BuildSettingsVersion.V2; 12 | 13 | ExtraModuleNames.AddRange( new string[] { "UE4SpotifyApi" } ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Source/UE4SpotifyApi/Private/SpotifyAPICredentials.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "SpotifyAPICredentials.h" 5 | #include "Kismet/GameplayStatics.h" 6 | 7 | 8 | void USpotifyAPICredentials::FillInCredentials(const FString& InPubKey, const FString& InSecKey) 9 | { 10 | PubKey = InPubKey; 11 | SecKey = InSecKey; 12 | 13 | UGameplayStatics::SaveGameToSlot(this, TEXT("SpotifySEC"), 0); 14 | } 15 | 16 | void USpotifyAPICredentials::GetCredentials(FString& OutPubKey, FString& OutSecKey) const 17 | { 18 | OutPubKey = PubKey; 19 | OutSecKey = SecKey; 20 | } 21 | -------------------------------------------------------------------------------- /Source/UE4SpotifyApi/Private/Types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #include "CoreMinimal.h" 5 | #include "Types.generated.h" 6 | 7 | UENUM(BlueprintType) 8 | enum ESpotifyAPIScopes 9 | { 10 | UserLibraryRead, 11 | UserLibraryModify, 12 | PlaylistReadPrivate, 13 | PlaylistModifyPublic, 14 | PlaylistModifyPrivate, 15 | PlaylistReadCollaborative, 16 | UserReadRecentlyPlayed, 17 | UserTopRead, 18 | UserReadPrivate, 19 | UserReadEmail, 20 | UserReadBirthdate, 21 | Streaming, 22 | UserModifyPlaybackState, 23 | UserReadPlaybackState, 24 | UserReadCurrentlyPlaying, 25 | UserFollowModify, 26 | UserFollowRead 27 | }; 28 | 29 | 30 | -------------------------------------------------------------------------------- /Source/UE4SpotifyApi/Public/MyActor.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "GameFramework/Actor.h" 7 | #include "MyActor.generated.h" 8 | 9 | UCLASS() 10 | class UE4SPOTIFYAPI_API AMyActor : public AActor 11 | { 12 | GENERATED_BODY() 13 | 14 | public: 15 | // Sets default values for this actor's properties 16 | AMyActor(); 17 | 18 | protected: 19 | // Called when the game starts or when spawned 20 | virtual void BeginPlay() override; 21 | 22 | public: 23 | // Called every frame 24 | virtual void Tick(float DeltaTime) override; 25 | 26 | virtual void BeginDestroy() override; 27 | 28 | }; 29 | -------------------------------------------------------------------------------- /Source/UE4SpotifyApi/Private/SpotifyAPICredentials.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "GameFramework/SaveGame.h" 7 | #include "SpotifyAPICredentials.generated.h" 8 | 9 | 10 | /** 11 | * 12 | */ 13 | UCLASS() 14 | class USpotifyAPICredentials : public USaveGame 15 | { 16 | GENERATED_BODY() 17 | 18 | 19 | private: 20 | 21 | UPROPERTY(SaveGame) 22 | FString PubKey; 23 | 24 | UPROPERTY(SaveGame) 25 | FString SecKey; 26 | 27 | public: 28 | 29 | void FillInCredentials(const FString& InPubKey, const FString& InSecKey); 30 | 31 | void GetCredentials(FString& OutPubKey, FString& OutSecKey) const; 32 | 33 | }; 34 | -------------------------------------------------------------------------------- /Source/UE4SpotifyApi/Private/MyActor.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "../Public/MyActor.h" 5 | #include "../Public/SpotifyAPIClient.h" 6 | 7 | // Sets default values 8 | AMyActor::AMyActor() 9 | { 10 | // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. 11 | PrimaryActorTick.bCanEverTick = true; 12 | 13 | } 14 | 15 | // Called when the game starts or when spawned 16 | void AMyActor::BeginPlay() 17 | { 18 | Super::BeginPlay(); 19 | 20 | ISpotifyAPIClient::GetStarted(); 21 | 22 | } 23 | 24 | // Called every frame 25 | void AMyActor::Tick(float DeltaTime) 26 | { 27 | Super::Tick(DeltaTime); 28 | 29 | } 30 | 31 | void AMyActor::BeginDestroy() 32 | { 33 | Super::BeginDestroy(); 34 | 35 | ISpotifyAPIClient::Shutdown(); 36 | 37 | } 38 | 39 | -------------------------------------------------------------------------------- /Source/UE4SpotifyApi/UE4SpotifyApi.Build.cs: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class UE4SpotifyApi : ModuleRules 6 | { 7 | public UE4SpotifyApi(ReadOnlyTargetRules Target) : base(Target) 8 | { 9 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 10 | 11 | PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Networking", "Http", "Json", "JsonUtilities", "Sockets" }); 12 | 13 | PrivateDependencyModuleNames.AddRange(new string[] { }); 14 | 15 | // Uncomment if you are using Slate UI 16 | // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); 17 | 18 | // Uncomment if you are using online features 19 | // PrivateDependencyModuleNames.Add("OnlineSubsystem"); 20 | 21 | // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Config/SteamVRBindings/knuckles.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Default bindings for ValveIndex", 3 | "controller_type": "knuckles", 4 | "last_edited_by": "UnrealEngine", 5 | "bindings": 6 | { 7 | "/actions/main": 8 | { 9 | "sources": [], 10 | "poses": [ 11 | { 12 | "output": "/actions/main/in/controllerleft", 13 | "path": "/user/hand/left/pose/raw", 14 | "requirement": "optional" 15 | }, 16 | { 17 | "output": "/actions/main/in/controllerright", 18 | "path": "/user/hand/right/pose/raw" 19 | } 20 | ], 21 | "skeleton": [ 22 | { 23 | "output": "/actions/main/in/skeletonleft", 24 | "path": "/user/hand/left/input/skeleton/left" 25 | }, 26 | { 27 | "output": "/actions/main/in/skeletonright", 28 | "path": "/user/hand/right/input/skeleton/right" 29 | } 30 | ], 31 | "haptics": [ 32 | { 33 | "output": "/actions/main/out/vibrateleft", 34 | "path": "/user/hand/left/output/haptic" 35 | }, 36 | { 37 | "output": "/actions/main/out/vibrateright", 38 | "path": "/user/hand/right/output/haptic" 39 | } 40 | ] 41 | } 42 | }, 43 | "description": "" 44 | } -------------------------------------------------------------------------------- /Config/SteamVRBindings/oculus_touch.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Default bindings for OculusTouch", 3 | "controller_type": "oculus_touch", 4 | "last_edited_by": "UnrealEngine", 5 | "bindings": 6 | { 7 | "/actions/main": 8 | { 9 | "sources": [], 10 | "poses": [ 11 | { 12 | "output": "/actions/main/in/controllerleft", 13 | "path": "/user/hand/left/pose/raw", 14 | "requirement": "optional" 15 | }, 16 | { 17 | "output": "/actions/main/in/controllerright", 18 | "path": "/user/hand/right/pose/raw" 19 | } 20 | ], 21 | "skeleton": [ 22 | { 23 | "output": "/actions/main/in/skeletonleft", 24 | "path": "/user/hand/left/input/skeleton/left" 25 | }, 26 | { 27 | "output": "/actions/main/in/skeletonright", 28 | "path": "/user/hand/right/input/skeleton/right" 29 | } 30 | ], 31 | "haptics": [ 32 | { 33 | "output": "/actions/main/out/vibrateleft", 34 | "path": "/user/hand/left/output/haptic" 35 | }, 36 | { 37 | "output": "/actions/main/out/vibrateright", 38 | "path": "/user/hand/right/output/haptic" 39 | } 40 | ] 41 | } 42 | }, 43 | "description": "" 44 | } -------------------------------------------------------------------------------- /Config/SteamVRBindings/vive_controller.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Default bindings for Vive", 3 | "controller_type": "vive_controller", 4 | "last_edited_by": "UnrealEngine", 5 | "bindings": 6 | { 7 | "/actions/main": 8 | { 9 | "sources": [], 10 | "poses": [ 11 | { 12 | "output": "/actions/main/in/controllerleft", 13 | "path": "/user/hand/left/pose/raw", 14 | "requirement": "optional" 15 | }, 16 | { 17 | "output": "/actions/main/in/controllerright", 18 | "path": "/user/hand/right/pose/raw" 19 | } 20 | ], 21 | "skeleton": [ 22 | { 23 | "output": "/actions/main/in/skeletonleft", 24 | "path": "/user/hand/left/input/skeleton/left" 25 | }, 26 | { 27 | "output": "/actions/main/in/skeletonright", 28 | "path": "/user/hand/right/input/skeleton/right" 29 | } 30 | ], 31 | "haptics": [ 32 | { 33 | "output": "/actions/main/out/vibrateleft", 34 | "path": "/user/hand/left/output/haptic" 35 | }, 36 | { 37 | "output": "/actions/main/out/vibrateright", 38 | "path": "/user/hand/right/output/haptic" 39 | } 40 | ] 41 | } 42 | }, 43 | "description": "" 44 | } -------------------------------------------------------------------------------- /Config/SteamVRBindings/vive_cosmos_controller.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Default bindings for Cosmos", 3 | "controller_type": "vive_cosmos_controller", 4 | "last_edited_by": "UnrealEngine", 5 | "bindings": 6 | { 7 | "/actions/main": 8 | { 9 | "sources": [], 10 | "poses": [ 11 | { 12 | "output": "/actions/main/in/controllerleft", 13 | "path": "/user/hand/left/pose/raw", 14 | "requirement": "optional" 15 | }, 16 | { 17 | "output": "/actions/main/in/controllerright", 18 | "path": "/user/hand/right/pose/raw" 19 | } 20 | ], 21 | "skeleton": [ 22 | { 23 | "output": "/actions/main/in/skeletonleft", 24 | "path": "/user/hand/left/input/skeleton/left" 25 | }, 26 | { 27 | "output": "/actions/main/in/skeletonright", 28 | "path": "/user/hand/right/input/skeleton/right" 29 | } 30 | ], 31 | "haptics": [ 32 | { 33 | "output": "/actions/main/out/vibrateleft", 34 | "path": "/user/hand/left/output/haptic" 35 | }, 36 | { 37 | "output": "/actions/main/out/vibrateright", 38 | "path": "/user/hand/right/output/haptic" 39 | } 40 | ] 41 | } 42 | }, 43 | "description": "" 44 | } -------------------------------------------------------------------------------- /Config/SteamVRBindings/holographic_controller.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Default bindings for MixedReality", 3 | "controller_type": "holographic_controller", 4 | "last_edited_by": "UnrealEngine", 5 | "bindings": 6 | { 7 | "/actions/main": 8 | { 9 | "sources": [], 10 | "poses": [ 11 | { 12 | "output": "/actions/main/in/controllerleft", 13 | "path": "/user/hand/left/pose/raw", 14 | "requirement": "optional" 15 | }, 16 | { 17 | "output": "/actions/main/in/controllerright", 18 | "path": "/user/hand/right/pose/raw" 19 | } 20 | ], 21 | "skeleton": [ 22 | { 23 | "output": "/actions/main/in/skeletonleft", 24 | "path": "/user/hand/left/input/skeleton/left" 25 | }, 26 | { 27 | "output": "/actions/main/in/skeletonright", 28 | "path": "/user/hand/right/input/skeleton/right" 29 | } 30 | ], 31 | "haptics": [ 32 | { 33 | "output": "/actions/main/out/vibrateleft", 34 | "path": "/user/hand/left/output/haptic" 35 | }, 36 | { 37 | "output": "/actions/main/out/vibrateright", 38 | "path": "/user/hand/right/output/haptic" 39 | } 40 | ] 41 | } 42 | }, 43 | "description": "" 44 | } -------------------------------------------------------------------------------- /Source/UE4SpotifyApi/Public/SpotifyAPIClient.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "HAL/Runnable.h" 7 | 8 | class FSocket; 9 | 10 | /** 11 | * 12 | */ 13 | class UE4SPOTIFYAPI_API ISpotifyAPIClient : public FRunnable 14 | { 15 | 16 | 17 | protected: 18 | 19 | static ISpotifyAPIClient* Runnable; 20 | 21 | ISpotifyAPIClient(); 22 | 23 | uint16 Port = 8064; 24 | 25 | FSocket* ListenerSocket; 26 | FSocket* ConnectionSocket; 27 | 28 | FRunnableThread* Thread; 29 | 30 | FThreadSafeCounter StopTaskCounter; 31 | 32 | FString Code; 33 | 34 | bool bFinished; 35 | 36 | public: 37 | 38 | virtual ~ISpotifyAPIClient(); 39 | 40 | static ISpotifyAPIClient* Get() 41 | { 42 | static ISpotifyAPIClient* Client; 43 | return Client; 44 | } 45 | 46 | static ISpotifyAPIClient* GetStarted(); 47 | 48 | FString GetCode() const; 49 | 50 | bool IsFinished() const 51 | { 52 | return bFinished; 53 | } 54 | 55 | virtual bool Init(); 56 | virtual uint32 Run(); 57 | virtual void Stop(); 58 | 59 | void EnsureCompletion(); 60 | 61 | static void Shutdown(); 62 | 63 | static bool IsThreadFinished(); 64 | }; 65 | 66 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Visual Studio 2015 user specific files 2 | .vs/ 3 | 4 | # Visual Studio 2015 database file 5 | *.VC.db 6 | 7 | # Compiled Object files 8 | *.slo 9 | *.lo 10 | *.o 11 | *.obj 12 | 13 | # Precompiled Headers 14 | *.gch 15 | *.pch 16 | 17 | # Compiled Dynamic libraries 18 | *.so 19 | *.dylib 20 | *.dll 21 | 22 | # Fortran module files 23 | *.mod 24 | 25 | # Compiled Static libraries 26 | *.lai 27 | *.la 28 | *.a 29 | *.lib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.ipa 36 | 37 | # These project files can be generated by the engine 38 | *.xcodeproj 39 | *.xcworkspace 40 | *.sln 41 | *.suo 42 | *.opensdf 43 | *.sdf 44 | *.VC.db 45 | *.VC.opendb 46 | 47 | # Precompiled Assets 48 | SourceArt/**/*.png 49 | SourceArt/**/*.tga 50 | 51 | # Binary Files 52 | Binaries/* 53 | Plugins/*/Binaries/* 54 | 55 | # Builds 56 | Build/* 57 | 58 | # Whitelist PakBlacklist-.txt files 59 | !Build/*/ 60 | Build/*/** 61 | !Build/*/PakBlacklist*.txt 62 | 63 | # Don't ignore icon files in Build 64 | !Build/**/*.ico 65 | 66 | # Built data for maps 67 | *_BuiltData.uasset 68 | 69 | # Configuration files generated by the Editor 70 | Saved/* 71 | 72 | # Compiled source files for the engine to use 73 | Intermediate/* 74 | Plugins/*/Intermediate/* 75 | 76 | # Cache files for the editor to use 77 | DerivedDataCache/* 78 | -------------------------------------------------------------------------------- /Config/SteamVRBindings/vive_tracker_camera.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Default bindings for Vive Trackers", 3 | "controller_type": "vive_tracker_camera", 4 | "last_edited_by": "UnrealEngine", 5 | "bindings": 6 | { 7 | "/actions/main": 8 | { 9 | "sources": [], 10 | "poses": [ 11 | { 12 | "output": "/actions/main/in/special1", 13 | "path": "/user/hand/left/pose/back", 14 | "requirement": "optional" 15 | }, 16 | { 17 | "output": "/actions/main/in/special2", 18 | "path": "/user/hand/right/pose/back", 19 | "requirement": "optional" 20 | }, 21 | { 22 | "output": "/actions/main/in/special3", 23 | "path": "/user/hand/left/pose/front", 24 | "requirement": "optional" 25 | }, 26 | { 27 | "output": "/actions/main/in/special4", 28 | "path": "/user/hand/right/pose/front", 29 | "requirement": "optional" 30 | }, 31 | { 32 | "output": "/actions/main/in/special5", 33 | "path": "/user/hand/left/pose/frontandrolled", 34 | "requirement": "optional" 35 | }, 36 | { 37 | "output": "/actions/main/in/special6", 38 | "path": "/user/hand/right/pose/frontandrolled", 39 | "requirement": "optional" 40 | }, 41 | { 42 | "output": "/actions/main/in/special7", 43 | "path": "/user/hand/left/pose/pistolgrip", 44 | "requirement": "optional" 45 | }, 46 | { 47 | "output": "/actions/main/in/special8", 48 | "path": "/user/hand/right/pose/pistolgrip", 49 | "requirement": "optional" 50 | } 51 | ] 52 | } 53 | }, 54 | "description": "" 55 | } -------------------------------------------------------------------------------- /Config/SteamVRBindings/steamvr_manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [ 3 | { 4 | "name": "/actions/main/in/controllerleft", 5 | "type": "pose", 6 | "requirement": "optional" 7 | }, 8 | { 9 | "name": "/actions/main/in/controllerright", 10 | "type": "pose", 11 | "requirement": "optional" 12 | }, 13 | { 14 | "name": "/actions/main/in/special1", 15 | "type": "pose", 16 | "requirement": "optional" 17 | }, 18 | { 19 | "name": "/actions/main/in/special2", 20 | "type": "pose", 21 | "requirement": "optional" 22 | }, 23 | { 24 | "name": "/actions/main/in/special3", 25 | "type": "pose", 26 | "requirement": "optional" 27 | }, 28 | { 29 | "name": "/actions/main/in/special4", 30 | "type": "pose", 31 | "requirement": "optional" 32 | }, 33 | { 34 | "name": "/actions/main/in/special5", 35 | "type": "pose", 36 | "requirement": "optional" 37 | }, 38 | { 39 | "name": "/actions/main/in/special6", 40 | "type": "pose", 41 | "requirement": "optional" 42 | }, 43 | { 44 | "name": "/actions/main/in/special7", 45 | "type": "pose", 46 | "requirement": "optional" 47 | }, 48 | { 49 | "name": "/actions/main/in/special8", 50 | "type": "pose", 51 | "requirement": "optional" 52 | }, 53 | { 54 | "name": "/actions/main/in/skeletonleft", 55 | "type": "skeleton", 56 | "skeleton": "/skeleton/hand/left", 57 | "requirement": "optional" 58 | }, 59 | { 60 | "name": "/actions/main/in/skeletonright", 61 | "type": "skeleton", 62 | "skeleton": "/skeleton/hand/right", 63 | "requirement": "optional" 64 | }, 65 | { 66 | "name": "/actions/main/out/vibrateleft", 67 | "type": "vibration", 68 | "requirement": "optional" 69 | }, 70 | { 71 | "name": "/actions/main/out/vibrateright", 72 | "type": "vibration", 73 | "requirement": "optional" 74 | }, 75 | { 76 | "name": "/actions/main/in/open_console", 77 | "type": "boolean", 78 | "requirement": "optional" 79 | } 80 | ], 81 | "action_sets": [ 82 | { 83 | "name": "/actions/main", 84 | "usage": "leftright" 85 | } 86 | ], 87 | "default_bindings": [ 88 | { 89 | "controller_type": "knuckles", 90 | "binding_url": "knuckles.json" 91 | }, 92 | { 93 | "controller_type": "vive_controller", 94 | "binding_url": "vive_controller.json" 95 | }, 96 | { 97 | "controller_type": "vive_cosmos_controller", 98 | "binding_url": "vive_cosmos_controller.json" 99 | }, 100 | { 101 | "controller_type": "oculus_touch", 102 | "binding_url": "oculus_touch.json" 103 | }, 104 | { 105 | "controller_type": "holographic_controller", 106 | "binding_url": "holographic_controller.json" 107 | }, 108 | { 109 | "controller_type": "indexhmd", 110 | "binding_url": "indexhmd.json" 111 | }, 112 | { 113 | "controller_type": "vive", 114 | "binding_url": "vive.json" 115 | }, 116 | { 117 | "controller_type": "vive_pro", 118 | "binding_url": "vive_pro.json" 119 | }, 120 | { 121 | "controller_type": "rift", 122 | "binding_url": "rift.json" 123 | }, 124 | { 125 | "controller_type": "vive_tracker_camera", 126 | "binding_url": "vive_tracker_camera.json" 127 | }, 128 | { 129 | "controller_type": "gamepad", 130 | "binding_url": "gamepad.json" 131 | } 132 | ], 133 | "localization": [ 134 | { 135 | "language_tag": "en_us", 136 | "/actions/main/in/controllerleft": "Left Controller [Pose]", 137 | "/actions/main/in/controllerright": "Right Controller [Pose]", 138 | "/actions/main/in/special1": "Special 1 [Tracker]", 139 | "/actions/main/in/special2": "Special 2 [Tracker]", 140 | "/actions/main/in/special3": "Special 3 [Tracker]", 141 | "/actions/main/in/special4": "Special 4 [Tracker]", 142 | "/actions/main/in/special5": "Special 5 [Tracker]", 143 | "/actions/main/in/special6": "Special 6 [Tracker]", 144 | "/actions/main/in/special7": "Special 7 [Tracker]", 145 | "/actions/main/in/special8": "Special 8 [Tracker]", 146 | "/actions/main/in/skeletonleft": "Skeleton (Left)", 147 | "/actions/main/in/skeletonright": "Skeleton (Right)", 148 | "/actions/main/out/vibrateleft": "Haptic (Left)", 149 | "/actions/main/out/vibrateright": "Haptic (Right)", 150 | "/actions/main/in/open_console": "Open Console", 151 | "/actions/main": "Main Game Actions" 152 | } 153 | ] 154 | } -------------------------------------------------------------------------------- /Source/UE4SpotifyApi/Private/SpotifyAPIClient.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | 5 | #include "UE4SpotifyApi/Public/SpotifyAPIClient.h" 6 | #include "SpotifyAPICredentials.h" 7 | #include "Kismet/GameplayStatics.h" 8 | #include "GameFramework/PlayerController.h" 9 | #include "Runtime/Online/HTTP/Public/Http.h" 10 | #include "Runtime/Networking/Public/Networking.h" 11 | #include "Runtime/Sockets/Public/Sockets.h" 12 | #include "TimerManager.h" 13 | 14 | ISpotifyAPIClient* ISpotifyAPIClient::Runnable = NULL; 15 | 16 | ISpotifyAPIClient::ISpotifyAPIClient() 17 | : StopTaskCounter(0) 18 | , bFinished(false) 19 | { 20 | UE_LOG(LogTemp, Warning, TEXT("Constructor")); 21 | 22 | Thread = FRunnableThread::Create(this, TEXT("SpotifyListenClient"), 0, TPri_BelowNormal); 23 | } 24 | 25 | ISpotifyAPIClient::~ISpotifyAPIClient() 26 | { 27 | delete Thread; 28 | Thread = NULL; 29 | if(ListenerSocket) 30 | { 31 | ListenerSocket->Close(); 32 | } 33 | } 34 | 35 | ISpotifyAPIClient* ISpotifyAPIClient::GetStarted() 36 | { 37 | if(!Runnable && FPlatformProcess::SupportsMultithreading()) 38 | { 39 | Runnable = new ISpotifyAPIClient(); 40 | } 41 | return Runnable; 42 | } 43 | 44 | FString ISpotifyAPIClient::GetCode() const 45 | { 46 | return Code; 47 | } 48 | 49 | bool ISpotifyAPIClient::Init() 50 | { 51 | //USpotifyAPICredentials* Credentials = Cast(UGameplayStatics::LoadGameFromSlot(TEXT("SpotifySEC"), 0)); 52 | //if (!Credentials) return false; 53 | const FString PubKey = "1032673ea07c4e3baf71241e45257144"; 54 | const FString SecKey = "1032673ea07c4e3baf71241e45257144"; 55 | //Credentials->GetCredentials(PubKey, SecKey); 56 | //Credentials->BeginDestroy(); 57 | //Credentials = nullptr; 58 | const FIPv4Endpoint Endpoint(FIPv4Address::InternalLoopback, Port); 59 | 60 | ListenerSocket = FTcpSocketBuilder(TEXT("ListenerSocket")) 61 | .AsReusable() 62 | .BoundToEndpoint(Endpoint) 63 | .Listening(8) 64 | .Build(); 65 | 66 | int NewSize = 0; 67 | ListenerSocket->SetReceiveBufferSize(2 * 1024 * 1024, NewSize); 68 | FPlatformProcess::LaunchURL(TEXT("https://accounts.spotify.com/authorize?response_type=code&redirect_uri=http://127.0.0.1:8064&client_id=1032673ea07c4e3baf71241e45257144&scope=user-modify-playback-state&state="), TEXT(""), nullptr); 69 | return true; 70 | } 71 | 72 | uint32 ISpotifyAPIClient::Run() 73 | { 74 | FPlatformProcess::Sleep(0.03); 75 | if (!ListenerSocket) return 0; 76 | auto SocketSubsystem = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM); 77 | const TSharedRef RemoteAddress = SocketSubsystem->CreateInternetAddr(); 78 | UE_LOG(LogTemp, Log, TEXT("TEST")); 79 | bool bPending; 80 | while(ListenerSocket && ListenerSocket->HasPendingConnection(bPending) && !bPending) 81 | { 82 | FPlatformProcess::Sleep(0.03); 83 | if (StopTaskCounter.GetValue() > 0) { 84 | ListenerSocket->Close(); 85 | SocketSubsystem->DestroySocket(ListenerSocket); 86 | ListenerSocket = nullptr; 87 | return 0; 88 | } 89 | } 90 | if (ListenerSocket->HasPendingConnection(bPending) && bPending) 91 | { 92 | 93 | /*if (ConnectionSocket != NULL) 94 | { 95 | ConnectionSocket->Close(); 96 | SocketSubsystem->DestroySocket(ConnectionSocket); 97 | }*/ 98 | 99 | ConnectionSocket = ListenerSocket->Accept(*RemoteAddress, TEXT("ConnectionSocket")); 100 | 101 | if(ConnectionSocket) 102 | { 103 | FPlatformProcess::Sleep(0.03); 104 | uint32 Size; 105 | TArray ReceivedData; 106 | 107 | while(ConnectionSocket->HasPendingData(Size)) 108 | { 109 | ReceivedData.SetNumUninitialized(FMath::Min(Size, 65507u)); 110 | int32 Read = 0; 111 | ConnectionSocket->Recv(ReceivedData.GetData(), ReceivedData.Num(), Read); 112 | FPlatformProcess::Sleep(0.06); 113 | } 114 | 115 | if(ReceivedData.Num() <= 0) 116 | { 117 | return 0; 118 | } 119 | 120 | const FString ReceivedString = FString(ANSI_TO_TCHAR(reinterpret_cast(ReceivedData.GetData()))); 121 | 122 | UE_LOG(LogTemp, Warning, TEXT("Received: %s"), *ReceivedString); 123 | 124 | TCHAR* SerializedChar = FString(TEXT("HTTP/1.1 200 OK\r\nCache-Control: no-cache, private\r\n\r\n\r\n\r\nSuccess!\r\n\r

Success!

\n

You can close this document now!

\r\n")).GetCharArray().GetData(); 125 | int32 size = FCString::Strlen(SerializedChar); 126 | int32 sent = 0; 127 | 128 | 129 | 130 | while(ConnectionSocket->Send((uint8*)TCHAR_TO_UTF8(SerializedChar), size, sent) && size - sent > 0); 131 | uint32 SizeSent; 132 | 133 | while (ConnectionSocket && ConnectionSocket->HasPendingData(SizeSent)); 134 | 135 | ConnectionSocket->Close(); 136 | SocketSubsystem->DestroySocket(ConnectionSocket); 137 | FPlatformProcess::Sleep(0.03); 138 | 139 | bFinished = true; 140 | 141 | ListenerSocket->Close(); 142 | SocketSubsystem->DestroySocket(ListenerSocket); 143 | 144 | const FRegexPattern CodePattern("=(\\S+)&"); 145 | FRegexMatcher CodeMatcher(CodePattern, ReceivedString); 146 | 147 | CodeMatcher.FindNext(); 148 | Code = CodeMatcher.GetCaptureGroup(1); 149 | 150 | return 1; 151 | 152 | } 153 | } 154 | 155 | if(ConnectionSocket && bFinished) 156 | { 157 | ConnectionSocket->Close(); 158 | SocketSubsystem->DestroySocket(ConnectionSocket); 159 | } 160 | if(ListenerSocket && bFinished) 161 | { 162 | ListenerSocket->Close(); 163 | SocketSubsystem->DestroySocket(ListenerSocket); 164 | } 165 | 166 | return 0; 167 | } 168 | 169 | void ISpotifyAPIClient::Stop() 170 | { 171 | StopTaskCounter.Increment(); 172 | } 173 | 174 | void ISpotifyAPIClient::EnsureCompletion() 175 | { 176 | Stop(); 177 | Thread->WaitForCompletion(); 178 | } 179 | 180 | void ISpotifyAPIClient::Shutdown() 181 | { 182 | if(Runnable) 183 | { 184 | Runnable->EnsureCompletion(); 185 | delete Runnable; 186 | Runnable = NULL; 187 | } 188 | } 189 | 190 | bool ISpotifyAPIClient::IsThreadFinished() 191 | { 192 | if (Runnable) return Runnable->IsFinished(); 193 | return true; 194 | } 195 | --------------------------------------------------------------------------------