diff --git a/RPH1/FodyWeavers.xml b/RPH1/FodyWeavers.xml
new file mode 100644
index 0000000..c6e1b7c
--- /dev/null
+++ b/RPH1/FodyWeavers.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/RPH1/Properties/AssemblyInfo.cs b/RPH1/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..6debf55
--- /dev/null
+++ b/RPH1/Properties/AssemblyInfo.cs
@@ -0,0 +1,38 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("SpotifyRage")]
+[assembly: AssemblyDescription("A plugin for Rage Plugin Hook that enables the use of Spotify within Grand Theft Auto V.")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("SpotifyRage")]
+[assembly: AssemblyCopyright("Copyright © Lucas Ritter, Spotify 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("ab9168d5-9bdb-43ab-9a90-9eeddf83b099")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+
+[assembly: Rage.Attributes.Plugin("SpotifyRage", Author = "Lucas Ritter, Spotify", ShouldTickInPauseMenu = false)]
diff --git a/RPH1/RPH1.csproj b/RPH1/RPH1.csproj
new file mode 100644
index 0000000..bd22987
--- /dev/null
+++ b/RPH1/RPH1.csproj
@@ -0,0 +1,85 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {AB9168D5-9BDB-43AB-9A90-9EEDDF83B099}
+ Library
+ Properties
+ SpotifyRage
+ SpotifyRage
+ v4.6.2
+ 512
+
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ x64
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ Spotify.ico
+
+
+
+ ..\packages\SpotifyWebHelperAPI.1.0.4\lib\Newtonsoft.Json.dll
+ True
+
+
+ E:\Games\Standalone\GTA\Vanilla\SDK\RagePluginHookSDK.dll
+
+
+ ..\packages\SpotifyWebHelperAPI.1.0.4\lib\SpotifyWebHelperAPI.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
+ xcopy $(TargetPath) "E:\Games\Standalone\GTA\Vanilla\Plugins" /F /Y
+
+
\ No newline at end of file
diff --git a/RPH1/Scaleform.cs b/RPH1/Scaleform.cs
new file mode 100644
index 0000000..e6bb3cd
--- /dev/null
+++ b/RPH1/Scaleform.cs
@@ -0,0 +1,92 @@
+using Rage.Native;
+
+namespace SpotifyRage
+{
+ class Scaleform
+ {
+ public int Handle { get; private set; }
+ public string ScaleformID { get; private set; }
+
+ public Scaleform(string scaleformId, bool forceLoad)
+ {
+ if (forceLoad)
+ Load(scaleformId);
+ }
+
+ public Scaleform(int handle, bool forceLoad = false)
+ {
+ this.Handle = handle;
+ }
+
+ public bool Load(string scaleformId)
+ {
+ // Request a Scaleform movie identifier from the game.
+ int handle = NativeFunction.Natives.RequestScaleformMovie(scaleformId);
+
+ // If a handle was not given, cancel the load process.
+ if (handle == 0) return false;
+
+ // Set local values.
+ this.Handle = handle;
+ this.ScaleformID = scaleformId;
+
+ // Loading was successful, return true.
+ return true;
+ }
+
+ public void Render2D()
+ {
+ // Draw a Scaleform movie in Fullscreen with 255 on all RGBA values.
+ NativeFunction.Natives.x0DF606929C105BE1(this.Handle, 255, 255, 255, 255);
+ }
+
+ public void CallFunction (string function, params object[] arguments)
+ {
+ // Start calling the function.
+ NativeFunction.Natives.xF6E48914C7A8694E(this.Handle, function);
+
+ // Loop through all arguments.
+ foreach (object argument in arguments)
+ {
+ // Do type checking
+
+ // 32bit Integer
+ if (argument.GetType() == typeof(int))
+ {
+ // Call native GRAPHICS::_PUSH_SCALEFORM_MOVIE_METHOD_PARAMETER_INT
+ NativeFunction.Natives.xC3D0841A0CC546A6((int)argument);
+ }
+
+ else if (argument.GetType() == typeof(string))
+ {
+ // Call native GRAPHICS::_PUSH_SCALEFORM_MOVIE_METHOD_PARAMETER_STRING
+ NativeFunction.Natives.xBA7148484BD90365((string)argument);
+ }
+
+ }
+
+ // Pop the function over to the game.
+ NativeFunction.Natives.xC6796A8FFA375E53();
+ }
+
+ public void CallFunctionArray (string function, params string[] arguments)
+ {
+ string[] argArray = new string[] { "", "", "", "", "" };
+
+ for (int i = 0; i < 5; i++)
+ {
+ if (arguments.Length > i && arguments[i] != null)
+ {
+ argArray[i] = arguments[i];
+ }
+ }
+
+ // Call native GRAPHICS::_CALL_SCALEFORM_MOVIE_FUNCTION_STRING_PARAMS
+ NativeFunction.Natives.x51BC1ED3CC44E8F7(this.Handle, function,
+ argArray[0], argArray[1], argArray[2], argArray[3], argArray[4]);
+
+ // Pop the function over to the game.
+ NativeFunction.Natives.EndScaleformMovieMethod();
+ }
+ }
+}
diff --git a/RPH1/Spotify.cs b/RPH1/Spotify.cs
new file mode 100644
index 0000000..f021c2c
--- /dev/null
+++ b/RPH1/Spotify.cs
@@ -0,0 +1,110 @@
+using System;
+using Rage;
+using Rage.Native;
+using SpotifyWebHelperAPI;
+
+namespace SpotifyRage
+{
+ public sealed class EntryPoint
+ {
+ public static int RadioStation { get; private set; } = 0;
+
+ private static ISpotifyWebHelperCommunicationService CommunicationService;
+ private static Scaleform DashboardScaleform;
+
+ private static bool DebugDraw = false;
+
+ public static void Main()
+ {
+ Game.Console.Print($"SpotifyRage is now starting..");
+
+ // Initialize a connection to the Spotify Web Helper application.
+ // TODO: Catch if the App is not running.
+ Game.Console.Print("Connecting to the Spotify Web Helper application.");
+ CommunicationService = SpotifyWebHelperApi.Create();
+
+ // Request Dashboard Scaleform Movie
+ DashboardScaleform = new Scaleform("dashboard", true);
+
+
+ // Update on every game tick.
+ Game.FrameRender += Update;
+
+ while (true)
+ GameFiber.Yield();
+ }
+
+ private static void Update(object sender, GraphicsEventArgs e)
+ {
+
+ if (Game.LocalPlayer.Character.IsInAnyVehicle(false))
+ {
+ if (NativeFunction.Natives.GetPlayerRadioStationIndex() == RadioStation)
+ {
+ var status = CommunicationService.GetStatus();
+
+ // Disable radio in car.
+ NativeFunction.Natives.SetFrontendRadioActive(false);
+ NativeFunction.Natives.SetVehicleRadioLoud(Game.LocalPlayer.Character.CurrentVehicle, false);
+ NativeFunction.Natives.SetVehicleRadioEnabled(Game.LocalPlayer.Character.CurrentVehicle, false);
+
+ PushSpotifyInfo(status.Track.ArtistResource.Name, status.Track.TrackResource.Name, status.Playing);
+
+ if (DebugDraw)
+ DashboardScaleform.Render2D();
+ }
+
+ // Check if vehicle radio is disabled or if it is set to be loud.
+ if (!NativeFunction.Natives.x5F43D83FD6738741() || !NativeFunction.Natives.x032A116663A4D5AC(Game.LocalPlayer.Character.CurrentVehicle))
+ {
+ NativeFunction.Natives.SetFrontendRadioActive(true);
+ NativeFunction.Natives.SetVehicleRadioLoud(Game.LocalPlayer.Character.CurrentVehicle, true);
+ NativeFunction.Natives.SetVehicleRadioEnabled(Game.LocalPlayer.Character.CurrentVehicle, true);
+ }
+ }
+ }
+#if DEBUG
+ [Rage.Attributes.ConsoleCommand()]
+ private static void Command_GetSpotifyInfo()
+ {
+ var status = CommunicationService.GetStatus();
+ Game.Console.Print($"Artist: {status.Track.ArtistResource.Name}, Track: {status.Track.TrackResource.Name}, Is Playing: {status.Playing}");
+ }
+
+ [Rage.Attributes.ConsoleCommand()]
+ private static void Command_SetTestInfo()
+ {
+ var status = CommunicationService.GetStatus();
+ Game.Console.Print($"Artist: {status.Track.ArtistResource.Name}, Track: {status.Track.TrackResource.Name}, Is Playing: {status.Playing}");
+ }
+
+ [Rage.Attributes.ConsoleCommand()]
+ private static void Command_GetDashboard()
+ {
+ Game.Console.Print(DashboardScaleform.Handle.ToString());
+ }
+
+ [Rage.Attributes.ConsoleCommand()]
+ private static void Command_DrawDebug(bool enabled)
+ {
+ DebugDraw = enabled;
+ }
+
+#endif
+
+ private static void PushSpotifyInfo(string artist, string track, bool playing)
+ {
+ try
+ {
+ DashboardScaleform.CallFunction("SET_RADIO",
+ "", playing ? "Spotify" : "Spotify - Paused",
+ artist, track);
+ }
+ catch (Exception exception)
+ {
+ Game.Console.Print("Spotify fucked up, " + exception.ToString());
+ }
+
+ }
+ }
+}
diff --git a/RPH1/Spotify.ico b/RPH1/Spotify.ico
new file mode 100644
index 0000000..df225ff
Binary files /dev/null and b/RPH1/Spotify.ico differ
diff --git a/RPH1/packages.config b/RPH1/packages.config
new file mode 100644
index 0000000..f262c24
--- /dev/null
+++ b/RPH1/packages.config
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SHVDN/FodyWeavers.xml b/SHVDN/FodyWeavers.xml
new file mode 100644
index 0000000..c6e1b7c
--- /dev/null
+++ b/SHVDN/FodyWeavers.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/SHVDN/Properties/AssemblyInfo.cs b/SHVDN/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ec42c72
--- /dev/null
+++ b/SHVDN/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("SpotifyRage")]
+[assembly: AssemblyDescription("A plugin for ScriptHookV.Net that enables the use of Spotify within Grand Theft Auto V.")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("SpotifyRage")]
+[assembly: AssemblyCopyright("Copyright © Lucas Ritter, Spotify 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("697e407f-5571-49ff-8e41-044c6550c12b")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/SHVDN/SHVDN.csproj b/SHVDN/SHVDN.csproj
new file mode 100644
index 0000000..e6be980
--- /dev/null
+++ b/SHVDN/SHVDN.csproj
@@ -0,0 +1,86 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {697E407F-5571-49FF-8E41-044C6550C12B}
+ Library
+ Properties
+ SpotifyRage
+ SpotifyRage
+ v4.6.2
+ 512
+
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ Spotify.ico
+
+
+
+ ..\packages\Costura.Fody.1.6.2\lib\dotnet\Costura.dll
+ False
+
+
+ ..\packages\SpotifyWebHelperAPI.1.0.4\lib\Newtonsoft.Json.dll
+ True
+
+
+ ..\packages\ScriptHookVDotNet2.2.10.5\lib\net452\ScriptHookVDotNet2.dll
+
+
+ ..\packages\SpotifyWebHelperAPI.1.0.4\lib\SpotifyWebHelperAPI.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ xcopy $(TargetPath) "E:\Games\Standalone\GTA\Vanilla\Scripts" /F /Y
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SHVDN/Scaleform.cs b/SHVDN/Scaleform.cs
new file mode 100644
index 0000000..b5224b6
--- /dev/null
+++ b/SHVDN/Scaleform.cs
@@ -0,0 +1,92 @@
+using GTA.Native;
+
+namespace SpotifyRage
+{
+ class Scaleform
+ {
+ public int Handle { get; private set; }
+ public string ScaleformID { get; private set; }
+
+ public Scaleform(string scaleformId, bool forceLoad)
+ {
+ if (forceLoad)
+ Load(scaleformId);
+ }
+
+ public Scaleform(int handle, bool forceLoad = false)
+ {
+ this.Handle = handle;
+ }
+
+ public bool Load(string scaleformId)
+ {
+ // Request a Scaleform movie identifier from the game.
+ int handle = Function.Call(Hash.REQUEST_SCALEFORM_MOVIE, scaleformId);
+
+ // If a handle was not given, cancel the load process.
+ if (handle == 0) return false;
+
+ // Set local values.
+ this.Handle = handle;
+ this.ScaleformID = scaleformId;
+
+ // Loading was successful, return true.
+ return true;
+ }
+
+ public void Render2D()
+ {
+ // Draw a Scaleform movie in Fullscreen with 255 on all RGBA values.
+ Function.Call(Hash.DRAW_SCALEFORM_MOVIE, this.Handle, 255, 255, 255, 255);
+ }
+
+ public void CallFunction (string function, params object[] arguments)
+ {
+ // Start calling the function.
+ Function.Call(Hash._PUSH_SCALEFORM_MOVIE_FUNCTION, this.Handle, function);
+
+ // Loop through all arguments.
+ foreach (object argument in arguments)
+ {
+ // Do type checking
+
+ // 32bit Integer
+ if (argument.GetType() == typeof(int))
+ {
+ // Call native GRAPHICS::_PUSH_SCALEFORM_MOVIE_METHOD_PARAMETER_INT
+ Function.Call(Hash._PUSH_SCALEFORM_MOVIE_FUNCTION_PARAMETER_INT, (int)argument);
+ }
+
+ else if (argument.GetType() == typeof(string))
+ {
+ // Call native GRAPHICS::_PUSH_SCALEFORM_MOVIE_METHOD_PARAMETER_STRING
+ Function.Call(Hash._PUSH_SCALEFORM_MOVIE_FUNCTION_PARAMETER_STRING, (string)argument);
+ }
+
+ }
+
+ // Pop the function over to the game.
+ Function.Call(Hash._POP_SCALEFORM_MOVIE_FUNCTION_VOID);
+ }
+
+ public void CallFunctionArray (string function, params string[] arguments)
+ {
+ string[] argArray = new string[] { "", "", "", "", "" };
+
+ for (int i = 0; i < 5; i++)
+ {
+ if (arguments.Length > i && arguments[i] != null)
+ {
+ argArray[i] = arguments[i];
+ }
+ }
+
+ // Call native GRAPHICS::_CALL_SCALEFORM_MOVIE_FUNCTION_STRING_PARAMS
+ Function.Call(Hash._CALL_SCALEFORM_MOVIE_FUNCTION_STRING_PARAMS, this.Handle, function,
+ argArray[0], argArray[1], argArray[2], argArray[3], argArray[4]);
+
+ // Pop the function over to the game.
+ Function.Call(Hash._POP_SCALEFORM_MOVIE_FUNCTION_VOID);
+ }
+ }
+}
diff --git a/SHVDN/Spotify.cs b/SHVDN/Spotify.cs
new file mode 100644
index 0000000..27dcb13
--- /dev/null
+++ b/SHVDN/Spotify.cs
@@ -0,0 +1,131 @@
+using System;
+using GTA;
+using GTA.Native;
+using SpotifyWebHelperAPI;
+using System.IO;
+
+namespace SpotifyRage
+{
+ public class Spotify : Script
+ {
+ public int RadioStation { get; private set; } = 0;
+
+ // The communication service between SpotifyWebHelper.exe and SHVDN.
+ private ISpotifyWebHelperCommunicationService CommunicationService;
+
+ // The Scaleform used by the dashboard.
+ private Scaleform DashboardScaleform;
+
+ // Enable this to show the Dashboard on screen.
+ private bool DebugDraw = false;
+
+ // This stores the current configuration.
+ private ScriptSettings Settings;
+
+ ///
+ /// The constructor for the Spotify class.
+ ///
+ public Spotify()
+ {
+ // Load the latest config.
+ LoadConfig();
+
+ // Initialize a connection to the Spotify Web Helper application.
+ // TODO: Catch if the App is not running.
+ CommunicationService = SpotifyWebHelperApi.Create();
+
+ // Request Dashboard Scaleform Movie
+ DashboardScaleform = new Scaleform("dashboard", true);
+
+
+ // Update on every game tick.
+ this.Tick += Update;
+
+
+ }
+
+ ///
+ /// Updates the information. Runs every gametick.
+ ///
+ ///
+ ///
+ private void Update(object sender, EventArgs e)
+ {
+ // Check if the player is in a vehicle.
+ if (Game.Player.Character.IsInVehicle())
+ {
+ // Check if the radio channel is set correctly.
+ if (Function.Call(Hash.GET_PLAYER_RADIO_STATION_INDEX) == RadioStation)
+ {
+ // Get the latest Spotify status.
+ var status = CommunicationService.GetStatus();
+
+ // Disable radio in car.
+ Function.Call(Hash.SET_FRONTEND_RADIO_ACTIVE, false);
+ Function.Call(Hash.SET_VEHICLE_RADIO_LOUD, false);
+ Function.Call(Hash.SET_VEHICLE_RADIO_ENABLED, false);
+
+ // Push over the spotify information.
+ PushSpotifyInfo(status.Track.ArtistResource.Name, status.Track.TrackResource.Name, status.Playing);
+
+ // Draw the dashboard on the screen.
+ if (DebugDraw)
+ DashboardScaleform.Render2D();
+ }
+
+ // Check if vehicle radio is disabled or if it is set to be loud.
+ if (!Function.Call(Hash._0x5F43D83FD6738741) || !Function.Call(Hash._0x032A116663A4D5AC, Game.Player.Character.CurrentVehicle))
+ {
+ // Enable radio in car.
+ Function.Call(Hash.SET_FRONTEND_RADIO_ACTIVE, true);
+ Function.Call(Hash.SET_VEHICLE_RADIO_LOUD, true);
+ Function.Call(Hash.SET_VEHICLE_RADIO_ENABLED, true);
+ }
+ }
+ }
+
+ ///
+ /// Loads the config from the hard drive.
+ ///
+ public void LoadConfig()
+ {
+ // Check if config file exists.
+ if (!File.Exists(@"scripts\SpotifyRage.ini"))
+ {
+ // Write to SpotifyRage.ini if it can't be found.
+ File.WriteAllLines(@"scripts\SpotifyRage.ini",
+ new string[] { "[Spotify]", "RadioStation=0", "DebugMode = false" });
+ }
+
+ // Load the config file.
+ Settings = ScriptSettings.Load(@"scripts\SpotifyRage.ini");
+
+ // Set all values.
+ DebugDraw = Settings.GetValue("Spotify", "DebugMode", false);
+ RadioStation = Settings.GetValue("Spotify", "RadioStation", 0);
+
+ }
+
+ ///
+ /// Pushes the given info over to the Dashboard scaleform for use ingame.
+ ///
+ /// The artist of the song.
+ /// The song name itself.
+ /// Whether the song is playing or not.
+ private void PushSpotifyInfo(string artist, string track, bool playing)
+ {
+ try
+ {
+ // Call function.
+ DashboardScaleform.CallFunction("SET_RADIO",
+ "", playing ? "Spotify" : "Spotify - Paused",
+ artist, track);
+ }
+ catch (Exception exception)
+ {
+ UI.Notify(exception.ToString());
+ }
+
+ }
+ }
+}
diff --git a/SHVDN/Spotify.ico b/SHVDN/Spotify.ico
new file mode 100644
index 0000000..df225ff
Binary files /dev/null and b/SHVDN/Spotify.ico differ
diff --git a/SHVDN/packages.config b/SHVDN/packages.config
new file mode 100644
index 0000000..7015b8b
--- /dev/null
+++ b/SHVDN/packages.config
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Spotify.sln b/Spotify.sln
new file mode 100644
index 0000000..cbcd484
--- /dev/null
+++ b/Spotify.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27130.2024
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RPH1", "RPH1\RPH1.csproj", "{AB9168D5-9BDB-43AB-9A90-9EEDDF83B099}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SHVDN", "SHVDN\SHVDN.csproj", "{697E407F-5571-49FF-8E41-044C6550C12B}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {AB9168D5-9BDB-43AB-9A90-9EEDDF83B099}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AB9168D5-9BDB-43AB-9A90-9EEDDF83B099}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AB9168D5-9BDB-43AB-9A90-9EEDDF83B099}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AB9168D5-9BDB-43AB-9A90-9EEDDF83B099}.Release|Any CPU.Build.0 = Release|Any CPU
+ {697E407F-5571-49FF-8E41-044C6550C12B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {697E407F-5571-49FF-8E41-044C6550C12B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {697E407F-5571-49FF-8E41-044C6550C12B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {697E407F-5571-49FF-8E41-044C6550C12B}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {93BF8C92-0A19-4A65-8C0E-7ECB58EFADED}
+ EndGlobalSection
+EndGlobal