Build 130105

This commit is contained in:
2013-11-18 20:06:17 +02:00
parent 4e0e7d4a83
commit 8954fd2635
82 changed files with 2620 additions and 586 deletions

View File

@ -0,0 +1,179 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using System.IO;
using Windows.Storage;
namespace DrumKit
{
static class DataManager
{
public static AppSettings Settings { get; private set; }
/// <summary>
/// Checks if this is the first time application was launched.
/// </summary>
public static async Task<bool> IsFirstLaunch()
{
// See if 'installed.xml' exists
var folder = ApplicationData.Current.RoamingFolder;
var files = await folder.GetFilesAsync();
return files.Count(x => x.Name == "installed.xml") == 0;
}
/// <summary>
/// Copies the content of the source folder into the destination folder recursively.
/// </summary>
//private static async Task CopyFolder(StorageFolder source, StorageFolder dest)
//{
// // Copy folders recursively
// var folders = await source.GetFoldersAsync();
// foreach (var i in folders)
// {
// var newfolder = await dest.CreateFolderAsync(i.Name, CreationCollisionOption.OpenIfExists);
// await CopyFolder(i, newfolder);
// }
// // Copy files
// var files = await source.GetFilesAsync();
// foreach (var i in files)
// await i.CopyAsync(dest);
//}
/// <summary>
/// Installs the assets at first launch.
/// </summary>
/// <returns></returns>
private static async Task InstallAssets()
{
// Read content of 'ApplicationData'
var reader = new DrumKit.Archiving.TarballReader();
await reader.Unpack(new Uri("ms-appx:///Assets/ApplicationData.tar"), ApplicationData.Current.RoamingFolder);
}
/// <summary>
/// Creates the 'installed.xml' file.
/// </summary>
/// <returns></returns>
private static async Task MarkInstalled()
{
// Open stream
StorageFile file = await ApplicationData.Current.RoamingFolder.CreateFileAsync("installed.xml");
var stream = await file.OpenAsync(FileAccessMode.ReadWrite);
var iostream = stream.AsStream();
// Generate xml
var writer = System.Xml.XmlWriter.Create(iostream, new System.Xml.XmlWriterSettings() { Async = true, CloseOutput = true });
writer.WriteStartDocument();
writer.WriteStartElement("drumkit");
writer.WriteString(DateTime.UtcNow.ToString());
writer.WriteEndElement();
writer.WriteEndDocument();
// Cleanup
await writer.FlushAsync();
writer.Dispose();
iostream.Dispose();
}
/// <summary>
/// Resets everything to factory settings.
/// The application must be reinitialized after (or closed).
/// </summary>
public static async Task FactoryReset()
{
await ApplicationData.Current.ClearAsync();
}
/// <summary>
/// Loads the settings file.
/// </summary>
public static async Task LoadSettings()
{
// If all else fails, default settings
Settings = new AppSettings();
// Get settings file
var files = await ApplicationData.Current.RoamingFolder.GetFilesAsync();
var sf = files.FirstOrDefault(x => x.Name == "settings.xml");
// File found
if (sf != null)
{
// Open file
var fstream = await sf.OpenReadAsync();
var fstream_net = fstream.AsStream();
// Deserialize
XmlSerializer s = new XmlSerializer(Settings.GetType());
var settings = s.Deserialize(fstream_net) as AppSettings;
// All good
if (settings != null)
Settings = settings;
}
}
/// <summary>
/// Loads the settings file.
/// </summary>
public static async Task SaveSettings()
{
// Get settings file
var file = await ApplicationData.Current.RoamingFolder.CreateFileAsync("settings.xml", CreationCollisionOption.ReplaceExisting);
// Open file
var fstream = await file.OpenAsync(FileAccessMode.ReadWrite);
var fstream_net = fstream.AsStream();
// Serialize
XmlSerializer s = new XmlSerializer(Settings.GetType());
s.Serialize(fstream_net, Settings);
// Cleanup
await fstream_net.FlushAsync();
fstream_net.Dispose();
}
/// <summary>
/// Initializes the application (prepares the application at first launch, loads settings and drums).
/// </summary>
public static async Task Initialize()
{
// Is this the first time the user launches the application?
if (await IsFirstLaunch())
{
// Clean up any junk
await FactoryReset();
// Copy local assets to app data
await InstallAssets();
// Generate 'installed.xml' file
await MarkInstalled();
}
// Load settings
await LoadSettings();
// Load drum packages
}
public static async Task Close()
{
// Save settings
await SaveSettings();
// Save modified layout & stuff
}
}
}

View File

@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using System.IO;
using Windows.Storage;
namespace DrumKit
{
static class DrumsManager
{
private static StorageFolder currentDrumkitKey = null;
private static int currentDrumkitLayoutIndex = -1;
public static Dictionary<StorageFolder, Drumkit> AvailableDrumkits { get; private set; }
public static DrumkitLayoutCollection CurrentDrumkitLayouts { get; private set; }
public static DrumkitConfig CurrentDrumkitConfig { get; private set; }
public static Drumkit CurrentDrumkit
{
get {
return (currentDrumkitKey == null) ? null : AvailableDrumkits[currentDrumkitKey];
}
}
public static StorageFolder CurrentDrumkitLocation
{
get {
return currentDrumkitKey;
}
}
public static DrumkitLayout CurrentDrumkitLayout
{
get {
return (currentDrumkitLayoutIndex == -1) ? null : CurrentDrumkitLayouts.Items[currentDrumkitLayoutIndex];
}
}
private static async Task<object> DeserializeFile(StorageFile file, Type type)
{
// Open manifest file
var stream = await file.OpenReadAsync();
var iostream = stream.AsStream();
// Deserialize
XmlSerializer serializer = new XmlSerializer(type);
return serializer.Deserialize(iostream);
}
private static async Task<Drumkit> LoadDrumkit(StorageFolder f)
{
// Open manifest file
var manifest = await f.GetFileAsync("drumkit.xml");
object dk = await DeserializeFile(manifest, typeof(Drumkit));
return dk as Drumkit;
}
private static async Task FindDrumkits()
{
// Reset list
AvailableDrumkits = new Dictionary<StorageFolder, Drumkit>();
// Get 'drumkits' folder content
var folder = await ApplicationData.Current.RoamingFolder.GetFolderAsync("Drumkits");
var kits = await folder.GetFoldersAsync();
// Load each drumkit
foreach (var i in kits)
{
Drumkit kit = await LoadDrumkit(i);
if (kit != null)
AvailableDrumkits.Add(i, kit);
}
}
private static async Task LoadCurrentDrumkit(string name)
{
// Get it from the list
var current = AvailableDrumkits.FirstOrDefault(x => x.Value.Name == name);
// Doesn't exist? The default should at least exist.
if (current.Equals(default(KeyValuePair<StorageFolder, Drumkit>)))
current = AvailableDrumkits.FirstOrDefault(x => x.Value.Name == "Default");
// Not even default? Get any kit
if (current.Equals(default(KeyValuePair<StorageFolder, Drumkit>)))
current = AvailableDrumkits.FirstOrDefault();
// No drumkit? This is a serious problem
if (current.Equals(default(KeyValuePair<StorageFolder, Drumkit>)))
throw new Exception("No drumkits available.");
currentDrumkitKey = current.Key;
// Load layout and configuration
StorageFile layout = await current.Key.GetFileAsync(current.Value.LayoutFilePath);
CurrentDrumkitLayouts = await DeserializeFile(layout, typeof(DrumkitLayoutCollection)) as DrumkitLayoutCollection;
StorageFile config = await current.Key.GetFileAsync(current.Value.ConfigFilePath);
CurrentDrumkitConfig = await DeserializeFile(config, typeof(DrumkitConfig)) as DrumkitConfig;
}
public static async Task Initialize(AppSettings settings)
{
// Load drumkits
await FindDrumkits();
// Load current drumkit
await LoadCurrentDrumkit(settings.CurrentKit);
}
public static void SetLayout()
{
currentDrumkitLayoutIndex = 0;
}
}
}

View File

@ -0,0 +1,147 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SharpDX;
using SharpDX.XAudio2;
using SharpDX.Multimedia;
using System.IO;
using Windows.Storage;
namespace DrumKit
{
static class SoundManager
{
#region Data types
private class MyWave
{
public AudioBuffer Buffer { get; set; }
public uint[] DecodedPacketsInfo { get; set; }
public WaveFormat WaveFormat { get; set; }
}
#endregion
#region Private attributes
private static XAudio2 xaudio = null;
private static MasteringVoice mvoice = null;
private static Dictionary<string, MyWave> sounds = null;
private static SoundPool soundPool = null;
#endregion
#region Initialization
/// <summary>
/// Initializes the sound manager
/// </summary>
public static void Initialize()
{
xaudio = new XAudio2();
xaudio.StartEngine();
mvoice = new MasteringVoice(xaudio);
sounds = new Dictionary<string, MyWave>();
}
#endregion
#region Unload
/// <summary>
/// Unloads all the sounds
/// </summary>
public static void UnloadAll()
{
if (sounds == null)
return;
sounds.Clear();
}
/// <summary>
/// Unloads the sounds related to a drum.
/// </summary>
/// <param name="drum">The drum which will be unloaded.</param>
public static void UnloadDrum(Drum drum)
{
foreach (var i in drum.Sounds)
sounds.Remove(drum.Id + i.Intensity.ToString());
}
#endregion
#region Load
/// <summary>
/// Adds a sound to the dictionary
/// </summary>
/// <param name="key">A key associated with the sound</param>
/// <param name="file">The file which will be loaded</param>
private static async Task AddSound(string key, StorageFile file)
{
MyWave wave = new MyWave();
// Load file
var stream = await file.OpenReadAsync();
var iostream = stream.AsStream();
var soundStream = new SoundStream(iostream);
var buffer = new AudioBuffer() {
Stream = soundStream,
AudioBytes = (int)soundStream.Length,
Flags = BufferFlags.EndOfStream
};
iostream.Dispose();
// Set up information
wave.Buffer = buffer;
wave.DecodedPacketsInfo = soundStream.DecodedPacketsInfo;
wave.WaveFormat = soundStream.Format;
// Now we can initialize the soundpool
if (soundPool == null)
soundPool = new SoundPool(xaudio, wave.WaveFormat);
// Add to sound list
sounds.Add(key, wave);
}
/// <summary>
/// Loads the sounds associated with a drum
/// </summary>
public static async Task LoadDrum(Drum drum, StorageFolder root)
{
// Load each sound
foreach (var i in drum.Sounds)
{
var file = await IOHelper.GetFileRelativeAsync(root, i.Source);
await AddSound(drum.Id + i.Intensity.ToString(), file);
}
}
/// <summary>
/// Loads every drum in a drumkit.
/// </summary>
public static async Task LoadDrumkit(Drumkit kit, StorageFolder root)
{
// Load each sound
foreach (var i in kit.Drums)
await LoadDrum(i, root);
}
#endregion
#region Play
/// <summary>
/// Plays a sound
/// </summary>
/// <param name="drum_id">The id of the drum</param>
/// <param name="intensity">The intensity</param>
public static void Play(string drum_id, int intensity)
{
// Get wave info
MyWave info = null;
if (!sounds.TryGetValue(drum_id + intensity.ToString(), out info))
return;
// Play
soundPool.PlayBuffer(info.Buffer, info.DecodedPacketsInfo);
}
#endregion
}
}

View File

@ -0,0 +1,183 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
namespace DrumKit
{
static class UIManager
{
private static Dictionary<string, DrumUI> drums;
private static Dictionary<VirtualKey, string> keymap;
public static Canvas TheCanvas { get; private set; }
#region Initialization
/// <summary>
/// Initializes the ui manager
/// </summary>
public static void Initialize()
{
drums = new Dictionary<string, DrumUI>();
keymap = new Dictionary<VirtualKey, string>();
TheCanvas = new Canvas();
}
/// <summary>
/// Loads the ui stuff for drumkit
/// </summary>
public static async Task ReloadDrumkit()
{
// Delete previous
drums.Clear();
keymap.Clear();
// Load drums
foreach (var i in DrumsManager.CurrentDrumkit.Drums)
{
DrumUI drumui = new DrumUI();
await drumui.InitializeDrum(i, DrumsManager.CurrentDrumkitLocation);
drumui.PointerPressed += HandlerDrumPointerPressed;
drumui.DragDelta += HandlerDrumMoved;
TheCanvas.Children.Add(drumui.Element);
drums.Add(i.Id, drumui);
}
}
/// <summary>
/// Updates the layout.
/// </summary>
public static void ReloadLayout()
{
DrumUI drum;
foreach (var i in DrumsManager.CurrentDrumkitLayout.Drums)
if (drums.TryGetValue(i.TargetId, out drum))
drum.UpdateLayout(i, TheCanvas.ActualWidth, TheCanvas.ActualHeight);
}
/// <summary>
/// Updates the configuration.
/// </summary>
public static async Task ReloadConfig()
{
foreach (var i in DrumsManager.CurrentDrumkitConfig.Drums)
{
// Enabled and not loaded
if (i.IsEnabled && !drums.ContainsKey(i.TargetId))
{
Drum drum = DrumsManager.CurrentDrumkit.Drums.FirstOrDefault(x => x.Id == i.TargetId);
if (drum != null)
{
DrumUI drumui = new DrumUI();
await drumui.InitializeDrum(drum, DrumsManager.CurrentDrumkitLocation);
drumui.PointerPressed += HandlerDrumPointerPressed;
drumui.DragDelta += HandlerDrumMoved;
drums.Add(i.TargetId, drumui);
}
}
// Disabled and loaded
else if (!i.IsEnabled && drums.ContainsKey(i.TargetId))
{
TheCanvas.Children.Remove(drums[i.TargetId].Element);
drums.Remove(i.TargetId);
}
// Keyboard mapping
if (!keymap.ContainsKey(i.Key))
keymap.Add(i.Key, i.TargetId);
}
}
#endregion
#region Event handlers
/// <summary>
/// Handles drum hit using mouse/touchpad
/// </summary>
private static void HandlerDrumPointerPressed(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{
var button = sender as FrameworkElement;
var tag = button.Tag as string;
if (tag != null)
HandlerDrumClickedCommon(tag);
}
/// <summary>
/// Handles drum hit using keyboard
/// </summary>
public static void HandlerKeyDown(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.KeyEventArgs args)
{
string drum;
// Key repeat or something
if (args.KeyStatus.WasKeyDown)
return;
// If key in key map, perform "click"
if (keymap.TryGetValue(args.VirtualKey, out drum))
HandlerDrumClickedCommon(drum);
}
/// <summary>
/// Handles drum hit.
/// </summary>
private static void HandlerDrumClickedCommon(string drum_id)
{
SoundManager.Play(drum_id, 0);
if (DataManager.Settings.Animations)
drums[drum_id].Hit();
}
/// <summary>
/// Handles drum movement.
/// </summary>
private static void HandlerDrumMoved(object sender, Windows.UI.Xaml.Controls.Primitives.DragDeltaEventArgs e)
{
var thumb = sender as Thumb;
var tag = thumb.Tag as string;
int drum_index = -1;
if (tag != null)
drum_index = DrumsManager.CurrentDrumkitLayout.Drums.FindIndex(x => x.TargetId == tag);
if (drum_index >= 0)
{
double delta_x = e.HorizontalChange / TheCanvas.ActualWidth;
double delta_y = e.VerticalChange / TheCanvas.ActualHeight;
if (double.IsInfinity(delta_x) || double.IsInfinity(delta_y) || double.IsNaN(delta_x) || double.IsNaN(delta_y))
return;
DrumsManager.CurrentDrumkitLayout.Drums[drum_index].X += delta_x;
DrumsManager.CurrentDrumkitLayout.Drums[drum_index].Y += delta_y;
drums[tag].UpdateLayout(DrumsManager.CurrentDrumkitLayout.Drums[drum_index], TheCanvas.ActualWidth, TheCanvas.ActualHeight);
}
}
#endregion
public static void EnterEdit()
{
foreach (var i in drums)
i.Value.EnableEdit();
}
public static void ExitEdit()
{
foreach (var i in drums)
i.Value.DisableEdit();
}
}
}