Decompiled source of NetRadio v1.0.4

plugins/NetRadio/NetRadio.dll

Decompiled 4 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CSCore;
using CSCore.Ffmpeg;
using CSCore.MediaFoundation;
using CSCore.SoundOut;
using CSCore.Streams;
using CSCore.Streams.SampleConverter;
using CommonAPI;
using CommonAPI.Phone;
using CommonAPI.UI;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Reptile;
using Reptile.Phone;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("NetRadio")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Radio app for Bomb Rush Cyberfunk")]
[assembly: AssemblyFileVersion("1.0.4.0")]
[assembly: AssemblyInformationalVersion("1.0.4+4212cdb39cfbf377986a78d11162d96481059f2a")]
[assembly: AssemblyProduct("NetRadio")]
[assembly: AssemblyTitle("NetRadio")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.4.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace NetRadio
{
	public class NetRadio
	{
		public static Random rando = new Random();

		public static ManualLogSource Log;

		public static NetRadioManager GlobalRadio;

		public const string PluginName = "NetRadio";

		public const string PluginGUID = "goatgirl.NetRadio";

		public const string PluginVersion = "1.0.4";

		public static bool gameStarted = false;

		public static Color LabelSelectedColorDefault = Color32.op_Implicit(new Color32((byte)49, (byte)90, (byte)165, byte.MaxValue));

		public static Color LabelUnselectedColorDefault = Color.white;

		public static int waveOutLatency = 50;

		public static List<string> hasRedir = new List<string>();

		public static NetRadioPlugin PluginInstance => NetRadioPlugin.Instance;

		public static MusicPlayer musicPlayer
		{
			get
			{
				IMusicPlayer obj = Core.Instance.AudioManager.MusicPlayer;
				return (MusicPlayer)(object)((obj is MusicPlayer) ? obj : null);
			}
		}

		public static Player player
		{
			get
			{
				WorldHandler instance = WorldHandler.instance;
				return (instance != null) ? instance.GetCurrentPlayer() : null;
			}
		}

		public static AudioSubSystem audioSubSystem
		{
			get
			{
				IAudioSubSystem obj = Core.Instance.AudioManager.audioSubSystem;
				return (AudioSubSystem)(object)((obj is AudioSubSystem) ? obj : null);
			}
		}

		public static AudioManager audioManager => Core.Instance.AudioManager;

		public static float radioMusicVolume => audioSubSystem.GetChannelVolumeScale((AudioChannelID)4, audioManager.musicAudioMaxVolume01Clamped) * audioSubSystem.GetChannelVolumeScale((AudioChannelID)0, audioManager.masterAudioMaxVolume01Clamped) * NetRadioSettings.streamVolume.Value;

		public static float sfxVolume => audioSubSystem.GetChannelVolumeScale((AudioChannelID)0, audioManager.masterAudioMaxVolume01Clamped) * audioSubSystem.GetChannelVolumeScale((AudioChannelID)1, audioManager.masterAudioMaxVolume01Clamped);

		public static float bufferTimeInSeconds => NetRadioSettings.extraBufferSec.Value;

		public static bool PlayerUsingMusicApp()
		{
			return PlayerUsingApp(typeof(AppMusicPlayer));
		}

		public static bool PlayerUsingApp(Type checkAppType)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)player.phone == (Object)null)
			{
				return false;
			}
			return ((object)player.phone.m_CurrentApp).GetType() == checkAppType && player.phone.IsOn && player.phoneLayerWeight >= 1f;
		}

		public static bool pressedAnyButtonIn(List<KeyCode> keybinds)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			foreach (KeyCode keybind in keybinds)
			{
				if (Input.GetKeyUp(keybind))
				{
					return true;
				}
			}
			return false;
		}

		public static Sprite LoadSprite(string path)
		{
			Sprite val = TextureUtility.LoadSprite(path);
			((Texture)val.texture).filterMode = (FilterMode)1;
			((Texture)val.texture).wrapMode = (TextureWrapMode)1;
			return val;
		}

		public static IEnumerator MuteUntilRadioPlaying()
		{
			while (!GlobalRadio.playing)
			{
				musicPlayer.ForcePaused();
				yield return null;
			}
		}

		public static bool IsStationButton(SimplePhoneButton button)
		{
			if ((Object)(object)button == (Object)null || (Object)(object)button.Label == (Object)null)
			{
				return false;
			}
			int childCount = ((Component)button.Label).gameObject.transform.childCount;
			bool flag = ((TMP_Text)button.Label).text.Contains("Custom Station") || ((TMP_Text)button.Label).text == "NetRadio" || NetRadioSettings.streamTitles.Contains(((TMP_Text)button.Label).text);
			return childCount > 2 && flag;
		}

		public static bool IsHeaderButton(SimplePhoneButton button)
		{
			if ((Object)(object)button == (Object)null || (Object)(object)button.Label == (Object)null)
			{
				return false;
			}
			int childCount = ((Component)button.Label).gameObject.transform.childCount;
			if (childCount < 1)
			{
				return false;
			}
			return ((Object)((Component)((Component)button.Label).gameObject.transform.GetChild(0)).gameObject).name.Contains("Header");
		}

		public static string StandardizeURL(string originalURL)
		{
			return originalURL.Replace("https://", "").Replace("http://", "").Trim()
				.ToLower()
				.TrimEnd(new char[1] { '/' });
		}

		public static string ReadIcyHeader(HttpResponseMessage response, string header)
		{
			string text = (header.StartsWith("icy-") ? header : ("icy-" + header));
			IEnumerable<string> source = default(IEnumerable<string>);
			if (((HttpHeaders)response.Headers).TryGetValues(text, ref source))
			{
				return source.First();
			}
			return null;
		}

		public static string GetRedirectedURL(string url)
		{
			try
			{
				HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
				httpWebRequest.Method = "POST";
				httpWebRequest.AllowAutoRedirect = true;
				httpWebRequest.Timeout = 2000;
				WebResponse response = httpWebRequest.GetResponse();
				string text = response.ResponseUri.AbsoluteUri.ToString();
				hasRedir.Add(text);
				if (!text.Equals(url))
				{
					Log.LogInfo((object)("Updating internal station URL " + url + " - redirects to " + text));
				}
				return text;
			}
			catch (Exception)
			{
				return null;
			}
		}
	}
	public class TracksHeaderApp : CustomApp
	{
		public Transform overlayInstance = null;

		public void CreateAndSaveIconlessTitleBar(string title, float fontSize = 80f)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			Transform val = Object.Instantiate<Transform>(((Component)((App)this).MyPhone.GetAppInstance<AppGraffiti>()).transform.Find("Overlay"));
			Transform val2 = ((Component)val).transform.Find("Icons");
			Object.Destroy((Object)(object)((Component)val2.Find("GraffitiIcon")).gameObject);
			Transform val3 = val2.Find("HeaderLabel");
			val3.localPosition = new Vector3(140f, val3.localPosition.y, val3.localPosition.z);
			Object.Destroy((Object)(object)((Component)val3).GetComponent<TMProLocalizationAddOn>());
			TextMeshProUGUI component = ((Component)val3).GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).text = title;
			((TMP_Text)component).fontSize = fontSize;
			((TMP_Text)component).fontSizeMax = fontSize;
			((TMP_Text)component).enableAutoSizing = true;
			val.SetParent(((Component)this).transform, false);
			overlayInstance = val;
		}

		public override void OnPressUp()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			int selectedIndex = base.ScrollView.SelectedIndex;
			int num = selectedIndex - 1;
			int num2 = 0;
			if (num < 0 || num >= base.ScrollView.Buttons.Count || !NetRadio.IsHeaderButton((SimplePhoneButton)base.ScrollView.Buttons[num]) || num != num2)
			{
				((CustomApp)this).OnPressUp();
			}
		}

		public override void OnPressDown()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			int selectedIndex = base.ScrollView.SelectedIndex;
			int num = selectedIndex + 1;
			int num2 = base.ScrollView.Buttons.Count - 1;
			if (num < 0 || num >= base.ScrollView.Buttons.Count || !NetRadio.IsHeaderButton((SimplePhoneButton)base.ScrollView.Buttons[num]) || num != num2)
			{
				((CustomApp)this).OnPressDown();
			}
		}
	}
	public class AppSelectedStation : TracksHeaderApp
	{
		public static AppSelectedStation Instance;

		public static PhoneButton lastSelectedButton;

		public static int currentStationIndex;

		public static float time = 0f;

		public static bool justCopied = false;

		public static bool justFailedCopy = false;

		public static int volumeInPercent = 100;

		public static bool changingVolume = false;

		public override bool Available => false;

		public static void Initialize()
		{
			PhoneAPI.RegisterApp<AppSelectedStation>("selected station", (Sprite)null);
		}

		public override void OnAppEnable()
		{
			Instance = this;
			lastSelectedButton = null;
			CreateAndSaveIconlessTitleBar(NetRadio.GlobalRadio.GetStationTitle(currentStationIndex));
			justCopied = false;
			changingVolume = false;
			time = 0f;
			string key = NetRadio.StandardizeURL(NetRadioSettings.configURLs[currentStationIndex]);
			float num = (NetRadioSaveData.stationVolumesByURL.ContainsKey(key) ? ((float)NetRadioSaveData.stationVolumesByURL[key]) : 1f);
			float num2 = num * 100f;
			volumeInPercent = 5 * (int)Math.Round((double)num2 / 5.0);
			SimplePhoneButton val = AppNetRadio.CreateHeaderButton(AppNetRadio.currentNowPlayingText, AppNetRadio.currentNowPlayingHeight);
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val);
			AppNetRadio.UpdateNowPlayingButton(val, ((CustomApp)this).ScrollView, skipCheck: true);
			if (NetRadio.GlobalRadio.playing && NetRadio.GlobalRadio.currentStation == currentStationIndex)
			{
				SimplePhoneButton val2 = PhoneUIUtility.CreateSimpleButton("Disconnect...");
				((PhoneButton)val2).OnConfirm = (Action)Delegate.Combine(((PhoneButton)val2).OnConfirm, (Action)delegate
				{
					NetRadio.GlobalRadio.Stop();
					if (AppNetRadio.musicPlayerWasInterrupted)
					{
						NetRadio.musicPlayer.PlayFrom(NetRadio.musicPlayer.CurrentTrackIndex, 0);
					}
					else
					{
						NetRadio.musicPlayer.PlayFrom(0, 0);
					}
					((App)this).MyPhone.OpenApp(typeof(AppNetRadio));
				});
				((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val2);
			}
			else
			{
				SimplePhoneButton val3 = PhoneUIUtility.CreateSimpleButton("Connect...");
				((PhoneButton)val3).OnConfirm = (Action)Delegate.Combine(((PhoneButton)val3).OnConfirm, (Action)delegate
				{
					((MonoBehaviour)this).StartCoroutine(Instance.ConnectToStation());
				});
				((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val3);
			}
			SimplePhoneButton val4 = PhoneUIUtility.CreateSimpleButton("Volume: ");
			SimplePhoneButton obj = val4;
			((PhoneButton)obj).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj).OnConfirm, (Action)delegate
			{
				changingVolume = !changingVolume;
			});
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val4);
			val4 = PhoneUIUtility.CreateSimpleButton("Copy URL to clipboard");
			SimplePhoneButton obj2 = val4;
			((PhoneButton)obj2).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj2).OnConfirm, (Action)delegate
			{
				time = 0f;
				try
				{
					GUIUtility.systemCopyBuffer = NetRadioSettings.configURLs[currentStationIndex];
					justCopied = true;
				}
				catch (Exception ex)
				{
					NetRadio.Log.LogError((object)("Error copying to clipboard: " + ex.Message));
					NetRadio.Log.LogError((object)ex.StackTrace);
					justFailedCopy = true;
				}
			});
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val4);
			((App)this).OnAppEnable();
		}

		public IEnumerator ConnectToStation()
		{
			int station = currentStationIndex;
			AppNetRadio.loaded = false;
			((App)this).MyPhone.OpenApp(typeof(AppNetRadio));
			while (!AppNetRadio.loaded)
			{
				yield return null;
			}
			AppNetRadio.Instance.AttemptConnection(station);
		}

		public override void OnAppUpdate()
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Expected O, but got Unknown
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			time += Time.deltaTime;
			if (justCopied && (double)time > 1.0)
			{
				justCopied = false;
			}
			if (((CustomApp)this).ScrollView.Buttons.Any() && ((CustomApp)this).ScrollView.SelectedIndex >= 0)
			{
				if (NetRadio.IsHeaderButton((SimplePhoneButton)((CustomApp)this).ScrollView.Buttons[((CustomApp)this).ScrollView.SelectedIndex]))
				{
					((App)this).m_AudioManager.audioSources[3].Stop();
					int num = ((CustomApp)this).ScrollView.Buttons.IndexOf(lastSelectedButton);
					if (num > ((CustomApp)this).ScrollView.SelectedIndex)
					{
						((CustomApp)this).ScrollView.OnPressUp();
					}
					else
					{
						((CustomApp)this).ScrollView.OnPressDown();
					}
				}
				lastSelectedButton = ((CustomApp)this).ScrollView.Buttons[((CustomApp)this).ScrollView.SelectedIndex];
			}
			foreach (SimplePhoneButton button in ((CustomApp)this).ScrollView.Buttons)
			{
				SimplePhoneButton val = button;
				if (NetRadio.IsHeaderButton(val))
				{
					AppNetRadio.UpdateNowPlayingButton(val, ((CustomApp)this).ScrollView);
					((PhoneButton)val).PlayDeselectAnimation(true);
				}
				else if (((TMP_Text)val.Label).text.Contains("Volume:"))
				{
					((TMP_Text)val.Label).text = "Volume: " + volumeInPercent + "%";
					SetLabelColor(val, changingVolume ? Color.green : Color.clear);
				}
				else if (((TMP_Text)val.Label).text.Contains("clipboard"))
				{
					((TMP_Text)val.Label).text = (justFailedCopy ? "Copy to clipboard failed!" : (justCopied ? "Copied to clipboard!" : "Copy URL to clipboard"));
					SetLabelColor(val, justFailedCopy ? Color.red : (justCopied ? Color.green : Color.clear));
				}
			}
			if (changingVolume)
			{
				string key = NetRadio.StandardizeURL(NetRadioSettings.configURLs[currentStationIndex]);
				decimal value = (decimal)volumeInPercent / 100m;
				if (NetRadioSaveData.stationVolumesByURL.ContainsKey(key))
				{
					NetRadioSaveData.stationVolumesByURL[key] = value;
				}
				else
				{
					NetRadioSaveData.stationVolumesByURL.Add(key, value);
				}
			}
		}

		public override void OnAppInit()
		{
			((CustomApp)this).OnAppInit();
			((CustomApp)this).ScrollView = PhoneScrollView.Create((CustomApp)(object)this, 275f, 1600f);
		}

		public override void OnAppDisable()
		{
			((CustomApp)this).ScrollView.RemoveAllButtons();
			((App)this).OnAppDisable();
			Object.Destroy((Object)(object)((Component)overlayInstance).gameObject);
			justCopied = false;
			changingVolume = false;
			time = 0f;
			((CustomSaveData)NetRadioSaveData.Instance).Save();
		}

		public void SetLabelColor(SimplePhoneButton nextButton, Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			if (color == Color.clear)
			{
				((TMP_Text)nextButton.Label).faceColor = Color32.op_Implicit((((CustomApp)this).ScrollView.SelectedIndex == ((CustomApp)this).ScrollView.Buttons.IndexOf((PhoneButton)(object)nextButton)) ? NetRadio.LabelSelectedColorDefault : NetRadio.LabelUnselectedColorDefault);
				nextButton.LabelSelectedColor = NetRadio.LabelSelectedColorDefault;
				nextButton.LabelUnselectedColor = NetRadio.LabelUnselectedColorDefault;
			}
			else
			{
				((TMP_Text)nextButton.Label).faceColor = Color32.op_Implicit(color);
				nextButton.LabelSelectedColor = color;
				nextButton.LabelUnselectedColor = color;
			}
		}

		public override void OnPressUp()
		{
			if (changingVolume)
			{
				volumeInPercent = Mathf.Clamp(volumeInPercent + 5, 0, 200);
			}
			else
			{
				base.OnPressUp();
			}
		}

		public override void OnPressDown()
		{
			if (changingVolume)
			{
				volumeInPercent = Mathf.Clamp(volumeInPercent - 5, 0, 200);
			}
			else
			{
				base.OnPressDown();
			}
		}

		public override void OnHoldUp()
		{
			if (!changingVolume)
			{
				((CustomApp)this).OnHoldUp();
			}
		}

		public override void OnHoldDown()
		{
			if (!changingVolume)
			{
				((CustomApp)this).OnHoldDown();
			}
		}
	}
	public class AppNetRadio : TracksHeaderApp
	{
		private static Sprite IconSprite = null;

		public const string appName = "NetRadio";

		public static AppNetRadio Instance;

		private static bool justCleared = false;

		public static bool playing = false;

		public static bool runPrefix = true;

		private static FfmpegDecoder ffmpegReader;

		public static WaveOut waveOut;

		private static VolumeSource volumeSource;

		private static SampleToIeeeFloat32 converter;

		public static Sprite SelectedButtonSprite;

		public static Sprite UnselectedButtonSprite;

		public static List<Sprite> SelectedAntennaSprites = new List<Sprite>();

		public static List<Sprite> UnselectedAntennaSprites = new List<Sprite>();

		public static Dictionary<string, List<Sprite>> StationIcons = new Dictionary<string, List<Sprite>>();

		public static List<Sprite> ConnectingSprites = new List<Sprite>();

		public static Image connectIcon;

		public static Sprite BlankButtonSprite;

		public static float time = -1f;

		public static float realTime = 0f;

		public static List<int> urlWrapOffsets = new List<int>();

		public static List<string> originalURLLabelText = new List<string>();

		public static List<bool> urlIsTooLong = new List<bool>();

		public static string dataDirectory = Path.Combine(NetRadioPlugin.Instance.Directory, "RadioApp-res/");

		public const float urlOffsetX = 680f;

		public const float urlOffsetY = -80f;

		public const float titleOffsetX = 230f;

		public const float titleOffsetY = 50f;

		public const float arrowOffsetX = 40f;

		public const float arrowOffsetY = 80f;

		public const float discOffsetX = -260f;

		public const float discOffsetY = 0f;

		public const float stationOffsetX = 525f;

		public const float stationOffsetY = 27.5f;

		public const float stationLogoSize = 220f;

		public const float stationLogoOpacity = 0.5f;

		public const float iconSize = 400f;

		public const float iconOffsetX = 250f;

		public const float iconOffsetY = 170f;

		public static List<SimplePhoneButton> filteredButtons = new List<SimplePhoneButton>();

		public static bool musicPlayerWasInterrupted = false;

		public static bool globalRadioWasInterrupted = false;

		public static int musicPlayerInterruptSamples = 0;

		public static PhoneButton lastSelectedButton;

		public static bool loaded = false;

		public static string currentNowPlayingText = "Now playing";

		public static float currentNowPlayingHeight = 100f;

		public static void Initialize()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			IconSprite = NetRadio.LoadSprite(Path.Combine(dataDirectory, "icon.png"));
			PhoneAPI.RegisterApp<AppNetRadio>("NetRadio", IconSprite);
			ffmpegReader = new FfmpegDecoder(Path.Combine(dataDirectory, "Tuning.mp3"));
			volumeSource = new VolumeSource(WaveToSampleBase.CreateConverter((IWaveSource)(object)ffmpegReader));
			waveOut = new WaveOut(NetRadio.waveOutLatency);
			converter = new SampleToIeeeFloat32((ISampleSource)(object)volumeSource);
			SelectedButtonSprite = NetRadio.LoadSprite(Path.Combine(dataDirectory, "SimpleButton-Selected.png"));
			UnselectedButtonSprite = NetRadio.LoadSprite(Path.Combine(dataDirectory, "SimpleButton.png"));
			BlankButtonSprite = NetRadio.LoadSprite(Path.Combine(dataDirectory, "BlankButton.png"));
			string text = dataDirectory + "Antenna-";
			string[] array = new string[2] { "Selected", "Unselected" };
			foreach (string text2 in array)
			{
				for (int j = 0; j <= 3; j++)
				{
					string path = text + text2 + j + ".png";
					Sprite item = NetRadio.LoadSprite(path);
					if (text2 == "Selected")
					{
						SelectedAntennaSprites.Add(item);
					}
					else
					{
						UnselectedAntennaSprites.Add(item);
					}
				}
				if (text2 == "Selected")
				{
					SelectedAntennaSprites.Add(NetRadio.LoadSprite(text + text2 + "2.png"));
				}
				else
				{
					UnselectedAntennaSprites.Add(NetRadio.LoadSprite(text + text2 + "2.png"));
				}
			}
			for (int k = 0; k <= 3; k++)
			{
				string path2 = dataDirectory + "Connecting" + (k + 1) + ".png";
				ConnectingSprites.Add(NetRadio.LoadSprite(path2));
			}
			string text3 = dataDirectory + "StationLogos/";
			List<string> list = Directory.GetFiles(text3).ToList();
			foreach (string item4 in list)
			{
				if (!item4.Contains("-Selected"))
				{
					string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(item4);
					Sprite item2 = NetRadio.LoadSprite(text3 + fileNameWithoutExtension + ".png");
					Sprite item3 = NetRadio.LoadSprite(text3 + fileNameWithoutExtension + "-Selected.png");
					List<Sprite> value = new List<Sprite> { item2, item3 };
					StationIcons.Add(fileNameWithoutExtension, value);
				}
			}
		}

		public static Sprite GetStationLogo(string requestedStation, bool selected)
		{
			int index = (selected ? 1 : 0);
			string key = (StationIcons.ContainsKey(requestedStation) ? requestedStation : "Custom");
			return StationIcons[key][index];
		}

		public override void OnReleaseLeft()
		{
			((App)this).MyPhone.ReturnToHome();
		}

		public override void OnAppEnable()
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			if ((Object)(object)overlayInstance != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)overlayInstance).gameObject);
				overlayInstance = null;
			}
			if (!NetRadio.GlobalRadio.threadRunning)
			{
				AddURLButtons();
			}
			else
			{
				((MonoBehaviour)this).StartCoroutine(Instance.ClearButtons());
			}
			if ((Object)(object)connectIcon != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)connectIcon).gameObject);
			}
			GameObject val = new GameObject("Connecting Icon");
			connectIcon = val.AddComponent<Image>();
			connectIcon.sprite = ConnectingSprites[0];
			((Component)connectIcon).transform.SetParent(((Component)((CustomApp)this).ScrollView).gameObject.transform.parent, false);
			ComponentExtensions.RectTransform((Component)(object)connectIcon).sizeDelta = new Vector2(400f, 400f);
			RectTransform obj = ComponentExtensions.RectTransform((Component)(object)connectIcon);
			((Transform)obj).localPosition = ((Transform)obj).localPosition + new Vector3(250f, 170f, 0f);
			RectTransform obj2 = ComponentExtensions.RectTransform((Component)(object)connectIcon);
			((Transform)obj2).localPosition = ((Transform)obj2).localPosition - new Vector3(200f, 200f, 0f);
			((Behaviour)connectIcon).enabled = false;
			((App)this).OnAppEnable();
			loaded = true;
		}

		private void AddURLButtons()
		{
			lastSelectedButton = null;
			realTime = 0f;
			filteredButtons.Clear();
			SimplePhoneButton val = CreateHeaderButton(currentNowPlayingText, currentNowPlayingHeight);
			((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)val);
			UpdateNowPlayingButton(val, ((CustomApp)this).ScrollView, skipCheck: true);
			int num = -1;
			int num2 = 0;
			foreach (string configURL in NetRadioSettings.configURLs)
			{
				num++;
				string text = NetRadio.GlobalRadio.GetStationTitle(num);
				if (text == "NetRadio")
				{
					num2++;
					text = "Custom Station " + num2;
				}
				SimplePhoneButton nextButton = CreateStationButton(text, configURL);
				SimplePhoneButton obj = nextButton;
				((PhoneButton)obj).OnConfirm = (Action)Delegate.Combine(((PhoneButton)obj).OnConfirm, (Action)delegate
				{
					if (!NetRadio.GlobalRadio.threadRunning)
					{
						if ((NetRadio.GlobalRadio.playing && filteredButtons.IndexOf(nextButton) == NetRadio.GlobalRadio.currentStation) || !NetRadioSettings.configureRequireConnection.Value)
						{
							AppSelectedStation.currentStationIndex = filteredButtons.IndexOf(nextButton);
							((App)this).MyPhone.OpenApp(typeof(AppSelectedStation));
						}
						else
						{
							AttemptConnection(filteredButtons.IndexOf(nextButton));
						}
					}
				});
				((CustomApp)this).ScrollView.AddButton((PhoneButton)(object)nextButton);
				filteredButtons.Add(nextButton);
				if (num >= urlIsTooLong.Count)
				{
					urlIsTooLong.Add(item: false);
				}
				else
				{
					urlIsTooLong[num] = false;
				}
			}
			if ((Object)(object)connectIcon != (Object)null)
			{
				connectIcon.sprite = ConnectingSprites[0];
				((Behaviour)connectIcon).enabled = false;
			}
		}

		public void AttemptConnection(int index)
		{
			musicPlayerWasInterrupted = NetRadio.musicPlayer.IsPlaying;
			if (musicPlayerWasInterrupted)
			{
				musicPlayerInterruptSamples = NetRadio.musicPlayer.CurrentTrackSamples;
			}
			globalRadioWasInterrupted = NetRadio.GlobalRadio.playing && !NetRadio.GlobalRadio.failedToLoad;
			NetRadio.musicPlayer.ForcePaused();
			NetRadio.GlobalRadio.Play(index);
			PlayNoise();
			((MonoBehaviour)this).StartCoroutine(Instance.ClearButtons());
		}

		public static void PlayNoise()
		{
			if (volumeSource != null)
			{
				volumeSource.Volume = NetRadio.radioMusicVolume;
			}
			ffmpegReader.Position = 0L;
			waveOut.Initialize((IWaveSource)(object)converter);
			waveOut.Play();
			playing = true;
		}

		private IEnumerator ClearButtons()
		{
			lastSelectedButton = null;
			realTime = 0f;
			justCleared = true;
			((CustomApp)this).ScrollView.RemoveAllButtons();
			CreateAndSaveIconlessTitleBar("Connecting...");
			yield return (object)new WaitForSeconds(0.5f);
			justCleared = false;
		}

		public void ReloadButtons()
		{
			if (((CustomApp)this).ScrollView.Buttons.Any())
			{
				((CustomApp)this).ScrollView.RemoveAllButtons();
				AddURLButtons();
			}
		}

		private IEnumerator RestoreButtons()
		{
			yield return (object)new WaitForSeconds(0.5f);
			AddURLButtons();
			if ((Object)(object)overlayInstance != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)overlayInstance).gameObject);
				overlayInstance = null;
			}
			justCleared = false;
			waveOut.Stop();
			playing = false;
		}

		public IEnumerator StopIn(float sec)
		{
			playing = false;
			yield return (object)new WaitForSeconds(sec);
			waveOut.Stop();
		}

		public IEnumerator HandleFailedConnection()
		{
			playing = false;
			waveOut.Stop();
			if ((Object)(object)overlayInstance != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)overlayInstance).gameObject);
				overlayInstance = null;
			}
			CreateAndSaveIconlessTitleBar("Connection failed!");
			if ((Object)(object)connectIcon != (Object)null)
			{
				connectIcon.sprite = ConnectingSprites[3];
			}
			if (musicPlayerWasInterrupted)
			{
				musicPlayerWasInterrupted = false;
				NetRadio.musicPlayer.PlayFrom(NetRadio.musicPlayer.CurrentTrackIndex, musicPlayerInterruptSamples);
			}
			else if (globalRadioWasInterrupted)
			{
				NetRadio.GlobalRadio.Play(NetRadio.GlobalRadio.previousStation);
				globalRadioWasInterrupted = false;
				yield break;
			}
			yield return (object)new WaitForSeconds(1f);
			NetRadio.GlobalRadio.failedToLoad = false;
		}

		public override void OnAppUpdate()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			if (!((CustomApp)this).ScrollView.Buttons.Any() || ((CustomApp)this).ScrollView.SelectedIndex < 0)
			{
				return;
			}
			if (NetRadio.IsHeaderButton((SimplePhoneButton)((CustomApp)this).ScrollView.Buttons[((CustomApp)this).ScrollView.SelectedIndex]))
			{
				((App)this).m_AudioManager.audioSources[3].Stop();
				int num = ((CustomApp)this).ScrollView.Buttons.IndexOf(lastSelectedButton);
				if (num > ((CustomApp)this).ScrollView.SelectedIndex)
				{
					((CustomApp)this).ScrollView.OnPressUp();
				}
				else
				{
					((CustomApp)this).ScrollView.OnPressDown();
				}
			}
			lastSelectedButton = ((CustomApp)this).ScrollView.Buttons[((CustomApp)this).ScrollView.SelectedIndex];
		}

		public override void OnAppLateUpdate()
		{
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Expected O, but got Unknown
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Invalid comparison between Unknown and I4
			if ((Object)(object)connectIcon != (Object)null)
			{
				((Behaviour)connectIcon).enabled = !((CustomApp)this).ScrollView.Buttons.Any();
			}
			if (!((CustomApp)this).ScrollView.Buttons.Any())
			{
				if (!NetRadio.GlobalRadio.threadRunning && !justCleared && !NetRadio.GlobalRadio.failedToLoad)
				{
					((MonoBehaviour)this).StartCoroutine(Instance.RestoreButtons());
					justCleared = true;
				}
				if ((Object)(object)connectIcon != (Object)null)
				{
					float num = realTime * 5f % 3f;
					if ((Object)(object)connectIcon.sprite != (Object)(object)ConnectingSprites[3])
					{
						connectIcon.sprite = ConnectingSprites[(int)num];
					}
				}
			}
			if (volumeSource != null)
			{
				volumeSource.Volume = NetRadio.radioMusicVolume;
			}
			realTime += Time.deltaTime;
			foreach (SimplePhoneButton button in ((CustomApp)this).ScrollView.Buttons)
			{
				SimplePhoneButton val = button;
				if (!NetRadio.IsStationButton(val))
				{
					filteredButtons.Remove(val);
					if (NetRadio.IsHeaderButton(val))
					{
						if (((CustomApp)this).ScrollView.Buttons.IndexOf((PhoneButton)(object)val) == 0)
						{
							UpdateNowPlayingButton(val, ((CustomApp)this).ScrollView);
						}
						((PhoneButton)val).PlayDeselectAnimation(true);
						continue;
					}
					if (((CustomApp)this).ScrollView.Buttons.IndexOf((PhoneButton)(object)val) == ((CustomApp)this).ScrollView.SelectedIndex)
					{
						time += Time.deltaTime;
					}
					if ((int)((Texture)val.ButtonImage.sprite.texture).wrapMode != 1)
					{
						((Texture)val.ButtonImage.sprite.texture).wrapMode = (TextureWrapMode)1;
					}
					continue;
				}
				int num2 = filteredButtons.IndexOf(val);
				if ((Object)(object)val == (Object)null || num2 < 0 || num2 >= filteredButtons.Count)
				{
					continue;
				}
				bool flag = ((CustomApp)this).ScrollView.Buttons.IndexOf((PhoneButton)(object)val) == ((CustomApp)this).ScrollView.SelectedIndex;
				TextMeshProUGUI component = ((Component)((Component)val.Label).gameObject.transform.GetChild(0)).gameObject.GetComponent<TextMeshProUGUI>();
				if ((Object)(object)component == (Object)null)
				{
					continue;
				}
				if (num2 >= urlWrapOffsets.Count)
				{
					urlWrapOffsets.Add(0);
				}
				if (flag && urlIsTooLong[num2])
				{
					time += Time.deltaTime;
					if (time > 0.3f)
					{
						time = 0f;
						urlWrapOffsets[num2] += ((!(((TMP_Text)component).text.Substring(0, 1) == " ")) ? 1 : 2);
					}
				}
				else
				{
					urlWrapOffsets[num2] = 0;
				}
				if (num2 >= originalURLLabelText.Count)
				{
					originalURLLabelText.Add(((TMP_Text)component).text);
				}
				string text = originalURLLabelText[num2];
				if (((TMP_Text)component).text == text && urlWrapOffsets[num2] > 3)
				{
					urlWrapOffsets[num2] = 0;
					time = -1f;
				}
				((TMP_Text)component).text = text.Remove(0, urlWrapOffsets[num2]) + text.Substring(0, urlWrapOffsets[num2]);
				bool value = ((TMP_Text)component).fontSize <= ((TMP_Text)component).fontSizeMin;
				if (((TMP_Text)component).text == text)
				{
					urlIsTooLong[num2] = value;
				}
				Image component2 = ((Component)((Component)val.Label).gameObject.transform.GetChild(1)).gameObject.GetComponent<Image>();
				if (!((Object)(object)component2 == (Object)null) && ((Object)((Component)component2).gameObject).name.Contains("Icon"))
				{
					bool flag2 = num2 == NetRadio.GlobalRadio.currentStation && NetRadio.GlobalRadio.playing;
					List<Sprite> list = (flag ? SelectedAntennaSprites : UnselectedAntennaSprites);
					float num3 = realTime * 5f % 4f;
					int index = (flag2 ? Mathf.Clamp((int)num3 + 1, 0, list.Count - 1) : 0);
					component2.sprite = list[index];
				}
			}
			((App)this).OnAppLateUpdate();
		}

		public override void OnAppDisable()
		{
			loaded = false;
			if ((Object)(object)connectIcon != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)connectIcon).gameObject);
				connectIcon = null;
			}
			((CustomApp)this).ScrollView.RemoveAllButtons();
			((App)this).OnAppDisable();
		}

		public override void OnAppInit()
		{
			Instance = this;
			loaded = false;
			((CustomApp)this).OnAppInit();
			((CustomApp)this).CreateTitleBar("NetRadio", IconSprite, 80f);
			((CustomApp)this).ScrollView = PhoneScrollView.Create((CustomApp)(object)this, 275f, 1600f);
		}

		public static SimplePhoneButton CreateSimpleButton(string label)
		{
			return PhoneUIUtility.CreateSimpleButton(label);
		}

		public static SimplePhoneButton CreateHeaderButton(string label, float height = 100f)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			runPrefix = false;
			SimplePhoneButton val = PhoneUIUtility.CreateSimpleButton(label);
			TextMeshProUGUI label2 = val.Label;
			GameObject val2 = new GameObject("Header");
			val2.transform.SetParent(((Component)label2).gameObject.transform, false);
			GameObjectExtensions.RectTransform(((Component)val.ButtonImage).gameObject).sizeDelta = new Vector2(1060f, height);
			Transform transform = ((TMP_Text)label2).transform;
			transform.localPosition += new Vector3(-70f, 0f, 0f);
			runPrefix = true;
			return val;
		}

		public static void UpdateNowPlayingButton(SimplePhoneButton button, PhoneScrollView scrollView, bool skipCheck = false)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = GameObjectExtensions.RectTransform(((Component)button.ButtonImage).gameObject);
			string text = ((TMP_Text)button.Label).text;
			float y = val.sizeDelta.y;
			if (!NetRadio.GlobalRadio.playing && !NetRadio.musicPlayer.IsPlaying)
			{
				((TMP_Text)button.Label).text = "";
			}
			else
			{
				string text2 = NetRadio.musicPlayer.musicTrackQueue.CurrentMusicTrack.Artist + " - " + NetRadio.musicPlayer.musicTrackQueue.CurrentMusicTrack.Title;
				string text3 = (NetRadio.GlobalRadio.playing ? NetRadio.GlobalRadio.currentSong : text2);
				((TMP_Text)button.Label).text = "Now playing " + text3;
				((TMP_Text)button.Label).alignment = (TextAlignmentOptions)514;
			}
			float x = val.sizeDelta.x;
			float num = ((TMP_Text)button.Label).fontSizeMin * (float)((TMP_Text)button.Label).textInfo.lineCount;
			if (num == 0f)
			{
				num -= scrollView.Separation;
			}
			val.sizeDelta = new Vector2(x, num);
			if (num != y && !skipCheck)
			{
				scrollView.UpdateButtons();
			}
			currentNowPlayingText = ((TMP_Text)button.Label).text;
			if (num > 0f)
			{
				currentNowPlayingHeight = ((PhoneButton)button).Height;
			}
		}

		private static SimplePhoneButton CreateStationButton(string label, string url)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Expected O, but got Unknown
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Expected O, but got Unknown
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			runPrefix = false;
			SimplePhoneButton val = PhoneUIUtility.CreateSimpleButton(label);
			Transform val2 = ((Component)val).gameObject.transform.Find("Animation Parent");
			url = NetRadio.StandardizeURL(url);
			url += "        ";
			GameObject val3 = new GameObject("URLLabel");
			TextMeshProUGUI val4 = val3.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val4).text = url;
			((TMP_Text)val4).alignment = (TextAlignmentOptions)513;
			((TMP_Text)val4).font = AppUtility.GetAppFont();
			((TMP_Text)val4).fontSize = 55f;
			((TMP_Text)val4).fontSizeMax = 55f;
			((TMP_Text)val4).fontSizeMin = 50f;
			((TMP_Text)val4).enableAutoSizing = true;
			((TMP_Text)val4).enableWordWrapping = false;
			TextMeshProUGUI label2 = val.Label;
			val3.transform.SetParent(((Component)label2).gameObject.transform, false);
			val3.transform.localPosition = new Vector3(680f, -80f, 0f);
			RectTransform val5 = GameObjectExtensions.RectTransform(val3);
			RectTransformExtensions.SetAnchorAndPivot(val5, 0f, 0.5f);
			val5.sizeDelta = new Vector2(850f, 100f);
			Vector3 val6 = default(Vector3);
			((Vector3)(ref val6))..ctor(230f, 50f, 0f);
			Transform transform = ((TMP_Text)label2).transform;
			transform.localPosition += val6;
			Transform transform2 = val3.transform;
			transform2.localPosition -= val6;
			val5.sizeDelta -= new Vector2(135f, 0f);
			RectTransform obj = ComponentExtensions.RectTransform((Component)(object)label2);
			obj.sizeDelta -= new Vector2(180f, 0f);
			RectTransform obj2 = GameObjectExtensions.RectTransform(val.ConfirmArrow);
			((Transform)obj2).localPosition = ((Transform)obj2).localPosition + new Vector3(40f, -9999f, 0f);
			GameObject val7 = new GameObject("Station Icon");
			Image val8 = val7.AddComponent<Image>();
			val7.transform.SetParent(((Component)label2).gameObject.transform, false);
			RectTransform obj3 = GameObjectExtensions.RectTransform(val7);
			((Transform)obj3).localPosition = ((Transform)obj3).localPosition - val6;
			val8.sprite = UnselectedAntennaSprites[0];
			GameObjectExtensions.RectTransform(val7).sizeDelta = new Vector2(280f, 280f);
			RectTransform obj4 = GameObjectExtensions.RectTransform(val7);
			((Transform)obj4).localPosition = ((Transform)obj4).localPosition + new Vector3(-260f, 0f, 0f);
			GameObject val9 = new GameObject("Station Logo");
			Image val10 = val9.AddComponent<Image>();
			val9.transform.SetParent(((Component)label2).gameObject.transform, false);
			RectTransform obj5 = GameObjectExtensions.RectTransform(val9);
			((Transform)obj5).localPosition = ((Transform)obj5).localPosition - val6;
			val10.sprite = GetStationLogo(label, selected: false);
			GameObjectExtensions.RectTransform(val9).sizeDelta = new Vector2(220f, 220f);
			RectTransform obj6 = GameObjectExtensions.RectTransform(val9);
			((Transform)obj6).localPosition = ((Transform)obj6).localPosition + new Vector3(525f, 27.5f, 0f);
			Color color = ((Graphic)val10).color;
			color.a = 0.5f;
			((Graphic)val10).color = color;
			runPrefix = true;
			return val;
		}
	}
	public class NetRadioManager : MonoBehaviour
	{
		public List<string> streamURLs = new List<string>();

		public FfmpegDecoder ffmpegReader;

		public DirectSoundOut directSoundOut;

		public VolumeSource volumeSource;

		public IWaveSource mediaFoundationReader;

		public FfmpegDecoder ffmpegReaderMono;

		public DirectSoundOut waveOutMono;

		public SampleAggregatorBase centerSource;

		public VolumeSource monoSource;

		public VolumeSource monoVolumeSource;

		public PanSource pannedMonoSource;

		public PeakMeter meter;

		public bool spatialize = true;

		public float minDistance = 0.5f;

		public float maxDistance = 10f;

		public float volume = 1f;

		public bool stopped = false;

		public Thread playURLThread;

		public Thread playURLChildThread;

		public bool useThread = true;

		public bool failedToLoad = false;

		private static HttpClient m_httpClient;

		private string currentMetadata;

		public float connectionTime = 0f;

		public float metadataTimeOffset = 0f;

		public float streamSampleVolume { get; private set; } = 0f;


		public float radioVolume
		{
			get
			{
				return (volumeSource != null) ? volumeSource.Volume : 0f;
			}
			set
			{
				if (volumeSource != null)
				{
					volumeSource.Volume = Mathf.Clamp01(value) * volume;
				}
				if (monoVolumeSource != null)
				{
					monoVolumeSource.Volume = Mathf.Clamp01(value) * volume;
				}
			}
		}

		public bool playing
		{
			get
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Invalid comparison between Unknown and I4
				return directSoundOut != null && (int)directSoundOut.PlaybackState == 1;
			}
			set
			{
				if (value)
				{
					Resume();
				}
				else
				{
					Stop();
				}
			}
		}

		public float pan { get; private set; } = 0f;


		public int currentStation { get; private set; } = -1;


		public int previousStation { get; private set; } = -1;


		public string currentStationURL => streamURLs[currentStation];

		public bool threadRunning => playURLThread != null && playURLThread.IsAlive;

		public string currentSong { get; private set; }

		public bool trackingMetadata { get; private set; } = false;


		private void Start()
		{
			NetRadio.Log.LogInfo((object)"Loaded radio manager");
			if ((Object)(object)NetRadio.GlobalRadio == (Object)(object)this)
			{
				NetRadioSettings.LoadURLs();
				new NetRadioSaveData();
			}
		}

		private void Update()
		{
			if (spatialize)
			{
				CalculateSpatial();
			}
			if (playing && ffmpegReader != null && ffmpegReader.Position + 150 >= ffmpegReader.Length && ffmpegReader.Length != 0L && ffmpegReader.CanSeek)
			{
				StopRadio();
			}
		}

		private void OnDestroy()
		{
			StopRadio();
			if (playURLChildThread != null)
			{
				playURLChildThread.Abort();
			}
			if (playURLThread != null)
			{
				playURLThread.Abort();
			}
			trackingMetadata = false;
			DisposeOfReaders();
		}

		private void DisposeOfReaders()
		{
			stopped = true;
			mediaFoundationReader = null;
			ffmpegReader = null;
			ffmpegReaderMono = null;
			try
			{
				if (directSoundOut != null)
				{
					directSoundOut.Dispose();
				}
			}
			catch (Exception ex)
			{
				NetRadio.Log.LogError((object)ex);
			}
			directSoundOut = null;
			try
			{
				if (waveOutMono != null)
				{
					waveOutMono.Dispose();
				}
			}
			catch (Exception ex2)
			{
				NetRadio.Log.LogError((object)ex2);
			}
			waveOutMono = null;
			if (m_httpClient != null)
			{
				((HttpMessageInvoker)m_httpClient).Dispose();
			}
		}

		public void Play(int streamIndex = -999)
		{
			PlayRadioStation((streamIndex == -999) ? currentStation : streamIndex);
		}

		public void Stop()
		{
			StopRadio();
		}

		public void Resume()
		{
			if (directSoundOut != null)
			{
				directSoundOut.Play();
			}
			if (waveOutMono != null)
			{
				waveOutMono.Play();
			}
		}

		public void Pause()
		{
			stopped = true;
			if (directSoundOut != null)
			{
				directSoundOut.Pause();
			}
			if (waveOutMono != null)
			{
				waveOutMono.Pause();
			}
		}

		public static void ReloadAllStations()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Invalid comparison between Unknown and I4
			NetRadioSettings.LoadURLs();
			NetRadioSettings.RefreshMusicApp();
			NetRadioManager[] array = Resources.FindObjectsOfTypeAll<NetRadioManager>();
			foreach (NetRadioManager netRadioManager in array)
			{
				if ((Object)(object)netRadioManager != (Object)null && netRadioManager.currentStation >= 0 && (int)netRadioManager.directSoundOut.PlaybackState > 0)
				{
					netRadioManager.PlayRadioStation(netRadioManager.currentStation);
				}
			}
		}

		public void PlayRandomStation()
		{
			int streamIndex = NetRadio.rando.Next(0, streamURLs.Count);
			PlayRadioStation(streamIndex);
		}

		public void PlayRadioStation(int streamIndex)
		{
			failedToLoad = false;
			if (streamIndex < 0 || streamIndex >= streamURLs.Count)
			{
				NetRadio.Log.LogError((object)"PlayRadioStation: Invalid stream index!");
				failedToLoad = true;
				return;
			}
			if (playURLThread != null && playURLThread.IsAlive)
			{
				playURLThread.Join();
				playURLChildThread.Join();
			}
			StopRadio();
			previousStation = currentStation;
			currentStation = streamIndex;
			if (useThread && !NetRadioSettings.noThreads.Value)
			{
				playURLThread = new Thread(StartPlayURL);
				playURLThread.Start();
			}
			else
			{
				PlayURL();
			}
		}

		private void StartPlayURL()
		{
			ThreadStart start = (NetRadioSettings.moreCodecs.Value ? new ThreadStart(PlayURLMF) : new ThreadStart(PlayURL));
			playURLChildThread = new Thread(start);
			playURLChildThread.Start();
			if (!playURLChildThread.Join(new TimeSpan(0, 0, 11)))
			{
				failedToLoad = true;
				playURLChildThread.Abort();
			}
		}

		private void CheckForRedirection()
		{
			try
			{
				if (!NetRadio.hasRedir.Contains(currentStationURL))
				{
					string redirectedURL = NetRadio.GetRedirectedURL(currentStationURL);
					if (redirectedURL != null)
					{
						streamURLs[currentStation] = redirectedURL;
					}
				}
			}
			catch (Exception)
			{
			}
		}

		private void PlayURLMF()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Expected O, but got Unknown
			CheckForRedirection();
			if (spatialize)
			{
				PlayURL();
				return;
			}
			try
			{
				DisposeOfReaders();
				m_httpClient = CreateHTTPClient();
				float realtimeSinceStartup = Time.realtimeSinceStartup;
				MediaFoundationDecoder val = new MediaFoundationDecoder(currentStationURL);
				connectionTime = Time.realtimeSinceStartup - realtimeSinceStartup;
				mediaFoundationReader = (IWaveSource)(object)val;
				int num = val.WaveFormat.SampleRate * val.WaveFormat.BlockAlign;
				num = (int)Mathf.Round((float)num * NetRadio.bufferTimeInSeconds);
				BufferSource val2 = new BufferSource((IWaveSource)(object)ffmpegReader, num);
				meter = new PeakMeter(WaveToSampleBase.CreateConverter((IWaveSource)(object)val2));
				meter.Interval = 50;
				if ((Object)(object)NetRadio.GlobalRadio == (Object)(object)this)
				{
					meter.PeakCalculated += delegate
					{
						streamSampleVolume = meter.PeakValue;
					};
				}
				centerSource = (SampleAggregatorBase)new VolumeSource((ISampleSource)(object)meter);
				volumeSource = new VolumeSource((ISampleSource)(object)centerSource);
				directSoundOut = InitializeSoundOut((ISampleSource)(object)volumeSource);
				NetRadioPlugin.UpdateGlobalRadioVolume();
				directSoundOut.Play();
				if (waveOutMono != null)
				{
					waveOutMono.Play();
				}
			}
			catch (Exception ex)
			{
				if (currentStationURL.StartsWith("http://"))
				{
					streamURLs[currentStation] = currentStationURL.Replace("http://", "https://");
					PlayURLMF();
					return;
				}
				NetRadio.Log.LogError((object)("(Media Foundation) Error playing radio: " + ex.Message));
				NetRadio.Log.LogError((object)ex.StackTrace);
				streamURLs[currentStation] = currentStationURL.Replace("https://", "http://");
				PlayURL();
				return;
			}
			if ((Object)(object)NetRadio.GlobalRadio == (Object)(object)this && !spatialize && !failedToLoad)
			{
				TrackMetadata();
			}
			stopped = false;
		}

		private void PlayURL()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Expected O, but got Unknown
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Expected O, but got Unknown
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Expected O, but got Unknown
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Expected O, but got Unknown
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Expected O, but got Unknown
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Expected O, but got Unknown
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Expected O, but got Unknown
			CheckForRedirection();
			try
			{
				DisposeOfReaders();
				m_httpClient = CreateHTTPClient();
				float realtimeSinceStartup = Time.realtimeSinceStartup;
				FfmpegDecoder val = new FfmpegDecoder(currentStationURL);
				connectionTime = Time.realtimeSinceStartup - realtimeSinceStartup;
				ffmpegReader = val;
				int num = ffmpegReader.WaveFormat.SampleRate * ffmpegReader.WaveFormat.BlockAlign;
				num = (int)Mathf.Round((float)num * NetRadio.bufferTimeInSeconds);
				BufferSource val2 = new BufferSource((IWaveSource)(object)ffmpegReader, num);
				meter = new PeakMeter(WaveToSampleBase.CreateConverter((IWaveSource)(object)val2));
				meter.Interval = 50;
				if ((Object)(object)NetRadio.GlobalRadio == (Object)(object)this)
				{
					meter.PeakCalculated += delegate
					{
						streamSampleVolume = meter.PeakValue;
					};
				}
				centerSource = (SampleAggregatorBase)new VolumeSource((ISampleSource)(object)meter);
				volumeSource = new VolumeSource((ISampleSource)(object)centerSource);
				if (spatialize)
				{
					ffmpegReaderMono = new FfmpegDecoder(currentStationURL);
					StereoToMonoSource val3 = new StereoToMonoSource(WaveToSampleBase.CreateConverter((IWaveSource)(object)ffmpegReaderMono));
					monoSource = new VolumeSource((ISampleSource)(object)val3);
					monoVolumeSource = new VolumeSource((ISampleSource)(object)monoSource);
					pannedMonoSource = new PanSource((ISampleSource)(object)monoVolumeSource);
					radioVolume = 0f;
					waveOutMono = new DirectSoundOut(NetRadio.waveOutLatency);
					waveOutMono.Initialize((IWaveSource)new SampleToIeeeFloat32((ISampleSource)(object)pannedMonoSource));
				}
				directSoundOut = InitializeSoundOut((ISampleSource)(object)volumeSource);
				NetRadioPlugin.UpdateGlobalRadioVolume();
				directSoundOut.Play();
				if (waveOutMono != null)
				{
					waveOutMono.Play();
				}
				connectionTime = Time.realtimeSinceStartup - realtimeSinceStartup;
			}
			catch (Exception ex)
			{
				if (currentStationURL.StartsWith("http://"))
				{
					streamURLs[currentStation] = currentStationURL.Replace("http://", "https://");
					PlayURL();
					return;
				}
				failedToLoad = true;
				NetRadio.Log.LogError((object)("Error playing radio: " + ex.Message));
				NetRadio.Log.LogError((object)ex.StackTrace);
			}
			if ((Object)(object)NetRadio.GlobalRadio == (Object)(object)this && !spatialize && !failedToLoad)
			{
				TrackMetadata();
			}
			stopped = false;
		}

		private async Task OutputStopped(PlaybackStoppedEventArgs args)
		{
			NetRadio.Log.LogWarning((object)"Stopped DirectSound output");
			if (((StoppedEventArgs)args).HasError)
			{
				Exception exception = ((StoppedEventArgs)args).Exception;
				NetRadio.Log.LogWarning((object)exception.Message);
			}
			if (!stopped)
			{
				NetRadio.Log.LogWarning((object)"Output device changed");
				await Task.Delay(500);
				NetRadio.Log.LogWarning((object)"Reconnecting?");
				PlayRadioStation(currentStation);
				AppNetRadio.PlayNoise();
			}
		}

		private DirectSoundOut InitializeSoundOut(ISampleSource source, DirectSoundOut original = null)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			return InitializeSoundOut((IWaveSource)new SampleToIeeeFloat32(source), original);
		}

		private DirectSoundOut InitializeSoundOut(IWaveSource source, DirectSoundOut original = null)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			DirectSoundOut val = (DirectSoundOut)((original != null) ? ((object)original) : ((object)new DirectSoundOut(NetRadio.waveOutLatency)));
			val.Stopped += delegate(object a, PlaybackStoppedEventArgs b)
			{
				OutputStopped(b);
			};
			val.Initialize(source);
			return val;
		}

		public void StopRadio()
		{
			stopped = true;
			trackingMetadata = false;
			currentMetadata = "";
			currentSong = "Unknown Track";
			if (directSoundOut != null)
			{
				directSoundOut.Stop();
			}
			if (waveOutMono != null)
			{
				waveOutMono.Stop();
			}
		}

		public string GetStationTitle(int streamIndex = -999)
		{
			if ((Object)(object)NetRadio.GlobalRadio != (Object)(object)this || spatialize)
			{
				return "LocalRadio";
			}
			int num = ((streamIndex == -999) ? currentStation : streamIndex);
			if (num < 0 || num >= streamURLs.Count || num >= NetRadioSettings.streamTitles.Count)
			{
				return "NetRadio";
			}
			return NetRadioSettings.streamTitles[num];
		}

		public async Task GetMetadata(string url = "")
		{
			if (m_httpClient == null)
			{
				m_httpClient = CreateHTTPClient();
			}
			if (url == "")
			{
				url = currentStationURL;
			}
			string oldMetadata = currentMetadata;
			currentMetadata = await GetMetaDataFromIceCastStream(url);
			if (currentMetadata != oldMetadata)
			{
				HandleMetadata(currentMetadata);
			}
		}

		private async Task TrackMetadata()
		{
			trackingMetadata = true;
			_ = currentMetadata;
			_ = currentStation;
			string oldMetadata = "";
			currentMetadata = "";
			bool looped = false;
			while (trackingMetadata && playing)
			{
				if (!string.IsNullOrWhiteSpace(currentStationURL))
				{
					float realtimeAtStart = Time.realtimeSinceStartup;
					currentMetadata = await GetMetaDataFromIceCastStream(currentStationURL);
					float processingTime = Time.realtimeSinceStartup - realtimeAtStart;
					if (currentMetadata != oldMetadata)
					{
						metadataTimeOffset = connectionTime - processingTime;
						metadataTimeOffset += NetRadio.bufferTimeInSeconds;
						metadataTimeOffset *= 0.79f;
						if (metadataTimeOffset > 0f && looped)
						{
							await Task.Delay((int)(metadataTimeOffset * 1000f));
						}
						HandleMetadata(currentMetadata);
						oldMetadata = currentMetadata;
						looped = true;
					}
				}
				await Task.Yield();
			}
			trackingMetadata = false;
		}

		private void HandleMetadata(string originalMetadata)
		{
			string text = "Unknown Track";
			if (!string.IsNullOrWhiteSpace(originalMetadata) && originalMetadata.Contains("StreamTitle='") && !originalMetadata.Contains("StreamTitle=''"))
			{
				string value = Regex.Match(originalMetadata, "(?:StreamTitle=')(.*)(?:')[;,= ]", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.CultureInvariant).Groups[1].Value;
				currentSong = value.Trim();
			}
			else
			{
				currentSong = text;
			}
			NetRadio.Log.LogInfo((object)("Metadata updated for station " + GetStationTitle() + ": " + currentSong));
			NetRadioPlugin.UpdateCurrentSong();
		}

		private HttpClient CreateHTTPClient()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			HttpClient val = new HttpClient();
			val.DefaultRequestHeaders.UserAgent.ParseAdd("C# App (BRC NetRadio)");
			val.Timeout = TimeSpan.FromSeconds(10.0);
			return val;
		}

		private async Task<string> GetMetaDataFromIceCastStream(string url)
		{
			if (url == null)
			{
				return null;
			}
			((HttpHeaders)m_httpClient.DefaultRequestHeaders).Add("Icy-MetaData", "1");
			HttpResponseMessage response = await m_httpClient.GetAsync(url, (HttpCompletionOption)1);
			((HttpHeaders)m_httpClient.DefaultRequestHeaders).Remove("Icy-MetaData");
			if (response.IsSuccessStatusCode)
			{
				string metaIntString = NetRadio.ReadIcyHeader(response, "metaint");
				if (!string.IsNullOrWhiteSpace(metaIntString) && int.TryParse(metaIntString, out var metadataInterval))
				{
					byte[] buffer = new byte[metadataInterval];
					using Stream stream = await response.Content.ReadAsStreamAsync();
					int numBytesRead = 0;
					int numBytesToRead = metadataInterval;
					while (numBytesToRead > 0)
					{
						int i = stream.Read(buffer, numBytesRead, Mathf.Min(10, numBytesToRead));
						numBytesRead += i;
						numBytesToRead -= i;
					}
					int lengthOfMetaData = stream.ReadByte();
					int metaBytesToRead = lengthOfMetaData * 16;
					byte[] metadataBytes = new byte[metaBytesToRead];
					await stream.ReadAsync(metadataBytes, 0, metaBytesToRead);
					return Encoding.UTF8.GetString(metadataBytes);
				}
			}
			return null;
		}

		private void CalculateSpatial()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			SetPan(GetSpatialPanning(Camera.main, ((Component)this).gameObject));
			Transform transform = ((Component)NetRadio.player).transform;
			float num = Vector3.Distance(transform.position, ((Component)this).gameObject.transform.position);
			float num2 = 1f;
			if (num > minDistance)
			{
				float num3 = num - minDistance;
				num2 -= Mathf.Sqrt(maxDistance * num3) / maxDistance;
				num2 = Mathf.Clamp01(num2);
			}
			radioVolume = num2 * NetRadio.sfxVolume;
			AdjustMusicVolume(num2);
		}

		public void AdjustMusicVolume(float volume, float multiplier = 0.5f)
		{
			NetRadio.musicPlayer.audioSource.volume = 1f - volume * multiplier;
			NetRadio.GlobalRadio.volume = 1f - volume * multiplier;
		}

		public float GetSpatialPanning(Camera cam, GameObject audioEmitter)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)cam == (Object)null || (Object)(object)audioEmitter == (Object)null)
			{
				return pan;
			}
			Vector3 forward = ((Component)cam).transform.forward;
			Vector3 val = audioEmitter.transform.position - ((Component)cam).transform.position;
			val.y = 0f;
			forward.y = 0f;
			((Vector3)(ref forward)).Normalize();
			((Vector3)(ref val)).Normalize();
			val = Quaternion.AngleAxis(-90f, Vector3.up) * val;
			float num = Vector3.Dot(forward, val);
			return Mathf.Clamp(num, -1f, 1f);
		}

		private void SetPan(float value)
		{
			pan = Mathf.Lerp(pan, value, 0.2f);
			if (pannedMonoSource != null && centerSource != null && monoSource != null)
			{
				pannedMonoSource.Pan = Mathf.Sign(pan);
				if (centerSource is VolumeSource)
				{
					SampleAggregatorBase obj = centerSource;
					((VolumeSource)((obj is VolumeSource) ? obj : null)).Volume = 1f - Mathf.Abs(pan);
				}
				monoSource.Volume = Mathf.Abs(pan);
			}
		}

		public static NetRadioManager CreateRadio(Transform parent, bool playNow = true, bool spatialize = true, List<string> clipURL = null)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject();
			NetRadioManager netRadioManager = val.AddComponent<NetRadioManager>();
			val.transform.parent = parent;
			netRadioManager.spatialize = spatialize;
			((Component)netRadioManager).gameObject.transform.position = ((Component)parent).transform.position;
			if (clipURL != null)
			{
				netRadioManager.streamURLs = clipURL;
			}
			if (playNow && netRadioManager.streamURLs != null && netRadioManager.streamURLs.Any())
			{
				netRadioManager.PlayRadioStation(0);
			}
			return netRadioManager;
		}
	}
	[HarmonyPatch(typeof(AppMusicPlayer))]
	internal class MusicAppPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch("OnReleaseRight")]
		public static bool OnReleaseRight_ClearCurrent(AppMusicPlayer __instance)
		{
			if (NetRadio.GlobalRadio.playing && !__instance.shuffleControlSelected)
			{
				NetRadio.GlobalRadio.Stop();
				__instance.m_StatusPanel.m_CurrentTrack = null;
				IMusicPlayer gameMusicPlayer = __instance.GameMusicPlayer;
				((MusicPlayer)((gameMusicPlayer is MusicPlayer) ? gameMusicPlayer : null)).musicTrackQueue.currentTrackIndex = -1;
				? val = __instance.m_StatusPanel;
				AUnlockable assignedContent = ((PhoneScrollUnlockableButton)/*isinst with value type is only supported in some contexts*/).AssignedContent;
				((MusicPlayerStatusPanel)val).OnNewTrack((MusicTrack)(object)((assignedContent is MusicTrack) ? assignedContent : null));
			}
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch("OnAppEnable")]
		public static void OnEnable_Refresh()
		{
			NetRadioPlugin.UpdateCurrentSong(skipCheck: true);
		}
	}
	[HarmonyPatch(typeof(MusicPlayerStatusPanel))]
	internal class MusicAppPanelPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("StatusIconUpdate")]
		public static void UpdateStatusIcon(MusicPlayerStatusPanel __instance)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			if (NetRadio.GlobalRadio.playing)
			{
				__instance.m_StatusImage.sprite = __instance.m_StatusIcons[0];
				float num = 1f;
				float num2 = 0.65f;
				Vector3 val = Vector3.one * (1f + NetRadio.GlobalRadio.streamSampleVolume * num - 0.5f * num);
				((Transform)((Graphic)__instance.m_StatusImage).rectTransform).localScale = Vector3.Lerp(((Transform)((Graphic)__instance.m_StatusImage).rectTransform).localScale, val, 30f * num2 * Time.deltaTime);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("ProgressbarUpdate")]
		public static void UpdateProgress(MusicPlayerStatusPanel __instance)
		{
			if (NetRadio.GlobalRadio.playing)
			{
				__instance.m_ProgressBar.fillAmount = NetRadio.GlobalRadio.streamSampleVolume;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("OnNewTrack")]
		public static void OnNewTrack_RadioUpdate(MusicPlayerStatusPanel __instance)
		{
			if (!(__instance.m_CurrentTrack.Artist == NetRadio.GlobalRadio.GetStationTitle()) && NetRadio.GlobalRadio.playing)
			{
				NetRadioPlugin.UpdateCurrentSong();
			}
		}
	}
	[HarmonyPatch(typeof(BaseModule))]
	internal class ReloadMainMenu
	{
		[HarmonyPatch("LoadMainMenuScene")]
		[HarmonyPostfix]
		private static void LoadingMenu_ResetVars()
		{
			NetRadio.gameStarted = false;
			NetRadio.GlobalRadio.Stop();
		}
	}
	[HarmonyPatch(typeof(StageManager))]
	internal class SMPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(StageManager), "StartMusicForStage", new Type[]
		{
			typeof(Stage),
			typeof(int)
		})]
		public static void StartupRadio()
		{
			if (NetRadio.gameStarted)
			{
				return;
			}
			NetRadio.gameStarted = true;
			if (NetRadioSettings.playOnStartup.Value)
			{
				((MonoBehaviour)NetRadioPlugin.Instance).StartCoroutine(NetRadio.MuteUntilRadioPlaying());
				if (NetRadioSettings.startupIndex.Value == -1)
				{
					NetRadio.GlobalRadio.PlayRandomStation();
				}
				else
				{
					NetRadio.GlobalRadio.PlayRadioStation(NetRadioSettings.startupIndex.Value);
				}
				AppNetRadio.PlayNoise();
				AppNetRadio.musicPlayerWasInterrupted = false;
			}
		}
	}
	[HarmonyPatch(typeof(SimplePhoneButton))]
	internal class ButtonPatches
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			Type type = typeof(SimplePhoneButton);
			yield return AccessTools.Method(type, "PlayHoldAnimation", (Type[])null, (Type[])null);
			yield return AccessTools.Method(type, "PlayHighlightAnimation", (Type[])null, (Type[])null);
			yield return AccessTools.Method(type, "PlayDeselectAnimation", (Type[])null, (Type[])null);
			yield return AccessTools.Method(type, "CacheResources", (Type[])null, (Type[])null);
		}

		public static void Postfix(SimplePhoneButton __instance)
		{
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			if ((!(NetRadio.player.phone.m_CurrentApp is AppNetRadio) || !AppNetRadio.runPrefix) && !(NetRadio.player.phone.m_CurrentApp is AppSelectedStation))
			{
				return;
			}
			if (NetRadio.IsHeaderButton(__instance))
			{
				__instance.ButtonImage.sprite = AppNetRadio.BlankButtonSprite;
			}
			if (!NetRadio.IsStationButton(__instance))
			{
				return;
			}
			Sprite sprite = __instance.ButtonImage.sprite;
			bool flag = (Object)(object)sprite == (Object)(object)__instance.SelectedButtonSprite;
			TextMeshProUGUI component = ((Component)((Component)__instance.Label).gameObject.transform.GetChild(0)).gameObject.GetComponent<TextMeshProUGUI>();
			if (!((Object)(object)component == (Object)null))
			{
				((TMP_Text)component).faceColor = Color32.op_Implicit(flag ? __instance.LabelUnselectedColor : __instance.LabelSelectedColor);
				__instance.ButtonImage.sprite = (flag ? AppNetRadio.SelectedButtonSprite : AppNetRadio.UnselectedButtonSprite);
				GameObjectExtensions.RectTransform(((Component)__instance.ButtonImage).gameObject).sizeDelta = new Vector2(1104f, 304f);
				AppNetRadio.time = -1f;
				Image component2 = ((Component)((Component)__instance.Label).gameObject.transform.GetChild(2)).gameObject.GetComponent<Image>();
				if ((Object)(object)component2 == (Object)null || ((Object)((Component)component2).gameObject).name.Contains("Logo"))
				{
					component2.sprite = AppNetRadio.GetStationLogo(((TMP_Text)__instance.Label).text, flag);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ASceneSetupInstruction))]
	internal class patch_StageManager_OnPostRender
	{
		[HarmonyPatch("SetSceneActive")]
		private static void Postfix(string sceneToSetActive)
		{
		}
	}
	[BepInPlugin("goatgirl.NetRadio", "NetRadio", "1.0.4")]
	[BepInProcess("Bomb Rush Cyberfunk.exe")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class NetRadioPlugin : BaseUnityPlugin
	{
		internal static Harmony Harmony = new Harmony("goatgirl.NetRadio");

		public static bool hasBRR = false;

		public static bool hasMusicCurator = false;

		public static NetRadioPlugin Instance { get; private set; }

		public string Directory => Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);

		private void Awake()
		{
			Instance = this;
			NetRadio.Log = ((BaseUnityPlugin)this).Logger;
			Harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin NetRadio is loaded!");
			NetRadio.GlobalRadio = NetRadioManager.CreateRadio(((Component)this).transform, playNow: false, spatialize: false);
			NetRadio.GlobalRadio.volume = 1f;
			AppNetRadio.Initialize();
			AppSelectedStation.Initialize();
			NetRadioSettings.BindSettings(((BaseUnityPlugin)this).Config);
			foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
			{
				if (pluginInfo.Value.Metadata.GUID.Contains("BombRushRadio"))
				{
					hasBRR = true;
				}
				if (pluginInfo.Value.Metadata.GUID.Contains("MusicCurator"))
				{
					hasMusicCurator = true;
				}
				if (pluginInfo.Value.Metadata.GUID.Contains("LiveRadioPOC"))
				{
					NetRadio.Log.LogError((object)"Development version of goatgirl.NetRadio detected! Please delete the development version (goatgirl.LiveRadioPOC)!");
				}
			}
			if (Debugger.IsAttached)
			{
				FfmpegUtils.LogToDefaultLogger = false;
				FfmpegUtils.FfmpegLogReceived += delegate(object s, FfmpegLogReceivedEventArgs e)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)e.Message);
				};
			}
		}

		private void OnDestroy()
		{
			Harmony.UnpatchSelf();
		}

		private void Update()
		{
			if (NetRadio.GlobalRadio != null)
			{
				if (NetRadio.GlobalRadio.playing)
				{
					UpdateGlobalRadioVolume();
					if (NetRadio.musicPlayer.IsPlaying)
					{
						NetRadio.musicPlayer.ForcePaused();
					}
				}
				if (AppNetRadio.waveOut != null && AppNetRadio.playing)
				{
					if (NetRadio.PlayerUsingApp(typeof(AppNetRadio)))
					{
						if (NetRadio.GlobalRadio.failedToLoad)
						{
							((MonoBehaviour)this).StartCoroutine(AppNetRadio.Instance.HandleFailedConnection());
						}
						else if (NetRadio.GlobalRadio.playing)
						{
							((MonoBehaviour)this).StartCoroutine(AppNetRadio.Instance.StopIn(1f));
						}
					}
					else if (NetRadio.GlobalRadio.playing || NetRadio.GlobalRadio.failedToLoad)
					{
						NetRadio.GlobalRadio.failedToLoad = false;
						AppNetRadio.waveOut.Stop();
						AppNetRadio.playing = false;
					}
				}
			}
			if (NetRadio.pressedAnyButtonIn(NetRadioSettings.keybindsReload))
			{
				NetRadioManager.ReloadAllStations();
			}
		}

		public static void UpdateGlobalRadioVolume()
		{
			string key = NetRadio.StandardizeURL(NetRadio.GlobalRadio.currentStationURL);
			float num = (NetRadioSaveData.stationVolumesByURL.ContainsKey(key) ? ((float)NetRadioSaveData.stationVolumesByURL[key]) : 1f);
			NetRadio.GlobalRadio.radioVolume = NetRadio.radioMusicVolume * num;
		}

		public static void UpdateCurrentSong(bool skipCheck = false)
		{
			if (NetRadio.GlobalRadio.playing && (skipCheck || NetRadio.PlayerUsingMusicApp()))
			{
				App currentApp = NetRadio.player.phone.m_CurrentApp;
				AppMusicPlayer val = (AppMusicPlayer)(object)((currentApp is AppMusicPlayer) ? currentApp : null);
				MusicTrack val2 = ScriptableObject.CreateInstance<MusicTrack>();
				val2.AudioClip = null;
				val2.Artist = NetRadio.GlobalRadio.GetStationTitle();
				val2.Title = NetRadio.GlobalRadio.currentSong;
				val.m_StatusPanel.OnNewTrack(val2);
			}
		}
	}
	public class NetRadioSaveData : CustomSaveData
	{
		public static readonly int saveVersion = 0;

		private static int readSaveVersion = 0;

		public static Dictionary<string, decimal> stationVolumesByURL = new Dictionary<string, decimal>();

		public static NetRadioSaveData Instance { get; private set; }

		public NetRadioSaveData()
			: base("NetRadio", "Slot{0}.data", (SaveLocations)2)
		{
			Instance = this;
			base.AutoSave = false;
		}

		public override void Initialize()
		{
			stationVolumesByURL = new Dictionary<string, decimal>();
			NetRadioSettings.LoadURLs();
			foreach (string configURL in NetRadioSettings.configURLs)
			{
				if (!stationVolumesByURL.ContainsKey(NetRadio.StandardizeURL(configURL)))
				{
					stationVolumesByURL.Add(NetRadio.StandardizeURL(configURL), 1m);
				}
			}
		}

		public override void Read(BinaryReader reader)
		{
			stationVolumesByURL.Clear();
			readSaveVersion = reader.ReadByte();
			int num = reader.ReadInt32();
			for (int i = 0; i < num; i++)
			{
				string key = reader.ReadString();
				decimal value = reader.ReadDecimal();
				if (!stationVolumesByURL.ContainsKey(key))
				{
					stationVolumesByURL.Add(key, value);
				}
			}
		}

		public override void Write(BinaryWriter writer)
		{
			writer.Write((byte)saveVersion);
			writer.Write(stationVolumesByURL.Count);
			foreach (string key in stationVolumesByURL.Keys)
			{
				writer.Write(key);
				writer.Write(stationVolumesByURL[key]);
			}
		}
	}
	internal class NetRadioSettings
	{
		public static ConfigEntry<string> streamURLsUnsplit;

		public static ConfigEntry<float> streamVolume;

		public static ConfigEntry<bool> playOnStartup;

		public static ConfigEntry<int> startupIndex;

		public static ConfigEntry<bool> configureRequireConnection;

		public static ConfigEntry<float> extraBufferSec;

		public static ConfigEntry<string> keybindsReloadUnsplit;

		public static ConfigEntry<bool> noThreads;

		public static ConfigEntry<bool> moreCodecs;

		public static List<KeyCode> keybindsReload;

		public static List<string> streamTitles = new List<string>();

		public const string partneredStations = "\r\n            (FunkyUncleFM)https://fancynoise.net:8443/fufm.mp3,\r\n        ";

		public static string extraStations = "";

		public static List<string> configURLs;

		public static void BindSettings(ConfigFile Config)
		{
			streamURLsUnsplit = Config.Bind<string>("Settings", "Custom Stream URLs", "", "List of custom radio station URLs, separated by commas. To add a display name, format your link like: (StationName)https://stationlink.com/stream.mp3");
			streamURLsUnsplit.SettingChanged += UpdateSettingsEvent;
			streamVolume = Config.Bind<float>("Settings", "Radio Volume", 1f, "Relative volume of all radio streams compared to in-game music. Note that you can set individual stations' volumes in the NetRadio app.");
			playOnStartup = Config.Bind<bool>("Settings", "Play Radio on Startup", false, "Whether or not a radio station should automatically play upon loading a save.");
			startupIndex = Config.Bind<int>("Settings", "Startup Radio Station", -1, "The index of the station to play automatically if Play Radio on Startup is enabled (the first station in the NetRadio app is at index 0). If set to -1, the station will be chosen randomly.");
			configureRequireConnection = Config.Bind<bool>("Settings", "Configuring Stations Requires Connection", true, "Whether it is possible to change a station's settings within the NetRadio app without connecting to the station.");
			extraBufferSec = Config.Bind<float>("Settings", "Buffer Time", 0.5f, "The length of the station's buffer in seconds. A longer buffer delays audio playback, but reduces stuttering.");
			keybindsReloadUnsplit = Config.Bind<string>("Settings", "Reload Radios Keybinds", "F11", "Press to reload all in-game radio streams.");
			keybindsReloadUnsplit.SettingChanged += UpdateSettingsEvent;
			noThreads = Config.Bind<bool>("Settings", "Disable Multithreading", false, "EXPERIMENTAL! Prevent multithreading for radio streaming, causing the game to freeze when starting a radio. Not recommended.");
			moreCodecs = Config.Bind<bool>("Settings", "Enable Media Foundation Codecs", false, "EXPERIMENTAL! Windows only. Allow the use of Windows Media Foundation codecs instead of FFmpeg. Note that if the Media Foundation player fails, the mod will fallback to FFmpeg.");
		}

		public static void UpdateSettingsEvent(object sender, EventArgs args)
		{
			LoadURLs();
			RefreshMusicApp();
		}

		public static void RefreshMusicApp()
		{
			if ((Object)(object)NetRadio.player != (Object)null && (Object)(object)NetRadio.player.phone != (Object)null && NetRadio.player.phone.m_CurrentApp is AppNetRadio && NetRadio.player.phone.IsOn && NetRadio.player.phoneLayerWeight >= 1f)
			{
				AppNetRadio.Instance.ReloadButtons();
			}
		}

		public static void LoadURLs()
		{
			string input = "\r\n            (FunkyUncleFM)https://fancynoise.net:8443/fufm.mp3,\r\n        " + streamURLsUnsplit.Value + extraStations;
			List<string> list = SplitStringByCommas(input).Distinct().ToList();
			List<string> list2 = new List<string>();
			streamTitles.Clear();
			foreach (string item in list)
			{
				if (!string.IsNullOrWhiteSpace(item))
				{
					string[] array = item.Split(new string[1] { ")" }, StringSplitOptions.RemoveEmptyEntries);
					string text = ((array.Length > 1) ? array[0].Split(new string[1] { "(" }, StringSplitOptions.None)[1] : "NetRadio");
					string text2 = ((array.Length > 1) ? array[1].Trim() : item.Trim());
					if (!text2.StartsWith("https://") && !text2.StartsWith("http://"))
					{
						NetRadio.Log.LogInfo((object)("adding HTTP to stream " + text2));
						text2 = "http://" + text2;
					}
					list2.Add(text2);
					streamTitles.Add(text.Trim());
					NetRadio.Log.LogInfo((object)("Added stream " + text2));
				}
			}
			NetRadio.GlobalRadio.streamURLs = list2;
			configURLs = list2;
			keybindsReload = KeyCodeListFromList(SplitStringByCommas(keybindsReloadUnsplit.Value));
			AppNetRadio.originalURLLabelText.Clear();
			AppNetRadio.urlWrapOffsets.Clear();
			AppNetRadio.urlIsTooLong.Clear();
		}

		public static List<string> SplitStringByCommas(string input)
		{
			return input.Replace("\n", "").Replace("\r", "").Replace("\t", "")
				.Replace(",  ", ",")
				.Replace(", ", ",")
				.Split(new string[1] { "," }, StringSplitOptions.RemoveEmptyEntries)
				.ToList();
		}

		public static KeyCode StringToKeyCode(string input)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (Enum.TryParse<KeyCode>(input, ignoreCase: true, out KeyCode result))
			{
				return result;
			}
			return (KeyCode)0;
		}

		public static List<KeyCode> KeyCodeListFromList(List<string> input)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			List<KeyCode> list = new List<KeyCode>();
			foreach (string item in input)
			{
				list.Add(StringToKeyCode(item));
			}
			return list;
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "NetRadio";

		public const string PLUGIN_NAME = "NetRadio";

		public const string PLUGIN_VERSION = "1.0.4";
	}
}