mirror of
				https://github.com/chibicitiberiu/drumkit.git
				synced 2024-02-24 10:53:32 +00:00 
			
		
		
		
	Latest build (version 2.2)
This commit is contained in:
		
							
								
								
									
										183
									
								
								DrumKit/Repository/DataRepository.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								DrumKit/Repository/DataRepository.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,183 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using Windows.Storage;
 | 
			
		||||
 | 
			
		||||
namespace DrumKit.Repository
 | 
			
		||||
{
 | 
			
		||||
    class DataRepository
 | 
			
		||||
    {
 | 
			
		||||
        #region Properties
 | 
			
		||||
        public AppSettings Settings { get; private set; }
 | 
			
		||||
        public AppInstallInfo InstallInfo { get; private set; }
 | 
			
		||||
        public ApplicationData RepositoryLocation { get; private set; }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Constructor
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Creates a new instance of drumkit.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public DataRepository()
 | 
			
		||||
        {
 | 
			
		||||
            this.InstallInfo = null;
 | 
			
		||||
            this.Settings = null;
 | 
			
		||||
            this.RepositoryLocation = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Initialize
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// And initializes the data using that information, and sets the location.
 | 
			
		||||
        /// Note that you cannot call this method multiple times on the same instance.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <exception cref="InvalidOperationException if location was already set" />
 | 
			
		||||
        public async Task Initialize(ApplicationData where)
 | 
			
		||||
        {
 | 
			
		||||
            // Set up location
 | 
			
		||||
            if (this.RepositoryLocation != null)
 | 
			
		||||
                throw new InvalidOperationException("You cannot change data repository location once set.");
 | 
			
		||||
 | 
			
		||||
            this.RepositoryLocation = where;
 | 
			
		||||
            Log.Write("[DataRepository] Location set: {0}", where.RoamingFolder.Path);
 | 
			
		||||
 | 
			
		||||
            // Read installation information
 | 
			
		||||
            this.InstallInfo = await this.ReadInstallInfo();
 | 
			
		||||
 | 
			
		||||
            // Version changed, or no info (new install)?
 | 
			
		||||
            if (this.IsFirstLaunch())
 | 
			
		||||
            {
 | 
			
		||||
                // Clean up any junk
 | 
			
		||||
                await this.FactoryReset();
 | 
			
		||||
 | 
			
		||||
                // Copy local assets to app data
 | 
			
		||||
                await this.InstallAssets();
 | 
			
		||||
 | 
			
		||||
                // Generate "installed.xml" file
 | 
			
		||||
                await this.WriteInstallInfo();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Load settings
 | 
			
		||||
            this.Settings = await this.ReadSettings();
 | 
			
		||||
            
 | 
			
		||||
            // No settings? Use default.
 | 
			
		||||
            if (this.Settings == null)
 | 
			
		||||
                this.Settings = new AppSettings();
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Reads the install info.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>An AppInstallInfo structure, or null if file does not exist.</returns>
 | 
			
		||||
        private async Task<AppInstallInfo> ReadInstallInfo()
 | 
			
		||||
        {
 | 
			
		||||
            // See if 'installed.xml' exists
 | 
			
		||||
            var files = await this.RepositoryLocation.RoamingFolder.GetFilesAsync();
 | 
			
		||||
            StorageFile file = files.FirstOrDefault(x => x.Name == "installed.xml");
 | 
			
		||||
            
 | 
			
		||||
            if (file == null) 
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
            // Read info
 | 
			
		||||
            object info = await IOHelper.DeserializeFile(file, typeof(AppInstallInfo));
 | 
			
		||||
            return info as AppInstallInfo;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task<AppSettings> ReadSettings()
 | 
			
		||||
        {
 | 
			
		||||
            // See if 'settings.xml' exists
 | 
			
		||||
            var files = await this.RepositoryLocation.RoamingFolder.GetFilesAsync();
 | 
			
		||||
            StorageFile file = files.FirstOrDefault(x => x.Name == "settings.xml");
 | 
			
		||||
 | 
			
		||||
            if (file == null)
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
            // Read info
 | 
			
		||||
            object settings = await IOHelper.DeserializeFile(file, typeof(AppSettings));
 | 
			
		||||
            return settings as AppSettings;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool IsFirstLaunch()
 | 
			
		||||
        {
 | 
			
		||||
            // Get current assembly information
 | 
			
		||||
            Assembly current_asm = typeof(DataRepository).GetTypeInfo().Assembly;
 | 
			
		||||
            int version = current_asm.GetName().Version.Major * 1000 + current_asm.GetName().Version.Minor;
 | 
			
		||||
           
 | 
			
		||||
            // If no install info, this is probably first launch
 | 
			
		||||
            if (this.InstallInfo == null)
 | 
			
		||||
            {
 | 
			
		||||
                Log.Write("[DataRepository] First launch!");
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Smaller version, upgrade necessary
 | 
			
		||||
            if (this.InstallInfo.Version != version)
 | 
			
		||||
            {
 | 
			
		||||
                Log.Write("[DataRepository] Version upgrade ({0} => {1}).", this.InstallInfo.Version, version);
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Nothing new
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Installs the assets at first launch.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private async Task InstallAssets()
 | 
			
		||||
        {
 | 
			
		||||
            // Read content of 'ApplicationData'
 | 
			
		||||
            var reader = new Tarball.TarballReader();
 | 
			
		||||
            await reader.Unpack(new Uri("ms-appx:///Assets/ApplicationData.tar"), this.RepositoryLocation.RoamingFolder);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Creates the 'installed.xml' file.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private async Task WriteInstallInfo()
 | 
			
		||||
        {
 | 
			
		||||
            // Create file
 | 
			
		||||
            StorageFile file = await this.RepositoryLocation.RoamingFolder.CreateFileAsync("installed.xml");
 | 
			
		||||
            
 | 
			
		||||
            // Create app info
 | 
			
		||||
            AppInstallInfo info = new AppInstallInfo();
 | 
			
		||||
            
 | 
			
		||||
            // Serialize info
 | 
			
		||||
            await IOHelper.SerializeFile(file, info, typeof(AppInstallInfo));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Resets to factory settings
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public async Task FactoryReset()
 | 
			
		||||
        {
 | 
			
		||||
            await this.RepositoryLocation.ClearAsync();
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Saves the current settings.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public async Task WriteSettings()
 | 
			
		||||
        {
 | 
			
		||||
            // Get settings file
 | 
			
		||||
            var file = await ApplicationData.Current.RoamingFolder.CreateFileAsync("settings.xml", CreationCollisionOption.ReplaceExisting);
 | 
			
		||||
 | 
			
		||||
            // Serialize settings
 | 
			
		||||
            await IOHelper.SerializeFile(file, this.Settings, typeof(AppSettings));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Releases the current resources.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										322
									
								
								DrumKit/Repository/DrumkitRepository.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										322
									
								
								DrumKit/Repository/DrumkitRepository.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,322 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Windows.Storage;
 | 
			
		||||
 | 
			
		||||
namespace DrumKit.Repository
 | 
			
		||||
{
 | 
			
		||||
    public class DrumkitRepository
 | 
			
		||||
    {
 | 
			
		||||
        #region Properties
 | 
			
		||||
        public Dictionary<string, Drumkit> AvailableDrumKits { get; private set; }
 | 
			
		||||
        public StorageFolder RepositoryLocation { get; private set; }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Constructor
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Creates a new instance of drumkit.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public DrumkitRepository()
 | 
			
		||||
        {
 | 
			
		||||
            this.AvailableDrumKits = new Dictionary<string, Drumkit>();
 | 
			
		||||
            this.RepositoryLocation = null;
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region (private) AddDrumkit
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Adds a drumkit to the dictionary.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="kit">Drumkit to add</param>
 | 
			
		||||
        /// <returns>True if item added successfully, false otherwise.</returns>
 | 
			
		||||
        private bool AddDrumkit(Drumkit kit)
 | 
			
		||||
        {
 | 
			
		||||
            // If drumkit is null
 | 
			
		||||
            if (kit == null)
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            // If name is unique
 | 
			
		||||
            if (this.AvailableDrumKits.ContainsKey(kit.Name))
 | 
			
		||||
            {
 | 
			
		||||
                Log.Error("[DrumkitRepository] Did not add kit, name not unique: name = {0}, location = {1} ", kit.Name, kit.RootFolder.Path);
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Add to list
 | 
			
		||||
            this.AvailableDrumKits.Add(kit.Name, kit);
 | 
			
		||||
            Log.Write("[DrumkitRepository] Added kit: name = {0}, location = {1}", kit.Name, kit.RootFolder.Path);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region (private) ReadDrumkit
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Reads information about a drumkit.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="where">Where drumkit located</param>
 | 
			
		||||
        /// <returns>Drumkit object, null if not a valid drumkit.</returns>
 | 
			
		||||
        private async Task<Drumkit> ReadDrumkit(StorageFolder where)
 | 
			
		||||
        {
 | 
			
		||||
            // Get manifest file
 | 
			
		||||
            var files = await where.GetFilesAsync();
 | 
			
		||||
            var manifest = files.FirstOrDefault(x => x.Name == "drumkit.xml");
 | 
			
		||||
 | 
			
		||||
            // No manifest? Not drumkit
 | 
			
		||||
            if (manifest == null)
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
            // Read drumkit object
 | 
			
		||||
            object kitobj = await IOHelper.DeserializeFile(manifest, typeof(Drumkit));
 | 
			
		||||
            var kit = kitobj as Drumkit;
 | 
			
		||||
 | 
			
		||||
            // Set root folder if possible
 | 
			
		||||
            if (kit != null)
 | 
			
		||||
                kit.RootFolder = where;
 | 
			
		||||
 | 
			
		||||
            // Return
 | 
			
		||||
            return kit;
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region ReadLayouts
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Reads the layouts of the specified drumkit.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="drumkit_name">Name of drumkit</param>
 | 
			
		||||
        public async Task<DrumkitLayoutCollection> ReadLayouts(string drumkit_name)
 | 
			
		||||
        {
 | 
			
		||||
            Drumkit kit = null;
 | 
			
		||||
            
 | 
			
		||||
            // Get the drumkit
 | 
			
		||||
            if (!this.AvailableDrumKits.TryGetValue(drumkit_name, out kit))
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
            // Get layouts file
 | 
			
		||||
            StorageFile file = await IOHelper.GetFileRelativeAsync(kit.RootFolder, kit.LayoutFilePath);
 | 
			
		||||
 | 
			
		||||
            // Read layouts
 | 
			
		||||
            object layouts = await IOHelper.DeserializeFile(file, typeof(DrumkitLayoutCollection));
 | 
			
		||||
            return layouts as DrumkitLayoutCollection;
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region WriteLayouts
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Rewrites the layouts for the specified drumkit.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="drumkit_name">Name of drumkit.</param>
 | 
			
		||||
        /// <param name="layouts">Layout collection to be saved.</param>
 | 
			
		||||
        public async Task WriteLayouts(string drumkit_name, DrumkitLayoutCollection layouts)
 | 
			
		||||
        {
 | 
			
		||||
            Drumkit kit = null;
 | 
			
		||||
 | 
			
		||||
            // Sanity check
 | 
			
		||||
            if (layouts == null)
 | 
			
		||||
                throw new RepositoryException("Cannot write null layout collection!");
 | 
			
		||||
 | 
			
		||||
            // Get the drumkit
 | 
			
		||||
            if (!this.AvailableDrumKits.TryGetValue(drumkit_name, out kit))
 | 
			
		||||
                throw new RepositoryException("No such drumkit.");
 | 
			
		||||
 | 
			
		||||
            // Delete old layouts file
 | 
			
		||||
            StorageFile old = await IOHelper.GetFileRelativeAsync(kit.RootFolder, kit.LayoutFilePath);
 | 
			
		||||
            await old.DeleteAsync();
 | 
			
		||||
 | 
			
		||||
            // Create new file
 | 
			
		||||
            StorageFile file = await IOHelper.CreateFileRelativeAsync(kit.RootFolder, kit.LayoutFilePath);
 | 
			
		||||
 | 
			
		||||
            // Write
 | 
			
		||||
            await IOHelper.SerializeFile(file, layouts, typeof(DrumkitLayoutCollection));
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region ReadConfig
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Reads the configuration file for the specified drumkit.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="drumkit_name">Name of drumkit</param>
 | 
			
		||||
        public async Task<DrumkitConfig> ReadConfig(string drumkit_name)
 | 
			
		||||
        {
 | 
			
		||||
            Drumkit kit = null;
 | 
			
		||||
 | 
			
		||||
            // Get the drumkit
 | 
			
		||||
            if (!this.AvailableDrumKits.TryGetValue(drumkit_name, out kit))
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
            // Get layouts file
 | 
			
		||||
            StorageFile file = await IOHelper.GetFileRelativeAsync(kit.RootFolder, kit.ConfigFilePath);
 | 
			
		||||
 | 
			
		||||
            // Read layouts
 | 
			
		||||
            object config = await IOHelper.DeserializeFile(file, typeof(DrumkitConfig));
 | 
			
		||||
            return config as DrumkitConfig;
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region WriteConfig
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Rewrites the configuration file for the specified drumkit.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="drumkit_name">Name of drumkit</param>
 | 
			
		||||
        /// <param name="config">Configuration</param>
 | 
			
		||||
        public async Task WriteConfig(string drumkit_name, DrumkitConfig config)
 | 
			
		||||
        {
 | 
			
		||||
            Drumkit kit = null;
 | 
			
		||||
 | 
			
		||||
            // Sanity check
 | 
			
		||||
            if (config == null)
 | 
			
		||||
                throw new RepositoryException("Cannot write null configs!");
 | 
			
		||||
 | 
			
		||||
            // Get the drumkit
 | 
			
		||||
            if (!this.AvailableDrumKits.TryGetValue(drumkit_name, out kit))
 | 
			
		||||
                throw new RepositoryException("No such drumkit.");
 | 
			
		||||
 | 
			
		||||
            // Delete old layouts file
 | 
			
		||||
            StorageFile old = await IOHelper.GetFileRelativeAsync(kit.RootFolder, kit.ConfigFilePath);
 | 
			
		||||
            await old.DeleteAsync();
 | 
			
		||||
 | 
			
		||||
            // Create new file
 | 
			
		||||
            StorageFile file = await IOHelper.CreateFileRelativeAsync(kit.RootFolder, kit.ConfigFilePath);
 | 
			
		||||
 | 
			
		||||
            // Write
 | 
			
		||||
            await IOHelper.SerializeFile(file, config, typeof(DrumkitConfig));
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Initialize
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Initializes the repository set to one location.
 | 
			
		||||
        /// Note that you cannot call this method multiple times for the same instance.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <exception cref="InvalidOperationException if location was already set" />
 | 
			
		||||
        public async Task Initialize(StorageFolder where)
 | 
			
		||||
        {
 | 
			
		||||
            // Set up location
 | 
			
		||||
            if (this.RepositoryLocation != null)
 | 
			
		||||
                throw new InvalidOperationException("You cannot change drumkit repository location once set.");
 | 
			
		||||
 | 
			
		||||
            this.RepositoryLocation = where;
 | 
			
		||||
            Log.Write("[DrumkitRepository] Location set: {0}", where.Path);
 | 
			
		||||
 | 
			
		||||
            // Get possible drumkits
 | 
			
		||||
            var folders = await where.GetFoldersAsync();
 | 
			
		||||
 | 
			
		||||
            // Load each drumkit
 | 
			
		||||
            foreach (var i in folders)
 | 
			
		||||
            {
 | 
			
		||||
                Drumkit kit = await this.ReadDrumkit(i);
 | 
			
		||||
 | 
			
		||||
                // If it is a drumkit
 | 
			
		||||
                if (kit != null)
 | 
			
		||||
                    this.AddDrumkit(kit);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region InstallTarball
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Adds a new drumkit to the repository.
 | 
			
		||||
        /// The drumkit should be an uncompressed tarball file, which will be
 | 
			
		||||
        /// unpacked to the repository's location.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="tarball">The tarball file.</param>
 | 
			
		||||
        /// <exception cref="ArgumentException if file is not a valid drumkit." />
 | 
			
		||||
        /// <exception cref="RepositoryException if name of drumkit is not unique." />
 | 
			
		||||
        public async Task InstallTarball (StorageFile tarball)
 | 
			
		||||
        {
 | 
			
		||||
            Log.Write("[DrumkitRepository] Installing tarball: {0}", tarball.Path);
 | 
			
		||||
            
 | 
			
		||||
            // Create destination folder
 | 
			
		||||
            string dest_name = System.IO.Path.GetFileNameWithoutExtension(tarball.Name);
 | 
			
		||||
            var dest = await this.RepositoryLocation.CreateFolderAsync(dest_name, CreationCollisionOption.GenerateUniqueName);
 | 
			
		||||
 | 
			
		||||
            // Unpack tarball
 | 
			
		||||
            var reader = new Tarball.TarballReader();
 | 
			
		||||
            await reader.Unpack(tarball, dest);
 | 
			
		||||
 | 
			
		||||
            // Read information
 | 
			
		||||
            Drumkit kit = await this.ReadDrumkit(dest);
 | 
			
		||||
 | 
			
		||||
            // If there was a problem
 | 
			
		||||
            if (kit == null || !this.AddDrumkit(kit))
 | 
			
		||||
            {
 | 
			
		||||
                Log.Error("[DrumkitRepository] Failed to install tarball: {0}", tarball.Path);
 | 
			
		||||
 | 
			
		||||
                // Cleanup
 | 
			
		||||
                await dest.DeleteAsync(StorageDeleteOption.PermanentDelete);
 | 
			
		||||
 | 
			
		||||
                // Throw exception
 | 
			
		||||
                if (kit == null)
 | 
			
		||||
                    throw new ArgumentException("Tarball not a drumkit.");
 | 
			
		||||
 | 
			
		||||
                else
 | 
			
		||||
                    throw new RepositoryException("Drumkit name not unique.");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region ExportTarball
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Exports a drumkit to a tarball file.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="drumkit_key">The key of the drumkit to export.</param>
 | 
			
		||||
        /// <param name="tarball">The destination tarball file.</param>
 | 
			
		||||
        /// <exception cref="ArgumentException">Raised if key is not valid.</exception>
 | 
			
		||||
        /// <exception cref="ArgumentNullException">Raised if destination tarball is null.</exception>
 | 
			
		||||
        public async Task ExportTarball(string drumkit_key, StorageFile tarball)
 | 
			
		||||
        {
 | 
			
		||||
            // Sanity checks
 | 
			
		||||
            if (!AvailableDrumKits.ContainsKey(drumkit_key))
 | 
			
		||||
                throw new ArgumentException("Invalid key!");
 | 
			
		||||
 | 
			
		||||
            if (tarball == null)
 | 
			
		||||
                throw new ArgumentNullException("Tarball cannot be null.");
 | 
			
		||||
 | 
			
		||||
            // Log
 | 
			
		||||
            Log.Write("[DrumkitRepository] Exporting drumkit \"{0}\" to tarball : {1}", drumkit_key, tarball.Path);
 | 
			
		||||
 | 
			
		||||
            // Get drumkit's folder
 | 
			
		||||
            StorageFolder folder = AvailableDrumKits[drumkit_key].RootFolder;
 | 
			
		||||
 | 
			
		||||
            // Create tarball writer
 | 
			
		||||
            Tarball.TarballWriter writer = new Tarball.TarballWriter();
 | 
			
		||||
            writer.AddItems(await folder.GetItemsAsync());
 | 
			
		||||
            await writer.Pack(tarball);
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Remove
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Removes a drumkit from the repository (and system)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="name">Name of drumkit</param>
 | 
			
		||||
        /// <exception cref="ArgumentException if name does not exist." />
 | 
			
		||||
        public async Task Remove(string name)
 | 
			
		||||
        {
 | 
			
		||||
            // Make sure such name exists
 | 
			
		||||
            if (!this.AvailableDrumKits.ContainsKey(name))
 | 
			
		||||
                throw new ArgumentException("Invalid name");
 | 
			
		||||
 | 
			
		||||
            // Remove folder
 | 
			
		||||
            if (this.AvailableDrumKits[name].RootFolder != null)
 | 
			
		||||
            {
 | 
			
		||||
                // Log
 | 
			
		||||
                Log.Write("[DrumkitRepository] Removing drumkit: name = {0}, location = {1}", name, this.AvailableDrumKits[name].RootFolder.Path);
 | 
			
		||||
                await this.AvailableDrumKits[name].RootFolder.DeleteAsync(StorageDeleteOption.PermanentDelete);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Remove entry
 | 
			
		||||
            this.AvailableDrumKits.Remove(name);
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Cleans the used resources.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
            this.AvailableDrumKits.Clear();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										140
									
								
								DrumKit/Repository/LogRepository.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								DrumKit/Repository/LogRepository.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,140 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Windows.Storage;
 | 
			
		||||
 | 
			
		||||
namespace DrumKit.Repository
 | 
			
		||||
{
 | 
			
		||||
    public static class LogRepository
 | 
			
		||||
    {
 | 
			
		||||
        private static StorageFile OutputFile = null;
 | 
			
		||||
        private static StorageFolder RootDirectory = null;
 | 
			
		||||
        private static List<string> Buffer = new List<string>();
 | 
			
		||||
 | 
			
		||||
        public static DateTime CurrentLogDate { get; private set; }
 | 
			
		||||
        public static List<DateTime> Dates { get; private set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Initializes the log repository.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static async Task Initialize(StorageFolder location)
 | 
			
		||||
        {
 | 
			
		||||
            // Create/open log file
 | 
			
		||||
            CurrentLogDate = new DateTime(DateTime.Now.Ticks);
 | 
			
		||||
            OutputFile = await location.CreateFileAsync(CurrentLogDate.Ticks.ToString() + ".log", CreationCollisionOption.OpenIfExists);
 | 
			
		||||
 | 
			
		||||
            // Set root directory
 | 
			
		||||
            RootDirectory = location;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Writes a line to the log file
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="text">The text to write.</param>
 | 
			
		||||
        public static async void WriteLine(string text)
 | 
			
		||||
        {
 | 
			
		||||
            // Append text
 | 
			
		||||
            if (OutputFile != null)
 | 
			
		||||
                try {
 | 
			
		||||
                    await FileIO.AppendTextAsync(OutputFile, text + "\n");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                catch { }
 | 
			
		||||
 | 
			
		||||
            // No file? write to a temporary buffer
 | 
			
		||||
            else Buffer.Add(text);
 | 
			
		||||
 | 
			
		||||
            // Also write to console
 | 
			
		||||
            System.Diagnostics.Debug.WriteLine(text);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Reads the list of log files
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static async Task ReadLogFiles()
 | 
			
		||||
        {
 | 
			
		||||
            // Make sure we have a root directory
 | 
			
		||||
            if (RootDirectory == null)
 | 
			
		||||
                throw new RepositoryException("No location set!");
 | 
			
		||||
 | 
			
		||||
            // Get files in root directory
 | 
			
		||||
            var files = await RootDirectory.GetFilesAsync();
 | 
			
		||||
 | 
			
		||||
            // Clear old dates
 | 
			
		||||
            Dates = new List<DateTime>();
 | 
			
		||||
 | 
			
		||||
            // Get dates
 | 
			
		||||
            long ticks;
 | 
			
		||||
            foreach (var i in files)
 | 
			
		||||
            {
 | 
			
		||||
                string file_name = Path.GetFileNameWithoutExtension(i.Name);
 | 
			
		||||
 | 
			
		||||
                if (long.TryParse(file_name, out ticks))
 | 
			
		||||
                    Dates.Add(new DateTime(ticks));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Deletes all log files except the current one.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static async Task Clear()
 | 
			
		||||
        {
 | 
			
		||||
            // Make sure we have a root directory
 | 
			
		||||
            if (RootDirectory == null)
 | 
			
		||||
                throw new RepositoryException("No location set!");
 | 
			
		||||
 | 
			
		||||
            // Get files in root directory
 | 
			
		||||
            var files = await RootDirectory.GetFilesAsync();
 | 
			
		||||
 | 
			
		||||
            // Calculate current date
 | 
			
		||||
            string current = CurrentLogDate.Ticks.ToString() + ".log";
 | 
			
		||||
 | 
			
		||||
            // Delete everything except current
 | 
			
		||||
            foreach (var i in files)
 | 
			
		||||
                if (i.Name != current)
 | 
			
		||||
                    await i.DeleteAsync();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Reads a log file.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="time">The date and time linked to this log file.</param>
 | 
			
		||||
        /// <returns>The list of lines for this file.</returns>
 | 
			
		||||
        public static async Task<IList<string>> ReadLog(DateTime time)
 | 
			
		||||
        {
 | 
			
		||||
            // Make sure we have a root directory
 | 
			
		||||
            if (RootDirectory == null)
 | 
			
		||||
                throw new RepositoryException("No location set!");
 | 
			
		||||
 | 
			
		||||
            // Find the file
 | 
			
		||||
            var file = await RootDirectory.GetFileAsync(time.Ticks.ToString() + ".log");
 | 
			
		||||
 | 
			
		||||
            // Return result
 | 
			
		||||
            return await FileIO.ReadLinesAsync(file);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Copies a log file to another location.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="log">Date and time for the log entry.</param>
 | 
			
		||||
        /// <param name="dest">Destination folder</param>
 | 
			
		||||
        public static async Task SaveAs (DateTime log, StorageFolder dest)
 | 
			
		||||
        {
 | 
			
		||||
            // Make sure we have a root directory
 | 
			
		||||
            if (RootDirectory == null)
 | 
			
		||||
                throw new RepositoryException("No location set!");
 | 
			
		||||
 | 
			
		||||
            // Find the file
 | 
			
		||||
            var file = await RootDirectory.GetFileAsync(log.Ticks.ToString() + ".log");
 | 
			
		||||
            
 | 
			
		||||
            // Copy
 | 
			
		||||
            await file.CopyAsync(dest);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								DrumKit/Repository/RepositoryException.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								DrumKit/Repository/RepositoryException.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace DrumKit.Repository
 | 
			
		||||
{
 | 
			
		||||
    class RepositoryException : Exception
 | 
			
		||||
    {
 | 
			
		||||
        public RepositoryException() : 
 | 
			
		||||
            base() { }
 | 
			
		||||
 | 
			
		||||
        public RepositoryException(string message) : 
 | 
			
		||||
            base(message) { }
 | 
			
		||||
 | 
			
		||||
        public RepositoryException(string message, Exception innerException) : 
 | 
			
		||||
            base(message, innerException) { }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										131
									
								
								DrumKit/Repository/SoundRepository.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								DrumKit/Repository/SoundRepository.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,131 @@
 | 
			
		||||
using SharpDX.XAudio2;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using Windows.Storage;
 | 
			
		||||
using SharpDX.Multimedia;
 | 
			
		||||
 | 
			
		||||
namespace DrumKit.Repository
 | 
			
		||||
{
 | 
			
		||||
    class SoundRepository
 | 
			
		||||
    {
 | 
			
		||||
        #region Properties
 | 
			
		||||
        public StorageFolder RepositoryLocation { get; private set; }
 | 
			
		||||
        public Dictionary<string, Sound> LoadedSounds { get; private set; }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Constructor
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Creates a new instance of sound repository.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public SoundRepository(StorageFolder where)
 | 
			
		||||
        {
 | 
			
		||||
            this.RepositoryLocation = null;
 | 
			
		||||
            this.LoadedSounds = new Dictionary<string, Sound>();
 | 
			
		||||
 | 
			
		||||
            this.Initialize(where);
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Initialize
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Initializes the repository set to one location.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void Initialize(StorageFolder where)
 | 
			
		||||
        {
 | 
			
		||||
            // Set up location
 | 
			
		||||
            this.RepositoryLocation = where;
 | 
			
		||||
            Log.Write("[SoundRepository] Location set: {0}", where.Path);
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Loads a sound into memory.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="drumid">The id of the drum which will hold the sound.</param>
 | 
			
		||||
        /// <param name="source">A sound source.</param>
 | 
			
		||||
        private async Task LoadSound(string drumid, SoundSource source)
 | 
			
		||||
        {
 | 
			
		||||
            // Get file
 | 
			
		||||
            StorageFile file = await IOHelper.GetFileRelativeAsync(RepositoryLocation, source.Source);
 | 
			
		||||
 | 
			
		||||
            // Open file
 | 
			
		||||
            var stream = await file.OpenReadAsync();
 | 
			
		||||
            var iostream = stream.AsStream();
 | 
			
		||||
            var soundStream = new SoundStream(iostream);
 | 
			
		||||
 | 
			
		||||
            // Read data
 | 
			
		||||
            var buffer = new AudioBuffer()
 | 
			
		||||
            {
 | 
			
		||||
                Stream = soundStream,
 | 
			
		||||
                AudioBytes = (int)soundStream.Length,
 | 
			
		||||
                Flags = BufferFlags.EndOfStream
 | 
			
		||||
            };
 | 
			
		||||
            iostream.Dispose();
 | 
			
		||||
 | 
			
		||||
            // Create sound object
 | 
			
		||||
            Sound sound = new Sound();
 | 
			
		||||
            sound.Buffer = buffer;
 | 
			
		||||
            sound.DecodedPacketsInfo = soundStream.DecodedPacketsInfo;
 | 
			
		||||
            sound.WaveFormat = soundStream.Format;
 | 
			
		||||
 | 
			
		||||
            // Add sound to dictionary
 | 
			
		||||
            this.LoadedSounds.Add(String.Format("{0}#{1}", drumid, source.Intensity), sound);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Loads all the sounds associated with a drum to memory.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="drum">The drum.</param>
 | 
			
		||||
        public async Task LoadSounds(Drum drum)
 | 
			
		||||
        {
 | 
			
		||||
            // Load each sound
 | 
			
		||||
            foreach (var i in drum.Sounds)
 | 
			
		||||
                await this.LoadSound(drum.Id, i);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Unloads all the sounds associated with a drum from memory.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="drum">The drum</param>
 | 
			
		||||
        public void UnloadSounds(Drum drum)
 | 
			
		||||
        {
 | 
			
		||||
            // Unload each sound
 | 
			
		||||
            foreach (var i in drum.Sounds)
 | 
			
		||||
            {
 | 
			
		||||
                string key = String.Format("{0}#{1}", drum.Id, i.Intensity);
 | 
			
		||||
                if (this.LoadedSounds.ContainsKey(key))
 | 
			
		||||
                    this.LoadedSounds.Remove(key);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets a loaded sound from the dictionary.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="drumid">ID of the drum.</param>
 | 
			
		||||
        /// <param name="intensity">Sound intensity.</param>
 | 
			
		||||
        public Sound? GetLoadedSound(string drumid, int intensity)
 | 
			
		||||
        {
 | 
			
		||||
            Sound sound;
 | 
			
		||||
            string key = String.Format("{0}#{1}", drumid, intensity);
 | 
			
		||||
 | 
			
		||||
            // Try to get sound
 | 
			
		||||
            if (!this.LoadedSounds.TryGetValue(key, out sound))
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
            // OK
 | 
			
		||||
            return sound;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Cleans the currently used resources.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
            this.LoadedSounds.Clear();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user