using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BetterMediaControls.audio;
using BetterMediaControls.patches;
using BetterMediaControls.util;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BetterMediaControls")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.2.0")]
[assembly: AssemblyInformationalVersion("1.1.2+69a1d6ea6a4b377b112daf6e92964b74cc53e464")]
[assembly: AssemblyProduct("Better Media Controls")]
[assembly: AssemblyTitle("BetterMediaControls")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.2.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 BetterMediaControls
{
[BepInPlugin("com.patty.bettermediacontrols", "BetterMediaControls", "1.1.2")]
[BepInProcess("OnTogether.exe")]
public class Plugin : BaseUnityPlugin
{
private const string PluginGUID = "com.patty.bettermediacontrols";
private const string PluginName = "BetterMediaControls";
private const string PluginVersion = "1.1.2";
private const string PluginAuthor = "CutiePatooties";
private readonly Harmony _harmony = new Harmony("com.patty.bettermediacontrols");
private ConfigEntry<string> _configMusicDir;
private ConfigEntry<bool> _configVanillaMusicEnabled;
private ConfigEntry<bool> _configShuffleEnabled;
public static Plugin Instance { get; private set; }
public bool IsVanillaMusicEnabled => _configVanillaMusicEnabled.Value;
public bool IsShuffleEnabled => _configShuffleEnabled.Value;
public static ManualLogSource Log { get; private set; }
public Sprite ShuffleOnSprite { get; private set; }
public Sprite ShuffleOffSprite { get; private set; }
private void Awake()
{
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
_configMusicDir = ((BaseUnityPlugin)this).Config.Bind<string>("General", "MusicDirectory", Path.Combine(Paths.ConfigPath, "BetterMediaControls-Music"), "Supports .wav, .ogg, and .mp3 files. Directory inside the plugin folder where custom music is stored.");
_configVanillaMusicEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableVanillaMusic", true, "If true, the game's original music will still show up alongside custom tracks.");
_configShuffleEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Playback", "EnableShuffle", false, "self explanatory. uses spotify shuffle (Fisher–Yates) algorithm.");
string path = Path.Combine(Paths.PluginPath, "CutiePatooties-BetterMediaControls", "BetterMediaControls", "icons");
ShuffleOnSprite = SpriteLoader.LoadSprite(Path.Combine(path, "Shuffle.png"));
ShuffleOffSprite = SpriteLoader.LoadSprite(Path.Combine(path, "ShuffleUnchecked.png"));
if ((Object)(object)ShuffleOnSprite == (Object)null || (Object)(object)ShuffleOffSprite == (Object)null)
{
Log.LogWarning((object)"Shuffle icons missing or failed to load");
}
string musicDirectory = GetMusicDirectory();
if (!Directory.Exists(musicDirectory))
{
try
{
Directory.CreateDirectory(musicDirectory);
Log.LogInfo((object)("Created music directory at " + musicDirectory));
}
catch (Exception arg)
{
Log.LogError((object)$"Failed to create music directory at {musicDirectory}: {arg}");
}
}
string text = Path.Combine(musicDirectory, "playlist.json");
if (!File.Exists(text))
{
try
{
File.WriteAllText(text, "{\"playlist\":[]}");
Log.LogInfo((object)("Created empty playlist.json at " + text));
}
catch (Exception arg2)
{
Log.LogError((object)$"Failed to create playlist.json at {text}: {arg2}");
}
}
((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin com.patty.bettermediacontrols is loaded!");
_harmony.PatchAll();
}
public void ToggleShuffle()
{
_configShuffleEnabled.Value = !_configShuffleEnabled.Value;
if (_configShuffleEnabled.Value)
{
ShufflePatch.ResetShuffle();
}
Log.LogInfo((object)("Shuffle " + (IsShuffleEnabled ? "enabled" : "disabled")));
}
public string GetMusicDirectory()
{
string value = _configMusicDir.Value;
value = Environment.ExpandEnvironmentVariables(value);
if (Path.IsPathRooted(value))
{
return value;
}
return Path.Combine(Paths.ConfigPath, "BetterMediaControls-Music");
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "BetterMediaControls";
public const string PLUGIN_NAME = "Better Media Controls";
public const string PLUGIN_VERSION = "1.1.2";
}
}
namespace BetterMediaControls.util
{
public static class ReflectionUtils
{
public static object GetField(object instance, string fieldName)
{
if (instance != null)
{
return AccessTools.Field(instance.GetType(), fieldName)?.GetValue(instance);
}
return null;
}
public static T GetField<T>(object instance, string fieldName) where T : class
{
return GetField(instance, fieldName) as T;
}
}
public static class SpriteLoader
{
public static Sprite LoadSprite(string path)
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
if (!File.Exists(path))
{
Plugin.Log.LogWarning((object)("Sprite not found: " + path));
return null;
}
byte[] array = File.ReadAllBytes(path);
Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
if (!ImageConversion.LoadImage(val, array))
{
Plugin.Log.LogError((object)("Failed to load image: " + path));
return null;
}
((Texture)val).filterMode = (FilterMode)1;
((Texture)val).wrapMode = (TextureWrapMode)1;
return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
}
}
}
namespace BetterMediaControls.patches
{
[HarmonyPatch(typeof(SoundManager))]
public static class MediaPatch
{
[CompilerGenerated]
private sealed class <>c__DisplayClass1_0
{
public AudioClip clip;
internal void <InjectSong>b__0(AudioClip c)
{
clip = c;
}
}
[CompilerGenerated]
private sealed class <>c__DisplayClass1_1
{
public AudioClip clip;
internal void <InjectSong>b__1(AudioClip c)
{
clip = c;
}
}
[CompilerGenerated]
private sealed class <InjectSong>d__1 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public SoundManager soundManager;
private <>c__DisplayClass1_0 <>8__1;
private <>c__DisplayClass1_1 <>8__2;
private ManualLogSource <log>5__2;
private string <musicDir>5__3;
private PlaylistFile <playlistFile>5__4;
private IList <songs>5__5;
private int <i>5__6;
private PlaylistEntry <entry>5__7;
private string <audioPath>5__8;
private string[] <files>5__9;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <InjectSong>d__1(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>8__1 = null;
<>8__2 = null;
<log>5__2 = null;
<musicDir>5__3 = null;
<playlistFile>5__4 = null;
<songs>5__5 = null;
<entry>5__7 = null;
<audioPath>5__8 = null;
<files>5__9 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
//IL_04bf: Unknown result type (might be due to invalid IL or missing references)
//IL_04d0: Unknown result type (might be due to invalid IL or missing references)
//IL_04db: Unknown result type (might be due to invalid IL or missing references)
//IL_04ec: Unknown result type (might be due to invalid IL or missing references)
//IL_04f9: Expected O, but got Unknown
//IL_0324: Unknown result type (might be due to invalid IL or missing references)
//IL_034e: Unknown result type (might be due to invalid IL or missing references)
//IL_035f: Unknown result type (might be due to invalid IL or missing references)
//IL_038b: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
{
<>1__state = -1;
<log>5__2 = Plugin.Log;
if (!Object.op_Implicit((Object)(object)Plugin.Instance))
{
<log>5__2.LogError((object)"Plugin instance is null");
return false;
}
<musicDir>5__3 = Plugin.Instance.GetMusicDirectory();
string text = Path.Combine(<musicDir>5__3, "playlist.json");
<playlistFile>5__4 = null;
bool flag = File.Exists(text);
if (!flag)
{
<log>5__2.LogWarning((object)("No playlist.json found at " + text + ", falling back to directory scan"));
}
else
{
try
{
string text2 = File.ReadAllText(text);
<playlistFile>5__4 = JsonConvert.DeserializeObject<PlaylistFile>(text2);
if (<playlistFile>5__4?.Playlist == null)
{
<log>5__2.LogError((object)"playlist.json parsed, but playlist is null");
return false;
}
<log>5__2.LogDebug((object)$"Parsed playlist.json with {<playlistFile>5__4.Playlist.Count} entries");
}
catch (Exception arg)
{
<log>5__2.LogError((object)$"Failed to parse playlist.json: {arg}");
return false;
}
}
object field = ReflectionUtils.GetField(soundManager, "_mixtapes");
if (field == null)
{
<log>5__2.LogError((object)"_mixtapes is null");
return false;
}
IList field2 = ReflectionUtils.GetField<IList>(field, "MixTapes");
if (field2 == null || field2.Count == 0)
{
<log>5__2.LogError((object)"MixTapes is null or empty");
return false;
}
object instance = field2[0];
<songs>5__5 = ReflectionUtils.GetField<IList>(instance, "Songs");
if (<songs>5__5 == null)
{
<log>5__2.LogError((object)"Songs is null");
return false;
}
if (!Plugin.Instance.IsVanillaMusicEnabled)
{
<songs>5__5.Clear();
}
if (flag)
{
<i>5__6 = <playlistFile>5__4.Playlist.Count - 1;
goto IL_03e8;
}
<files>5__9 = Directory.GetFiles(<musicDir>5__3);
<i>5__6 = <files>5__9.Length - 1;
goto IL_0543;
}
case 1:
<>1__state = -1;
if (!Object.op_Implicit((Object)(object)<>8__1.clip))
{
<log>5__2.LogError((object)("Failed to load audio: " + <audioPath>5__8));
}
else
{
Song val2 = new Song
{
Title = (string.IsNullOrEmpty(<entry>5__7.Title) ? Path.GetFileNameWithoutExtension(<entry>5__7.File) : <entry>5__7.Title),
Artist = (string.IsNullOrEmpty(<entry>5__7.Artist) ? "Unknown" : <entry>5__7.Artist),
Music = <>8__1.clip,
Volume = ((<entry>5__7.Volume > 0f) ? <entry>5__7.Volume : 1f)
};
<songs>5__5.Insert(0, val2);
<log>5__2.LogDebug((object)("Added song: " + val2.Title + " by " + val2.Artist));
<>8__1 = null;
<entry>5__7 = null;
<audioPath>5__8 = null;
}
goto IL_03d6;
case 2:
{
<>1__state = -1;
if (!Object.op_Implicit((Object)(object)<>8__2.clip))
{
<log>5__2.LogError((object)("Failed to load audio: " + <audioPath>5__8));
}
else
{
Song val = new Song
{
Title = Path.GetFileNameWithoutExtension(<audioPath>5__8),
Artist = "Unknown",
Music = <>8__2.clip,
Volume = 0.5f
};
<songs>5__5.Insert(0, val);
<log>5__2.LogDebug((object)("Added fallback song: " + val.Title));
<>8__2 = null;
<audioPath>5__8 = null;
}
goto IL_0531;
}
IL_0531:
<i>5__6--;
goto IL_0543;
IL_03d6:
<i>5__6--;
goto IL_03e8;
IL_0543:
if (<i>5__6 >= 0)
{
<>8__2 = new <>c__DisplayClass1_1();
<audioPath>5__8 = <files>5__9[<i>5__6];
if (AudioLoader.IsSupportedFile(<audioPath>5__8))
{
<>8__2.clip = null;
<>2__current = AudioLoader.LoadAudio(<audioPath>5__8, delegate(AudioClip c)
{
<>8__2.clip = c;
});
<>1__state = 2;
return true;
}
goto IL_0531;
}
<files>5__9 = null;
break;
IL_03e8:
if (<i>5__6 < 0)
{
break;
}
<>8__1 = new <>c__DisplayClass1_0();
<entry>5__7 = <playlistFile>5__4.Playlist[<i>5__6];
<audioPath>5__8 = Path.Combine(<musicDir>5__3, <entry>5__7.File);
if (!File.Exists(<audioPath>5__8))
{
<log>5__2.LogError((object)("Missing audio file: " + <audioPath>5__8));
goto IL_03d6;
}
<log>5__2.LogDebug((object)("Loading song: " + <audioPath>5__8));
<>8__1.clip = null;
<>2__current = AudioLoader.LoadAudio(<audioPath>5__8, delegate(AudioClip c)
{
<>8__1.clip = c;
});
<>1__state = 1;
return true;
}
<log>5__2.LogInfo((object)$"Final song count: {<songs>5__5.Count}");
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[HarmonyPatch("Start")]
public static void Postfix(SoundManager __instance)
{
((MonoBehaviour)__instance).StartCoroutine(InjectSong(__instance));
}
[IteratorStateMachine(typeof(<InjectSong>d__1))]
private static IEnumerator InjectSong(SoundManager soundManager)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <InjectSong>d__1(0)
{
soundManager = soundManager
};
}
}
[HarmonyPatch(typeof(SoundManager), "ChangeSong")]
[HarmonyPatch(new Type[] { typeof(bool) })]
public static class ShufflePatch
{
private static readonly List<int> ShuffledOrder = new List<int>();
private static int _shufflePosition;
private static int _lastMixtapeIndex = -1;
private static readonly MethodInfo ChangeSongClipMethod = AccessTools.Method(typeof(SoundManager), "ChangeSongClip", (Type[])null, (Type[])null);
private static void Shuffle(List<int> list)
{
for (int num = list.Count - 1; num > 0; num--)
{
int num2 = Random.Range(0, num + 1);
int index = num;
int index2 = num2;
int value = list[num2];
int value2 = list[num];
list[index] = value;
list[index2] = value2;
}
}
[HarmonyPrefix]
public static bool Prefix(SoundManager __instance, bool isNext)
{
//IL_018a: Unknown result type (might be due to invalid IL or missing references)
//IL_0194: Expected O, but got Unknown
if (!Plugin.Instance.IsShuffleEnabled)
{
return true;
}
IList field = ReflectionUtils.GetField<IList>(ReflectionUtils.GetField(__instance, "_mixtapes"), "MixTapes");
if (field == null || field.Count == 0)
{
return true;
}
int num = (int)ReflectionUtils.GetField(__instance, "_mixtapeIndex");
int item = (int)ReflectionUtils.GetField(__instance, "_songIndex");
if (num != _lastMixtapeIndex)
{
ShuffledOrder.Clear();
_shufflePosition = 0;
_lastMixtapeIndex = num;
}
IList field2 = ReflectionUtils.GetField<IList>(field[num], "Songs");
if (field2 == null || field2.Count == 0)
{
return true;
}
if (ShuffledOrder.Count != field2.Count)
{
ShuffledOrder.Clear();
for (int i = 0; i < field2.Count; i++)
{
ShuffledOrder.Add(i);
}
Shuffle(ShuffledOrder);
_shufflePosition = ShuffledOrder.IndexOf(item);
if (_shufflePosition < 0)
{
_shufflePosition = 0;
}
}
if (isNext)
{
_shufflePosition++;
if (_shufflePosition >= ShuffledOrder.Count)
{
_shufflePosition = 0;
}
}
else
{
_shufflePosition--;
if (_shufflePosition < 0)
{
_shufflePosition = ShuffledOrder.Count - 1;
}
}
int num2 = ShuffledOrder[_shufflePosition];
AccessTools.Field(((object)__instance).GetType(), "_songIndex").SetValue(__instance, num2);
ChangeSongClipMethod.Invoke(__instance, null);
MonoSingleton<UIManager>.I.UpdateSongInfo((Song)field2[num2]);
return false;
}
public static void ResetShuffle()
{
ShuffledOrder.Clear();
_shufflePosition = 0;
}
}
}
namespace BetterMediaControls.patches.ui
{
[HarmonyPatch(typeof(UIManager), "Start")]
public static class ShuffleUIPatch
{
[HarmonyPostfix]
public static void Postfix(UIManager __instance)
{
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00c9: Expected O, but got Unknown
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Expected O, but got Unknown
ManualLogSource log = Plugin.Log;
Image field = ReflectionUtils.GetField<Image>(__instance, "_loopImage");
if ((Object)(object)field == (Object)null)
{
log.LogError((object)"Shuffle UI: _loopImage not found");
return;
}
GameObject gameObject = ((Component)field).gameObject;
GameObject val = Object.Instantiate<GameObject>(gameObject, gameObject.transform.parent);
((Object)val).name = "Button_Shuffle";
Transform transform = val.transform;
transform.localPosition += new Vector3(60f, 0f, 0f);
Image shuffleImage = val.GetComponent<Image>();
Button component = val.GetComponent<Button>();
if ((Object)(object)component == (Object)null || (Object)(object)shuffleImage == (Object)null)
{
log.LogError((object)"Shuffle UI: missing Image or Button component");
return;
}
component.onClick = new ButtonClickedEvent();
((UnityEvent)component.onClick).AddListener((UnityAction)delegate
{
Plugin.Instance.ToggleShuffle();
UpdateShuffleUI(__instance, shuffleImage);
MonoSingleton<SFXManager>.I.PlayUIClick();
});
UpdateShuffleUI(__instance, shuffleImage);
log.LogInfo((object)"Shuffle button cloned from loop button");
}
private static void UpdateShuffleUI(UIManager uiManager, Image shuffleImage)
{
bool isShuffleEnabled = Plugin.Instance.IsShuffleEnabled;
Sprite val = Plugin.Instance.ShuffleOnSprite ?? ReflectionUtils.GetField<Sprite>(uiManager, "_loopCheckedSprite");
Sprite val2 = Plugin.Instance.ShuffleOffSprite ?? ReflectionUtils.GetField<Sprite>(uiManager, "_loopUncheckedSprite");
shuffleImage.sprite = (isShuffleEnabled ? val : val2);
}
}
}
namespace BetterMediaControls.audio
{
public static class AudioLoader
{
[CompilerGenerated]
private sealed class <LoadAudio>d__2 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public string path;
public Action<AudioClip> onLoaded;
private UnityWebRequest <request>5__2;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <LoadAudio>d__2(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
int num = <>1__state;
if (num == -3 || num == 1)
{
try
{
}
finally
{
<>m__Finally1();
}
}
<request>5__2 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//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_004d: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Invalid comparison between Unknown and I4
bool result;
try
{
switch (<>1__state)
{
default:
result = false;
break;
case 0:
{
<>1__state = -1;
string text = "file:///" + path.Replace("\\", "/");
AudioType audioType = GetAudioType(path);
<request>5__2 = UnityWebRequestMultimedia.GetAudioClip(text, audioType);
<>1__state = -3;
((DownloadHandlerAudioClip)<request>5__2.downloadHandler).streamAudio = true;
<>2__current = <request>5__2.SendWebRequest();
<>1__state = 1;
result = true;
break;
}
case 1:
<>1__state = -3;
if ((int)<request>5__2.result != 1)
{
Plugin.Log.LogError((object)("Failed to load audio " + path + ": " + <request>5__2.error));
onLoaded(null);
result = false;
<>m__Finally1();
}
else
{
AudioClip content = DownloadHandlerAudioClip.GetContent(<request>5__2);
((Object)content).name = Path.GetFileNameWithoutExtension(path);
onLoaded(content);
<>m__Finally1();
<request>5__2 = null;
result = false;
}
break;
}
}
catch
{
//try-fault
((IDisposable)this).Dispose();
throw;
}
return result;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
private void <>m__Finally1()
{
<>1__state = -1;
if (<request>5__2 != null)
{
((IDisposable)<request>5__2).Dispose();
}
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private static readonly string[] SupportedExtensions = new string[3] { ".wav", ".ogg", ".mp3" };
public static bool IsSupportedFile(string path)
{
string extension = Path.GetExtension(path);
string[] supportedExtensions = SupportedExtensions;
foreach (string b in supportedExtensions)
{
if (string.Equals(extension, b, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
[IteratorStateMachine(typeof(<LoadAudio>d__2))]
public static IEnumerator LoadAudio(string path, Action<AudioClip> onLoaded)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <LoadAudio>d__2(0)
{
path = path,
onLoaded = onLoaded
};
}
private static AudioType GetAudioType(string path)
{
return (AudioType)(Path.GetExtension(path)?.ToLowerInvariant() switch
{
".ogg" => 14,
".mp3" => 13,
".wav" => 20,
_ => 0,
});
}
}
public class PlaylistFile
{
public List<PlaylistEntry> Playlist;
}
public class PlaylistEntry
{
public string File;
public string Title;
public string Artist;
public float Volume = 1f;
}
}