Files
2026-02-21 16:45:37 +08:00

516 lines
13 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text.RegularExpressions;
using Crosstales.Radio.Model;
using Crosstales.Radio.Model.Enum;
using UnityEngine;
namespace Crosstales.Radio.Util
{
public static class Helper
{
private static readonly Regex lineEndingsRegex = new Regex("\\r\\n|\\r|\\n");
private static readonly int[] mp3Bitrates = new int[14]
{
32, 40, 48, 56, 64, 80, 96, 112, 128, 160,
192, 224, 256, 320
};
private static readonly int[] oggBitrates = new int[14]
{
32, 45, 48, 64, 80, 96, 112, 128, 160, 192,
224, 256, 320, 500
};
private const string file_prefix = "file://";
public static bool isInternetAvailable
{
get
{
return Application.internetReachability != NetworkReachability.NotReachable;
}
}
public static bool isWindowsPlatform
{
get
{
return Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsEditor;
}
}
public static bool isMacOSPlatform
{
get
{
return Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.OSXEditor;
}
}
public static bool isLinuxPlatform
{
get
{
return Application.platform == RuntimePlatform.LinuxPlayer || Application.platform == RuntimePlatform.LinuxEditor;
}
}
public static bool isStandalonePlatform
{
get
{
return isWindowsPlatform || isMacOSPlatform || isLinuxPlatform;
}
}
public static bool isAndroidPlatform
{
get
{
return Application.platform == RuntimePlatform.Android;
}
}
public static bool isIOSPlatform
{
get
{
return Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.tvOS;
}
}
public static bool isWSAPlatform
{
get
{
return Application.platform == RuntimePlatform.MetroPlayerARM || Application.platform == RuntimePlatform.MetroPlayerX86 || Application.platform == RuntimePlatform.MetroPlayerX64 || Application.platform == RuntimePlatform.XboxOne;
}
}
public static bool isWebGLPlatform
{
get
{
return Application.platform == RuntimePlatform.WebGLPlayer;
}
}
public static bool isWebPlayerPlatform
{
get
{
return false;
}
}
public static bool isWebPlatform
{
get
{
return isWebPlayerPlatform || isWebGLPlatform;
}
}
public static bool isWindowsBasedPlatform
{
get
{
return isWindowsPlatform || isWSAPlatform;
}
}
public static bool isAppleBasedPlatform
{
get
{
return isMacOSPlatform || isIOSPlatform;
}
}
public static bool isEditor
{
get
{
return Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.LinuxEditor;
}
}
public static bool isEditorMode
{
get
{
return isEditor && !Application.isPlaying;
}
}
public static bool isSupportedPlatform
{
get
{
return true;
}
}
public static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
bool result = true;
if (sslPolicyErrors != SslPolicyErrors.None)
{
for (int i = 0; i < chain.ChainStatus.Length; i++)
{
if (chain.ChainStatus[i].Status != X509ChainStatusFlags.RevocationStatusUnknown)
{
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags;
result = chain.Build((X509Certificate2)certificate);
}
}
}
return result;
}
public static bool isSane(ref RadioStation station)
{
if (station == null)
{
Debug.LogError("'Station' is null!" + Environment.NewLine + "Add a valid station to the player.");
return false;
}
if (string.IsNullOrEmpty(station.Url))
{
Debug.LogError(string.Concat(station, Environment.NewLine, "'Url' is null or empty!", Environment.NewLine, "Cannot start playback -> please add a valid url of a radio station (see 'Radios.txt' for some examples)."));
return false;
}
if (!isValidURL(station.Url))
{
Debug.LogError(string.Concat(station, Environment.NewLine, "'Url' is not valid!", Environment.NewLine, "Cannot start playback -> please add a valid url of a radio station (see 'Radios.txt' for some examples)."));
return false;
}
if (!isValidFormat(station.Format))
{
Debug.LogError(string.Concat(station, Environment.NewLine, "'Format' is invalid: '", station.Format, "'", Environment.NewLine, "Cannot start playback -> please add a valid audio format for a radio station (see 'Radios.txt' for some examples)."));
return false;
}
if (!isValidBitrate(station.Bitrate, station.Format))
{
Debug.LogWarning(string.Concat(station, Environment.NewLine, "'Bitrate' is invalid: ", station.Bitrate, Environment.NewLine, "Autmatically using ", Config.DEFAULT_BITRATE, " kbit/s for playback."));
station.Bitrate = Config.DEFAULT_BITRATE;
}
if (station.ChunkSize < 1)
{
Debug.LogWarning(string.Concat(station, Environment.NewLine, "'ChunkSize' is smaller than 1KB!", Environment.NewLine, "Autmatically using ", Config.DEFAULT_CHUNKSIZE, "KB for playback."));
station.ChunkSize = Config.DEFAULT_CHUNKSIZE;
}
if (station.Format == AudioFormat.MP3)
{
if (station.BufferSize < Config.DEFAULT_BUFFERSIZE / 4)
{
Debug.LogWarning(string.Concat(station, Environment.NewLine, "'BufferSize' is smaller than DEFAULT_BUFFERSIZE/4!", Environment.NewLine, "Autmatically using ", Config.DEFAULT_BUFFERSIZE / 4, "KB for playback."));
station.BufferSize = Config.DEFAULT_BUFFERSIZE / 4;
}
}
else if (station.BufferSize < 64)
{
station.BufferSize = 64;
}
if (station.BufferSize < station.ChunkSize)
{
Debug.LogWarning(string.Concat(station, Environment.NewLine, "'BufferSize' is smaller than 'ChunkSize'!", Environment.NewLine, "Autmatically using ", station.ChunkSize, "KB for playback."));
station.BufferSize = station.ChunkSize;
}
return true;
}
public static string ValidatePath(string path)
{
if (!string.IsNullOrEmpty(path))
{
string text = path.Trim();
string text2 = null;
if (isWindowsPlatform)
{
text2 = text.Replace('/', '\\');
if (!text2.EndsWith("\\"))
{
text2 += "\\";
}
}
else
{
text2 = text.Replace('\\', '/');
if (!text2.EndsWith("/"))
{
text2 += "/";
}
}
return string.Join("_", text2.Split(Path.GetInvalidPathChars()));
}
return path;
}
public static string ValidateFile(string path)
{
if (!string.IsNullOrEmpty(path))
{
string text = ValidatePath(path);
if (text.EndsWith("\\") || text.EndsWith("/"))
{
text = text.Substring(0, text.Length - 1);
}
string text2 = text.Substring((!isWindowsBasedPlatform) ? (text.LastIndexOf("/") + 1) : (text.LastIndexOf("\\") + 1));
string text3 = string.Join(string.Empty, text2.Split(Path.GetInvalidFileNameChars()));
return text.Substring(0, text.Length - text2.Length) + text3;
}
return path;
}
public static string CleanUrl(string url, bool removeProtocol = true, bool removeWWW = true, bool removeSlash = true)
{
string text = url.Trim();
if (!string.IsNullOrEmpty(url))
{
if (removeProtocol)
{
text = text.Substring(text.IndexOf("//") + 2);
}
if (removeProtocol)
{
text = text.CTReplace("www.", string.Empty);
}
if (removeSlash && text.EndsWith("/"))
{
text = text.Substring(0, text.Length - 1);
}
}
return text;
}
public static List<string> SplitStringToLines(string text, bool ignoreCommentedLines = true, int skipHeaderLines = 0, int skipFooterLines = 0)
{
List<string> list = new List<string>(100);
if (string.IsNullOrEmpty(text))
{
Debug.LogWarning("Parameter 'text' is null or empty!" + Environment.NewLine + "=> 'SplitStringToLines()' will return an empty string list.");
}
else
{
string[] array = lineEndingsRegex.Split(text);
for (int i = 0; i < array.Length; i++)
{
if (i + 1 <= skipHeaderLines || i >= array.Length - skipFooterLines || string.IsNullOrEmpty(array[i]))
{
continue;
}
if (ignoreCommentedLines)
{
if (!array[i].StartsWith("#", StringComparison.OrdinalIgnoreCase))
{
list.Add(array[i]);
}
}
else
{
list.Add(array[i]);
}
}
}
return list;
}
public static string FormatBytesToHRF(long bytes)
{
string[] array = new string[5] { "B", "KB", "MB", "GB", "TB" };
double num = bytes;
int num2 = 0;
while (num >= 1024.0 && num2 < array.Length - 1)
{
num2++;
num /= 1024.0;
}
return string.Format("{0:0.##} {1}", num, array[num2]);
}
public static string FormatSecondsToHourMinSec(double seconds)
{
int num = (int)seconds;
int num2 = num % 60;
if (seconds >= 3600.0)
{
int num3 = num / 3600;
int num4 = (num - num3 * 3600) / 60;
return num3 + ":" + ((num4 >= 10) ? num4.ToString() : ("0" + num4)) + ":" + ((num2 >= 10) ? num2.ToString() : ("0" + num2));
}
int num5 = num / 60;
return num5 + ":" + ((num2 >= 10) ? num2.ToString() : ("0" + num2));
}
public static float[] ConvertByteArrayToFloatArray(byte[] bytes, int count)
{
float[] array = new float[count / 2];
int num = 0;
for (int i = 0; i < count; i += 2)
{
array[num] = bytesToFloat(bytes[i], bytes[i + 1]);
num++;
}
return array;
}
public static byte[] ConvertFloatArrayToByteArray(float[] floats, int count)
{
byte[] array = new byte[count * 2];
int num = 0;
int num2 = 0;
while (num < count)
{
short num3 = (short)(floats[num] * 32767f);
array[num2] = (byte)(num3 & 0xFF);
array[num2 + 1] = (byte)((num3 >> 8) & 0xFF);
num++;
num2 += 2;
}
return array;
}
public static Color HSVToRGB(float h, float s, float v, float a = 1f)
{
if (s == 0f)
{
return new Color(v, v, v, a);
}
h /= 60f;
int num = Mathf.FloorToInt(h);
float num2 = h - (float)num;
float num3 = v * (1f - s);
float num4 = v * (1f - s * num2);
float num5 = v * (1f - s * (1f - num2));
switch (num)
{
case 0:
return new Color(v, num5, num3, a);
case 1:
return new Color(num4, v, num3, a);
case 2:
return new Color(num3, v, num5, a);
case 3:
return new Color(num3, num4, v, a);
case 4:
return new Color(num5, num3, v, a);
default:
return new Color(v, num3, num4, a);
}
}
public static AudioFormat AudioFormatFromString(string format)
{
AudioFormat result = AudioFormat.MP3;
if (!string.IsNullOrEmpty(format) && format.CTEquals("ogg"))
{
result = AudioFormat.OGG;
}
return result;
}
public static AudioCodec AudioCodecFromString(string codec)
{
AudioCodec result = AudioCodec.None;
if (!string.IsNullOrEmpty(codec))
{
if (codec.CTEquals("MP3_NLayer"))
{
result = AudioCodec.MP3_NLayer;
}
else if (codec.CTEquals("MP3_NAudio"))
{
result = AudioCodec.MP3_NAudio;
}
else if (codec.CTEquals("OGG_NVorbis"))
{
result = AudioCodec.OGG_NVorbis;
}
}
return result;
}
public static AudioCodec AudioCodecForAudioFormat(AudioFormat format)
{
switch (format)
{
case AudioFormat.MP3:
if (isWindowsPlatform)
{
return Constants.DEFAULT_CODEC_MP3_WINDOWS;
}
return Constants.DEFAULT_CODEC_MP3;
case AudioFormat.OGG:
return AudioCodec.OGG_NVorbis;
default:
return AudioCodec.None;
}
}
public static bool isValidFormat(AudioFormat format)
{
return format == AudioFormat.MP3 || format == AudioFormat.OGG;
}
public static int NearestBitrate(int bitrate, AudioFormat format)
{
int num = 128;
if (format == AudioFormat.MP3)
{
return NearestMP3Bitrate(bitrate);
}
return NearestOGGBitrate(bitrate);
}
public static int NearestMP3Bitrate(int bitrate)
{
return mp3Bitrates.Aggregate((int x, int y) => (Math.Abs(x - bitrate) >= Math.Abs(y - bitrate)) ? y : x);
}
public static int NearestOGGBitrate(int bitrate)
{
return oggBitrates.Aggregate((int x, int y) => (Math.Abs(x - bitrate) >= Math.Abs(y - bitrate)) ? y : x);
}
public static bool isValidBitrate(int bitrate, AudioFormat format)
{
bool flag = false;
if (format == AudioFormat.MP3)
{
return isValidMP3Bitrate(bitrate);
}
return isValidOGGBitrate(bitrate);
}
public static bool isValidMP3Bitrate(int bitrate)
{
return mp3Bitrates.Contains(bitrate);
}
public static bool isValidOGGBitrate(int bitrate)
{
return oggBitrates.Contains(bitrate);
}
public static bool isValidURL(string url)
{
return !string.IsNullOrEmpty(url) && (url.StartsWith("file://", StringComparison.OrdinalIgnoreCase) || url.StartsWith(Constants.PREFIX_HTTP, StringComparison.OrdinalIgnoreCase) || url.StartsWith(Constants.PREFIX_HTTPS, StringComparison.OrdinalIgnoreCase));
}
private static float bytesToFloat(byte firstByte, byte secondByte)
{
return (float)(short)((secondByte << 8) | firstByte) / 32768f;
}
}
}