Decompiled source of MyCustomRadio v0.1.2

HowToFishCustomRadio.dll

Decompiled 15 hours ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Threading;
using BepInEx;
using BepInEx.Logging;
using FishNet;
using FishNet.Broadcast;
using FishNet.Connection;
using FishNet.Managing.Object;
using FishNet.Object;
using FishNet.Serializing;
using FishNet.Transporting;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("HowToFishCustomRadio")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("HowToFishCustomRadio")]
[assembly: AssemblyTitle("HowToFishCustomRadio")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace CustomRadioFramework;

public struct MusicChunkBroadcast : IBroadcast
{
	public int trackId;

	public int chunkIndex;

	public int totalChunks;

	public byte[] data;
}
public struct MusicControlBroadcast : IBroadcast
{
	public bool isPaused;

	public float timePosition;
}
public struct MusicVolumeBroadcast : IBroadcast
{
	public float volume;
}
public static class CustomSerializers
{
	public static void WriteMusicChunkBroadcast(this Writer writer, MusicChunkBroadcast msg)
	{
		writer.Write<int>(msg.trackId);
		writer.Write<int>(msg.chunkIndex);
		writer.Write<int>(msg.totalChunks);
		writer.Write<byte[]>(msg.data);
	}

	public static MusicChunkBroadcast ReadMusicChunkBroadcast(this Reader reader)
	{
		return new MusicChunkBroadcast
		{
			trackId = reader.Read<int>(),
			chunkIndex = reader.Read<int>(),
			totalChunks = reader.Read<int>(),
			data = reader.Read<byte[]>()
		};
	}

	public static void WriteMusicControlBroadcast(this Writer writer, MusicControlBroadcast msg)
	{
		writer.Write<bool>(msg.isPaused);
		writer.Write<float>(msg.timePosition);
	}

	public static MusicControlBroadcast ReadMusicControlBroadcast(this Reader reader)
	{
		return new MusicControlBroadcast
		{
			isPaused = reader.Read<bool>(),
			timePosition = reader.Read<float>()
		};
	}

	public static void WriteMusicVolumeBroadcast(this Writer writer, MusicVolumeBroadcast msg)
	{
		writer.Write<float>(msg.volume);
	}

	public static MusicVolumeBroadcast ReadMusicVolumeBroadcast(this Reader reader)
	{
		return new MusicVolumeBroadcast
		{
			volume = reader.Read<float>()
		};
	}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class OpenFileName
{
	public int structSize;

	public IntPtr hwndOwner = IntPtr.Zero;

	public IntPtr hInstance = IntPtr.Zero;

	public string filter;

	public string customFilter;

	public int maxCustFilter;

	public int filterIndex;

	public string file;

	public int maxFile;

	public string fileTitle;

	public int maxFileTitle;

	public string initialDir;

	public string title;

	public int flags;

	public short fileOffset;

	public short fileExtension;

	public string defExt;

	public IntPtr custData = IntPtr.Zero;

	public IntPtr hook = IntPtr.Zero;

	public string templateName;

	public IntPtr reservedPtr = IntPtr.Zero;

	public int reservedInt;

	public int flagsEx;
}
public class LocalDialog
{
	[DllImport("Comdlg32.dll", CharSet = CharSet.Auto, SetLastError = true, ThrowOnUnmappableChar = true)]
	public static extern bool GetOpenFileName([In][Out] OpenFileName ofn);
}
[BepInPlugin("com.customradio.howtofish", "Custom Radio Framework", "0.1.2")]
public class Plugin : BaseUnityPlugin
{
	public static ManualLogSource Log;

	public static float LocalIgnoreNetworkTime;

	private CustomRadioNetworkService networkService;

	private CustomRadioAudioController audioController;

	private CustomRadioUI uiManager;

	private void Awake()
	{
		Log = ((BaseUnityPlugin)this).Logger;
		Log.LogInfo((object)"Custom Radio v0.1.2 (Standard) загружен. Защита Steamworks включена.");
		CleanupOldTempFiles();
		audioController = new CustomRadioAudioController(this);
		networkService = new CustomRadioNetworkService(this, audioController);
		uiManager = new CustomRadioUI(this, networkService, audioController);
		((MonoBehaviour)this).StartCoroutine(WaitForNetwork());
	}

	private IEnumerator WaitForNetwork()
	{
		while ((Object)(object)InstanceFinder.NetworkManager == (Object)null || (Object)(object)InstanceFinder.ClientManager == (Object)null)
		{
			yield return null;
		}
		networkService.RegisterCallbacks();
	}

	private void Update()
	{
		uiManager.HandleInput();
		networkService.ProcessTimeouts();
	}

	private void OnGUI()
	{
		uiManager.DrawUI();
	}

	private void OnDestroy()
	{
		networkService?.UnregisterCallbacks();
		audioController?.Dispose();
		CleanupOldTempFiles();
	}

	private void CleanupOldTempFiles()
	{
		try
		{
			string[] files = Directory.GetFiles(Application.temporaryCachePath, "radio_sync_*.mp3");
			for (int i = 0; i < files.Length; i++)
			{
				File.Delete(files[i]);
			}
		}
		catch
		{
		}
	}
}
public class CustomRadioAudioController : IDisposable
{
	private Plugin plugin;

	public AudioSource Source { get; private set; }

	public bool IsPaused { get; private set; }

	public float CurrentVolume { get; set; } = 1f;

	public CustomRadioAudioController(Plugin plugin)
	{
		this.plugin = plugin;
	}

	public void EnsureRadioExists()
	{
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: 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_008c: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Source != (Object)null)
		{
			return;
		}
		GameObject val = null;
		GameObject val2 = GameObject.Find("LocalPlayer");
		float num = float.MaxValue;
		if ((Object)(object)InstanceFinder.ClientManager != (Object)null)
		{
			foreach (NetworkObject value in ((ManagedObjects)InstanceFinder.ClientManager.Objects).Spawned.Values)
			{
				if (((Object)((Component)value).gameObject).name.IndexOf("Radio", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					if (!((Object)(object)val2 != (Object)null))
					{
						val = ((Component)value).gameObject;
						break;
					}
					float num2 = Vector3.Distance(val2.transform.position, ((Component)value).transform.position);
					if (num2 < num)
					{
						num = num2;
						val = ((Component)value).gameObject;
					}
				}
			}
		}
		if ((Object)(object)val == (Object)null && (Object)(object)val2 != (Object)null)
		{
			val = val2;
		}
		if ((Object)(object)val != (Object)null)
		{
			Transform val3 = val.transform.Find("CustomRadioSource");
			GameObject val4 = (GameObject)(((Object)(object)val3 != (Object)null) ? ((object)((Component)val3).gameObject) : ((object)new GameObject("CustomRadioSource")));
			val4.transform.SetParent(val.transform);
			val4.transform.localPosition = Vector3.zero;
			Source = val4.GetComponent<AudioSource>() ?? val4.AddComponent<AudioSource>();
			Source.spatialBlend = 1f;
			Source.minDistance = 3f;
			Source.maxDistance = 40f;
			Source.rolloffMode = (AudioRolloffMode)1;
			Source.volume = CurrentVolume;
		}
	}

	public void PlayLocalFile(string path)
	{
		((MonoBehaviour)plugin).StartCoroutine(LoadAndPlayAudio("file:///" + path.Replace("\\", "/")));
	}

	private IEnumerator LoadAndPlayAudio(string url)
	{
		UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(url, (AudioType)13);
		try
		{
			yield return www.SendWebRequest();
			if ((Object)(object)Source == (Object)null)
			{
				yield break;
			}
			if ((int)www.result == 1)
			{
				AudioClip content = DownloadHandlerAudioClip.GetContent(www);
				if ((Object)(object)Source.clip != (Object)null)
				{
					Object.Destroy((Object)(object)Source.clip);
				}
				Source.clip = content;
				IsPaused = false;
				Source.Play();
			}
		}
		finally
		{
			((IDisposable)www)?.Dispose();
		}
	}

	public void ApplyControlState(bool pauseState, float timePosition)
	{
		if (!((Object)(object)Source == (Object)null))
		{
			IsPaused = pauseState;
			Source.time = timePosition;
			if (IsPaused)
			{
				Source.Pause();
			}
			else
			{
				Source.Play();
			}
		}
	}

	public void ApplyVolume(float vol)
	{
		CurrentVolume = vol;
		if ((Object)(object)Source != (Object)null)
		{
			Source.volume = CurrentVolume;
		}
	}

	public void Dispose()
	{
		if ((Object)(object)Source != (Object)null && (Object)(object)Source.clip != (Object)null)
		{
			Object.Destroy((Object)(object)Source.clip);
		}
	}
}
public class CustomRadioNetworkService
{
	private class DownloadContext
	{
		public FileStream Stream;

		public int ExpectedChunks;

		public HashSet<int> ReceivedChunks;

		public float LastActivityTime;

		public string TempPath;
	}

	public const int CHUNK_SIZE = 8192;

	private const int MAX_FILE_SIZE = 15728640;

	private const float DOWNLOAD_TIMEOUT = 120f;

	private Plugin plugin;

	private CustomRadioAudioController audio;

	private bool isRegistered;

	private Dictionary<int, DownloadContext> activeDownloads = new Dictionary<int, DownloadContext>();

	public CustomRadioNetworkService(Plugin plugin, CustomRadioAudioController audio)
	{
		this.plugin = plugin;
		this.audio = audio;
	}

	public void RegisterCallbacks()
	{
		if (!isRegistered)
		{
			GenericWriter<MusicChunkBroadcast>.SetWrite((Action<Writer, MusicChunkBroadcast>)CustomSerializers.WriteMusicChunkBroadcast);
			GenericReader<MusicChunkBroadcast>.SetRead((Func<Reader, MusicChunkBroadcast>)CustomSerializers.ReadMusicChunkBroadcast);
			GenericWriter<MusicControlBroadcast>.SetWrite((Action<Writer, MusicControlBroadcast>)CustomSerializers.WriteMusicControlBroadcast);
			GenericReader<MusicControlBroadcast>.SetRead((Func<Reader, MusicControlBroadcast>)CustomSerializers.ReadMusicControlBroadcast);
			GenericWriter<MusicVolumeBroadcast>.SetWrite((Action<Writer, MusicVolumeBroadcast>)CustomSerializers.WriteMusicVolumeBroadcast);
			GenericReader<MusicVolumeBroadcast>.SetRead((Func<Reader, MusicVolumeBroadcast>)CustomSerializers.ReadMusicVolumeBroadcast);
			InstanceFinder.ClientManager.RegisterBroadcast<MusicChunkBroadcast>((Action<MusicChunkBroadcast, Channel>)OnClientReceiveChunk);
			InstanceFinder.ServerManager.RegisterBroadcast<MusicChunkBroadcast>((Action<NetworkConnection, MusicChunkBroadcast, Channel>)OnServerReceiveChunk, true);
			InstanceFinder.ClientManager.RegisterBroadcast<MusicControlBroadcast>((Action<MusicControlBroadcast, Channel>)OnClientReceiveControl);
			InstanceFinder.ServerManager.RegisterBroadcast<MusicControlBroadcast>((Action<NetworkConnection, MusicControlBroadcast, Channel>)OnServerReceiveControl, true);
			InstanceFinder.ClientManager.RegisterBroadcast<MusicVolumeBroadcast>((Action<MusicVolumeBroadcast, Channel>)OnClientReceiveVolume);
			InstanceFinder.ServerManager.RegisterBroadcast<MusicVolumeBroadcast>((Action<NetworkConnection, MusicVolumeBroadcast, Channel>)OnServerReceiveVolume, true);
			isRegistered = true;
		}
	}

	public void UnregisterCallbacks()
	{
		if (!isRegistered)
		{
			return;
		}
		if ((Object)(object)InstanceFinder.ClientManager != (Object)null)
		{
			InstanceFinder.ClientManager.UnregisterBroadcast<MusicChunkBroadcast>((Action<MusicChunkBroadcast, Channel>)OnClientReceiveChunk);
			InstanceFinder.ClientManager.UnregisterBroadcast<MusicControlBroadcast>((Action<MusicControlBroadcast, Channel>)OnClientReceiveControl);
			InstanceFinder.ClientManager.UnregisterBroadcast<MusicVolumeBroadcast>((Action<MusicVolumeBroadcast, Channel>)OnClientReceiveVolume);
		}
		if ((Object)(object)InstanceFinder.ServerManager != (Object)null)
		{
			InstanceFinder.ServerManager.UnregisterBroadcast<MusicChunkBroadcast>((Action<NetworkConnection, MusicChunkBroadcast, Channel>)OnServerReceiveChunk);
			InstanceFinder.ServerManager.UnregisterBroadcast<MusicControlBroadcast>((Action<NetworkConnection, MusicControlBroadcast, Channel>)OnServerReceiveControl);
			InstanceFinder.ServerManager.UnregisterBroadcast<MusicVolumeBroadcast>((Action<NetworkConnection, MusicVolumeBroadcast, Channel>)OnServerReceiveVolume);
		}
		foreach (DownloadContext value in activeDownloads.Values)
		{
			value.Stream.Dispose();
			if (File.Exists(value.TempPath))
			{
				File.Delete(value.TempPath);
			}
		}
		activeDownloads.Clear();
	}

	public void SendFile(string path)
	{
		((MonoBehaviour)plugin).StartCoroutine(StreamFileCoroutine(path));
	}

	private IEnumerator StreamFileCoroutine(string path)
	{
		if ((Object)(object)InstanceFinder.ClientManager == (Object)null)
		{
			yield break;
		}
		FileInfo fileInfo = new FileInfo(path);
		if (fileInfo.Length > 15728640)
		{
			yield break;
		}
		int trackId = Random.Range(1000, 999999);
		int totalChunks = Mathf.CeilToInt((float)fileInfo.Length / 8192f);
		using FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
		byte[] buffer = new byte[8192];
		int chunkIndex = 0;
		int num;
		while ((num = fs.Read(buffer, 0, buffer.Length)) > 0)
		{
			byte[] array;
			if (num < 8192)
			{
				array = new byte[num];
				Buffer.BlockCopy(buffer, 0, array, 0, num);
			}
			else
			{
				array = buffer;
			}
			InstanceFinder.ClientManager.Broadcast<MusicChunkBroadcast>(new MusicChunkBroadcast
			{
				trackId = trackId,
				chunkIndex = chunkIndex,
				totalChunks = totalChunks,
				data = array
			}, (Channel)0);
			chunkIndex++;
			yield return (object)new WaitForSeconds(0.03f);
		}
	}

	public void SendControl(bool isPaused, float time)
	{
		if ((Object)(object)InstanceFinder.ClientManager != (Object)null)
		{
			InstanceFinder.ClientManager.Broadcast<MusicControlBroadcast>(new MusicControlBroadcast
			{
				isPaused = isPaused,
				timePosition = time
			}, (Channel)0);
		}
	}

	public void SendVolume(float vol)
	{
		if ((Object)(object)InstanceFinder.ClientManager != (Object)null)
		{
			InstanceFinder.ClientManager.Broadcast<MusicVolumeBroadcast>(new MusicVolumeBroadcast
			{
				volume = vol
			}, (Channel)0);
		}
	}

	private void OnServerReceiveChunk(NetworkConnection conn, MusicChunkBroadcast msg, Channel channel)
	{
		if (msg.data != null && msg.data.Length <= 9216)
		{
			InstanceFinder.ServerManager.Broadcast<MusicChunkBroadcast>(msg, true, (Channel)0);
		}
	}

	private void OnServerReceiveControl(NetworkConnection conn, MusicControlBroadcast msg, Channel channel)
	{
		InstanceFinder.ServerManager.Broadcast<MusicControlBroadcast>(msg, true, (Channel)0);
	}

	private void OnServerReceiveVolume(NetworkConnection conn, MusicVolumeBroadcast msg, Channel channel)
	{
		InstanceFinder.ServerManager.Broadcast<MusicVolumeBroadcast>(msg, true, (Channel)0);
	}

	private void OnClientReceiveChunk(MusicChunkBroadcast msg, Channel channel)
	{
		if (!activeDownloads.TryGetValue(msg.trackId, out var value))
		{
			string text = Path.Combine(Application.temporaryCachePath, $"radio_sync_{msg.trackId}.mp3");
			value = new DownloadContext
			{
				TempPath = text,
				Stream = new FileStream(text, FileMode.Create, FileAccess.Write, FileShare.None),
				ExpectedChunks = msg.totalChunks,
				ReceivedChunks = new HashSet<int>(),
				LastActivityTime = Time.realtimeSinceStartup
			};
			activeDownloads[msg.trackId] = value;
		}
		value.Stream.Seek((long)msg.chunkIndex * 8192L, SeekOrigin.Begin);
		value.Stream.Write(msg.data, 0, msg.data.Length);
		value.ReceivedChunks.Add(msg.chunkIndex);
		value.LastActivityTime = Time.realtimeSinceStartup;
		if (value.ReceivedChunks.Count >= value.ExpectedChunks)
		{
			value.Stream.Dispose();
			activeDownloads.Remove(msg.trackId);
			audio.PlayLocalFile(value.TempPath);
		}
	}

	private void OnClientReceiveControl(MusicControlBroadcast msg, Channel channel)
	{
		if (!(Time.realtimeSinceStartup - Plugin.LocalIgnoreNetworkTime < 0.8f))
		{
			audio.ApplyControlState(msg.isPaused, msg.timePosition);
		}
	}

	private void OnClientReceiveVolume(MusicVolumeBroadcast msg, Channel channel)
	{
		if (!(Time.realtimeSinceStartup - Plugin.LocalIgnoreNetworkTime < 0.8f))
		{
			audio.ApplyVolume(msg.volume);
		}
	}

	public void ProcessTimeouts()
	{
		if (activeDownloads.Count == 0)
		{
			return;
		}
		List<int> list = null;
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		foreach (KeyValuePair<int, DownloadContext> activeDownload in activeDownloads)
		{
			if (realtimeSinceStartup - activeDownload.Value.LastActivityTime > 120f)
			{
				if (list == null)
				{
					list = new List<int>();
				}
				list.Add(activeDownload.Key);
			}
		}
		if (list == null)
		{
			return;
		}
		foreach (int item in list)
		{
			DownloadContext downloadContext = activeDownloads[item];
			downloadContext.Stream.Dispose();
			if (File.Exists(downloadContext.TempPath))
			{
				File.Delete(downloadContext.TempPath);
			}
			activeDownloads.Remove(item);
		}
	}
}
public class CustomRadioUI
{
	private Plugin plugin;

	private CustomRadioNetworkService network;

	private CustomRadioAudioController audio;

	private bool showUI;

	private bool isDialogOpen;

	private ConcurrentQueue<string> pendingFiles = new ConcurrentQueue<string>();

	private float lastSeekSendTime;

	private float lastVolumeSendTime;

	private GUIStyle windowStyle;

	private GUIStyle btnStyle;

	private GUIStyle labelStyle;

	private GUIStyle sliderTrackStyle;

	private GUIStyle sliderThumbStyle;

	private bool stylesInitialized;

	public CustomRadioUI(Plugin plugin, CustomRadioNetworkService network, CustomRadioAudioController audio)
	{
		this.plugin = plugin;
		this.network = network;
		this.audio = audio;
	}

	private void InitStyles()
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Expected O, but got Unknown
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Expected O, but got Unknown
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: 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_0167: Expected O, but got Unknown
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Expected O, but got Unknown
		//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_020a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: Expected O, but got Unknown
		//IL_0236: 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)
		if (!stylesInitialized)
		{
			windowStyle = new GUIStyle(GUI.skin.box);
			windowStyle.normal.background = MakeTex(2, 2, new Color(0.08f, 0.08f, 0.08f, 0.95f));
			windowStyle.normal.textColor = Color.white;
			windowStyle.alignment = (TextAnchor)1;
			windowStyle.fontStyle = (FontStyle)1;
			windowStyle.fontSize = 14;
			btnStyle = new GUIStyle(GUI.skin.button);
			btnStyle.normal.background = MakeTex(2, 2, new Color(0.18f, 0.18f, 0.18f, 1f));
			btnStyle.hover.background = MakeTex(2, 2, new Color(0.35f, 0.35f, 0.35f, 1f));
			btnStyle.active.background = MakeTex(2, 2, new Color(0.5f, 0.5f, 0.5f, 1f));
			btnStyle.normal.textColor = Color.white;
			btnStyle.fontStyle = (FontStyle)1;
			labelStyle = new GUIStyle(GUI.skin.label);
			labelStyle.normal.textColor = new Color(0.85f, 0.85f, 0.85f, 1f);
			labelStyle.alignment = (TextAnchor)4;
			labelStyle.fontSize = 13;
			sliderTrackStyle = new GUIStyle(GUI.skin.horizontalSlider);
			sliderTrackStyle.normal.background = MakeTex(2, 2, new Color(0.2f, 0.2f, 0.2f, 1f));
			sliderTrackStyle.fixedHeight = 6f;
			sliderThumbStyle = new GUIStyle(GUI.skin.horizontalSliderThumb);
			sliderThumbStyle.normal.background = MakeTex(2, 2, new Color(0.8f, 0.8f, 0.8f, 1f));
			sliderThumbStyle.hover.background = MakeTex(2, 2, Color.white);
			sliderThumbStyle.fixedWidth = 14f;
			sliderThumbStyle.fixedHeight = 14f;
			stylesInitialized = true;
		}
	}

	private Texture2D MakeTex(int width, int height, Color col)
	{
		//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_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Expected O, but got Unknown
		Color[] array = (Color[])(object)new Color[width * height];
		for (int i = 0; i < array.Length; i++)
		{
			array[i] = col;
		}
		Texture2D val = new Texture2D(width, height);
		val.SetPixels(array);
		val.Apply();
		return val;
	}

	public void HandleInput()
	{
		if (Input.GetKeyDown((KeyCode)121))
		{
			showUI = !showUI;
			audio.EnsureRadioExists();
		}
		if (pendingFiles.TryDequeue(out var result))
		{
			network.SendFile(result);
		}
	}

	public void DrawUI()
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		//IL_020e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0275: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0337: Unknown result type (might be due to invalid IL or missing references)
		if (!showUI)
		{
			return;
		}
		InitStyles();
		GUI.Box(new Rect(20f, 20f, 320f, 200f), "\nC U S T O M   R A D I O", windowStyle);
		if (GUI.Button(new Rect(40f, 55f, 280f, 25f), "Загрузить MP3", btnStyle))
		{
			OpenWindowsExplorerSafe();
		}
		AudioSource source = audio.Source;
		if (!((Object)(object)source != (Object)null) || !((Object)(object)source.clip != (Object)null))
		{
			return;
		}
		string text = FormatTime(source.time) + "  /  " + FormatTime(source.clip.length);
		GUI.Label(new Rect(40f, 85f, 280f, 20f), text, labelStyle);
		GUI.changed = false;
		float time = GUI.HorizontalSlider(new Rect(40f, 105f, 280f, 15f), source.time, 0f, source.clip.length, sliderTrackStyle, sliderThumbStyle);
		if (GUI.changed)
		{
			source.time = time;
			Plugin.LocalIgnoreNetworkTime = Time.realtimeSinceStartup;
			if (Time.realtimeSinceStartup - lastSeekSendTime > 0.1f)
			{
				lastSeekSendTime = Time.realtimeSinceStartup;
				network.SendControl(audio.IsPaused, time);
			}
		}
		if (GUI.Button(new Rect(100f, 130f, 45f, 25f), "<<", btnStyle))
		{
			float time2 = (source.time = Mathf.Max(0f, source.time - 15f));
			Plugin.LocalIgnoreNetworkTime = Time.realtimeSinceStartup;
			network.SendControl(audio.IsPaused, time2);
		}
		string text2 = (audio.IsPaused ? "Play" : "Pause");
		if (GUI.Button(new Rect(155f, 130f, 50f, 25f), text2, btnStyle))
		{
			bool flag = !audio.IsPaused;
			audio.ApplyControlState(flag, source.time);
			Plugin.LocalIgnoreNetworkTime = Time.realtimeSinceStartup;
			network.SendControl(flag, source.time);
		}
		if (GUI.Button(new Rect(215f, 130f, 45f, 25f), ">>", btnStyle))
		{
			float time3 = (source.time = Mathf.Min(source.clip.length, source.time + 15f));
			Plugin.LocalIgnoreNetworkTime = Time.realtimeSinceStartup;
			network.SendControl(audio.IsPaused, time3);
		}
		GUI.Label(new Rect(40f, 165f, 70f, 20f), $"Vol: {Mathf.RoundToInt(audio.CurrentVolume * 100f)}%", labelStyle);
		GUI.changed = false;
		float vol = GUI.HorizontalSlider(new Rect(110f, 170f, 210f, 15f), audio.CurrentVolume, 0f, 1f, sliderTrackStyle, sliderThumbStyle);
		if (GUI.changed)
		{
			audio.ApplyVolume(vol);
			Plugin.LocalIgnoreNetworkTime = Time.realtimeSinceStartup;
			if (Time.realtimeSinceStartup - lastVolumeSendTime > 0.1f)
			{
				lastVolumeSendTime = Time.realtimeSinceStartup;
				network.SendVolume(vol);
			}
		}
	}

	private string FormatTime(float timeInSeconds)
	{
		int num = Mathf.FloorToInt(timeInSeconds / 60f);
		int num2 = Mathf.FloorToInt(timeInSeconds % 60f);
		return $"{num:00}:{num2:00}";
	}

	private void OpenWindowsExplorerSafe()
	{
		if (isDialogOpen)
		{
			return;
		}
		isDialogOpen = true;
		new Thread((ThreadStart)delegate
		{
			OpenFileName openFileName = new OpenFileName();
			openFileName.structSize = Marshal.SizeOf(openFileName);
			openFileName.filter = "MP3 Files (*.mp3)\0*.mp3\0";
			openFileName.file = new string(new char[1024]);
			openFileName.maxFile = openFileName.file.Length;
			openFileName.title = "Выберите песню для радио";
			openFileName.flags = 528392;
			if (LocalDialog.GetOpenFileName(openFileName))
			{
				pendingFiles.Enqueue(openFileName.file.TrimEnd(new char[1]));
			}
			isDialogOpen = false;
		}).Start();
	}
}