using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Windows.Storage; using Windows.UI.Xaml; namespace DrumKit { public static class DataController { #region Fields: Repositories private static Repository.DataRepository DataRepo { get; set; } private static Repository.DrumkitRepository DrumkitRepo { get; set; } private static Repository.SoundRepository SoundRepository { get; set; } private static SoundPool SoundPool { get; set; } #endregion #region Fields: Timers private static DispatcherTimer saveConfigTimer { get; set; } private static DispatcherTimer saveLayoutTimer { get; set; } private static DispatcherTimer saveSettingsTimer { get; set; } #endregion #region Fields: Public properties /// /// Gets application's installation info /// public static AppInstallInfo InstallInfo { get { return (DataRepo == null) ? null : DataRepo.InstallInfo; } } /// /// Gets application's settings. /// public static AppSettings Settings { get { return (DataRepo == null) ? null : DataRepo.Settings; } } /// /// Gets the list of available drumkits. /// public static Dictionary AvailableDrumkits { get { return (DrumkitRepo == null) ? null : DrumkitRepo.AvailableDrumKits; } } /// /// Gets or sets the current drumkit. /// public static Drumkit CurrentDrumkit { get { return AvailableDrumkits[CurrentDrumkitName]; } set { CurrentDrumkitName = value.Name; } } /// /// Gets the current drumkit names. /// public static string CurrentDrumkitName { get; private set; } /// /// Gets the current drumkit layouts. /// public static DrumkitLayoutCollection CurrentLayouts { get; private set; } /// /// Gets the current drums configuration. /// public static DrumkitConfig CurrentConfig { get; private set; } /// /// Gets or sets the master volume. /// public static float MasterVolume { get { return Settings.MasterVolume; } set { Settings.MasterVolume = value; SoundPool.MasterVolume = value; } } #endregion #region Events /// /// Triggered when the progress of the initialize method changed. /// public static event EventHandler> ProgressChanged; #endregion #region Initialization /// /// Initializes everything. /// public static async Task Initialize() { // Initialize timers InitializeTimers(); // Prepare data ReportProgress(1 * 100 / 8, "Loading data..."); await InitializeData(); // Open log file await Log.Initialize(); // Prepare drumkits ReportProgress(4 * 100 / 8, "Loading drums..."); await InitializeDrumkits(); // Figure out current drumkit, throw ControllerException if nothing found. CurrentDrumkitName = GetCurrentDrumkit(); // Load drumkit layouts and config ReportProgress(5 * 100 / 8, "Loading drums..."); CurrentLayouts = await DrumkitRepo.ReadLayouts(CurrentDrumkitName); CurrentConfig = await DrumkitRepo.ReadConfig(CurrentDrumkitName); // Load drumkit sounds ReportProgress(6 * 100 / 8, "Loading sounds..."); await InitializeSounds(); // Load user interface (images and stuff) ReportProgress(7 * 100 / 8, "Loading interface..."); await InitializeUI(); } /// /// Initializes the timers for IO operations /// The timers are used in order to avoid problems from too many IO requests in a short period of time. /// private static void InitializeTimers() { saveConfigTimer = new DispatcherTimer(); saveConfigTimer.Interval = TimeSpan.FromSeconds(.5); saveConfigTimer.Tick += SaveConfigTick; saveLayoutTimer = new DispatcherTimer(); saveLayoutTimer.Interval = TimeSpan.FromSeconds(.5); saveLayoutTimer.Tick += SaveLayoutTick; saveSettingsTimer = new DispatcherTimer(); saveSettingsTimer.Interval = TimeSpan.FromSeconds(.5); saveSettingsTimer.Tick += SaveSettingsTick; } /// /// Initializes the data: loads settings, app install info, performs after install actions. /// private static async Task InitializeData() { DataRepo = new Repository.DataRepository(); await DataRepo.Initialize(ApplicationData.Current); } /// /// Initializes the drumkit repository: loads information about every drumkit /// private static async Task InitializeDrumkits() { StorageFolder repo = await ApplicationData.Current.RoamingFolder.CreateFolderAsync("Drumkits", CreationCollisionOption.OpenIfExists); DrumkitRepo = new Repository.DrumkitRepository(); await DrumkitRepo.Initialize(repo); } /// /// Initializes the sound repository: loads all the drums associated with the current drumkit, creates soundpool. /// private static async Task InitializeSounds() { // Create repository StorageFolder repo = CurrentDrumkit.RootFolder; SoundRepository = new Repository.SoundRepository(repo); // Load drums foreach (var i in CurrentDrumkit.DrumsList) if (CurrentConfig.Drums[i.Id].IsEnabled) await SoundRepository.LoadSounds(i); // Create soundpool if (SoundRepository.LoadedSounds.Count > 0) SoundPool = new SoundPool(SoundRepository.LoadedSounds.First().Value.WaveFormat, Settings.Polyphony); else SoundPool = new SoundPool(new SharpDX.Multimedia.WaveFormat(), Settings.Polyphony); SoundPool.MasterVolume = Settings.MasterVolume; } /// /// Determines the current drumkit /// private static string GetCurrentDrumkit() { // Try the application settings if (AvailableDrumkits.ContainsKey(Settings.CurrentKit)) return Settings.CurrentKit; // Nope, try default if (AvailableDrumkits.ContainsKey("Default")) return "Default"; // Nope, try anything if (AvailableDrumkits.Count > 0) return AvailableDrumkits.First().Key; // Still nothing? Error throw new ControllerException("No drumkits available!"); } /// /// Loads the drum images /// private static async Task InitializeUI() { // Load images foreach (var i in CurrentDrumkit.DrumsList) { i.LoadedImageSource = await IOHelper.GetImageAsync(CurrentDrumkit.RootFolder, i.ImageSource); i.LoadedImagePressedSource = await IOHelper.GetImageAsync(CurrentDrumkit.RootFolder, i.ImagePressedSource); } } #endregion /// /// Resets to factory settings /// public static async Task FactoryReset() { await ApplicationData.Current.ClearAsync(); } #region Private methods /// /// Reports current progress (calls event). /// /// Percentage of task completed. /// What is happening, like a message to the user. private static void ReportProgress(int percent, string info) { if (ProgressChanged != null) ProgressChanged(null, new KeyValuePair(percent, info)); } #endregion #region Playback /// /// Plays a sound if loaded. /// /// ID of the drum the sound belongs to. /// Intensity of sound public static void PlaySound(string drum_id, int intensity=0) { // Get sound Sound? sound = SoundRepository.GetLoadedSound(drum_id, intensity); // If possible, play if (sound.HasValue) { float l = Convert.ToSingle(CurrentConfig.Drums[drum_id].VolumeL); float r = Convert.ToSingle(CurrentConfig.Drums[drum_id].VolumeR); SoundPool.PlayBuffer(sound.Value, l, r); } } #endregion #region Drumkit repository /// /// Deletes a drumkit from the system. /// /// Name (identifier) of drumkit public static async Task RemoveDrumkit (string name) { // Make sure there is at least a drumkit remaining if (AvailableDrumkits.Count <= 1) throw new ControllerException("Cannot remove last drumkit."); // Is it current drumkit? if (name == CurrentDrumkitName) throw new ArgumentException("Cannot remove currently loaded drumkit."); // Remove await DrumkitRepo.Remove(name); } /// /// Installs a drumkit package. /// /// A .tar file public static async Task InstallDrumkit(StorageFile tarball) { await DrumkitRepo.InstallTarball(tarball); } /// /// Exports a drumkit package. /// /// The key of the drumkit to export /// The destination file public static async Task ExportDrumkit(string drumkit_key, StorageFile tarball) { await DrumkitRepo.ExportTarball(drumkit_key, tarball); } /// /// Creates a new layout /// public static void CreateLayout() { // Create object var layout = new DrumkitLayout(); // Add layout for each of the existing drums foreach (var i in CurrentDrumkit.Drums.Keys) layout.Drums.Add(i, new DrumLayout() { TargetId = i }); // Add to layout list CurrentLayouts.Items.Add(layout); } #endregion #region Save methods /// /// Saves the drum configuration settings for current drumkit. /// public static void SaveConfig() { saveConfigTimer.Stop(); saveConfigTimer.Start(); } /// /// Saves the drum layout settings for current drumkit. /// public static void SaveLayout() { saveLayoutTimer.Stop(); saveLayoutTimer.Start(); } /// /// Saves the applications settings. /// public static void SaveSettings() { saveSettingsTimer.Stop(); saveSettingsTimer.Start(); } /// /// Save settings timer. /// private static async void SaveSettingsTick(object sender, object e) { // Save settings await DataRepo.WriteSettings(); Log.Write("Saved settings"); // Stop timer var timer = sender as DispatcherTimer; if (timer != null) timer.Stop(); } /// /// Save layouts timer /// private static async void SaveLayoutTick(object sender, object e) { // Save layouts await DrumkitRepo.WriteLayouts(CurrentDrumkitName, CurrentLayouts); Log.Write("Saved layout..."); // Stop timer var timer = sender as DispatcherTimer; if (timer != null) timer.Stop(); } /// /// Save drum configuration timer. /// private static async void SaveConfigTick(object sender, object e) { // Save drumkit configuration await DrumkitRepo.WriteConfig(CurrentDrumkitName, CurrentConfig); Log.Write("Saved configuration..."); // Stop timer var timer = sender as DispatcherTimer; if (timer != null) timer.Stop(); } #endregion /// /// Saves settings and other stuff /// public static void Dispose() { DrumkitRepo.Dispose(); SoundRepository.Dispose(); SoundPool.Dispose(); } } }