Latest build (version 2.2)

This commit is contained in:
2013-11-18 20:11:53 +02:00
parent 8954fd2635
commit 9c3b53d4a6
503 changed files with 186904 additions and 1139 deletions

View File

@ -13,6 +13,7 @@
Required by Visual Studio project and item templates
-->
<ResourceDictionary Source="Common/StandardStyles.xaml"/>
<ResourceDictionary Source="Common/TextButtonStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

View File

@ -80,22 +80,10 @@ namespace DrumKit
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private async void OnSuspending(object sender, SuspendingEventArgs e)
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
try {
await DataManager.Close();
}
catch (Exception ex) {
Log.Error("Exception in OnSuspending method!");
Log.Except(ex);
}
Log.Write("Application suspended.");
//TODO:::...
deferral.Complete();
}
}

Binary file not shown.

Binary file not shown.

View File

@ -1,328 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using Windows.Storage;
namespace DrumKit.Archiving
{
public class TarballReader
{
#region Data types etc
/// <summary>
/// Tarball header structure
/// </summary>
private struct TarballHeader
{
public string FileName;
public uint FileMode;
public uint OwnerId, GroupId;
public int Size;
public DateTime LastModified;
public uint Checksum;
public byte LinkIndicator;
public string LinkedFile;
}
#endregion
#region Private attributes
private Stream stream;
private TarballHeader header;
#endregion
#region Constructor
/// <summary>
/// Creates a new instance of a tarball archive reader.
/// </summary>
public TarballReader()
{
stream = null;
header = new TarballHeader();
}
#endregion
#region Public functions (unpack)
/// <summary>
/// Unpacks a tarball in a temporary folder.
/// </summary>
/// <param name="file">An URI to the tarball file.</param>
/// <returns>Storage folder pointing to where the files were unpacked.</returns>
public async Task<StorageFolder> Unpack (Uri file)
{
var stfile = await StorageFile.GetFileFromApplicationUriAsync(file);
return await this.Unpack(stfile);
}
/// <summary>
/// Unpacks a tarball in a specified folder.
/// </summary>
/// <param name="file">An URI to the tarball file.</param>
/// <param name="destination">A folder where files will be unpacked.</param>
/// <returns>Storage folder pointing to where the files were unpacked.</returns>
public async Task<StorageFolder> Unpack(Uri file, StorageFolder destination)
{
var stfile = await StorageFile.GetFileFromApplicationUriAsync(file);
return await this.Unpack(stfile, destination);
}
/// <summary>
/// Unpacks a tarball in a temporary folder.
/// </summary>
/// <param name="file">A path to the tarball file.</param>
/// <returns>Storage folder pointing to where the files were unpacked.</returns>
public async Task<StorageFolder> Unpack(string file)
{
var stfile = await StorageFile.GetFileFromPathAsync(file);
return await this.Unpack(stfile);
}
/// <summary>
/// Unpacks a tarball in a specified folder.
/// </summary>
/// <param name="file">A path to the tarball file.</param>
/// <param name="destination">A folder where files will be unpacked.</param>
/// <returns>Storage folder pointing to where the files were unpacked.</returns>
public async Task<StorageFolder> Unpack(string file, StorageFolder destination)
{
var stfile = await StorageFile.GetFileFromPathAsync(file);
return await this.Unpack(stfile, destination);
}
/// <summary>
/// Unpacks a tarball in a temporary folder.
/// </summary>
/// <param name="file">The tarball file.</param>
/// <returns>Storage folder pointing to where the files were unpacked.</returns>
public async Task<StorageFolder> Unpack(StorageFile file)
{
// Prepare temp folder
var dest = await this.CreateTempFolder();
// Unpack
await this.Initialize(file);
await this.UnpackFiles(dest);
this.Dispose();
// Results
return dest;
}
/// <summary>
/// Unpacks a tarball in a specified folder.
/// </summary>
/// <param name="file">The tarball file.</param>
/// <param name="destination">A folder where files will be unpacked.</param>
/// <returns>Storage folder pointing to where the files were unpacked.</returns>
public async Task<StorageFolder> Unpack(StorageFile file, StorageFolder destination)
{
// Unpack
await this.Initialize(file);
await this.UnpackFiles(destination);
this.Dispose();
// Results
return destination;
}
#endregion
#region Initialize, dispose
/// <summary>
/// Performs initialization actions before unpacking (such as opening the stream).
/// </summary>
private async Task Initialize(StorageFile file)
{
var str = await file.OpenReadAsync();
this.stream = str.AsStream();
}
/// <summary>
/// Performs cleanups after unpacking finished.
/// </summary>
private void Dispose()
{
// Clean up
this.stream.Dispose();
this.stream = null;
this.header = new TarballHeader();
}
#endregion
#region Headers
/// <summary>
/// Calculates the checksum from a header.
/// </summary>
/// <param name="buffer">The header bytes</param>
private uint CalculateChecksum(byte[] buffer)
{
uint result = 0;
// Calculate sum of all bytes, with the exception of bytes 148-155
// (checksum field). These are all assumed to be 0x20.
for (int i = 0; i < buffer.Length; i++)
if (i >= 148 && i < 156)
result += 0x20;
else result += Convert.ToUInt32(buffer[i]);
// Done
return result;
}
/// <summary>
/// Converts binary data to a TarballHeader.
/// </summary>
private TarballHeader ParseHeaderFields(byte[] buffer)
{
TarballHeader header = new TarballHeader();
string temp;
// File name
temp = SharpDX.Text.ASCIIEncoding.ASCII.GetString(buffer, 0, 100).Trim('\0', ' ');
header.FileName = temp;
// File mode
temp = SharpDX.Text.ASCIIEncoding.ASCII.GetString(buffer, 100, 8).Trim('\0', ' ');
header.FileMode = (string.IsNullOrEmpty(temp)) ? 0 : Convert.ToUInt32(temp, 8);
// Owner id
temp = SharpDX.Text.ASCIIEncoding.ASCII.GetString(buffer, 108, 8).Trim('\0', ' ');
header.OwnerId = (string.IsNullOrEmpty(temp)) ? 0 : Convert.ToUInt32(temp, 8);
// Group id
temp = SharpDX.Text.ASCIIEncoding.ASCII.GetString(buffer, 116, 8).Trim('\0', ' ');
header.GroupId = (string.IsNullOrEmpty(temp)) ? 0 : Convert.ToUInt32(temp, 8);
// Size
temp = SharpDX.Text.ASCIIEncoding.ASCII.GetString(buffer, 124, 12).Trim('\0', ' ');
header.Size = (string.IsNullOrEmpty(temp)) ? 0 : Convert.ToInt32(temp, 8);
// Last modified date
temp = SharpDX.Text.ASCIIEncoding.ASCII.GetString(buffer, 136, 12).Trim('\0', ' ');
int seconds = (string.IsNullOrEmpty(temp)) ? 0 : Convert.ToInt32(temp, 8);
header.LastModified = new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(seconds).ToLocalTime();
// Checksum
temp = SharpDX.Text.ASCIIEncoding.ASCII.GetString(buffer, 148, 8).Trim('\0', ' ');
header.Checksum = (string.IsNullOrEmpty(temp)) ? 0 : Convert.ToUInt32(temp, 8);
// Link indicator
header.LinkIndicator = buffer[156];
// Linked file
temp = SharpDX.Text.ASCIIEncoding.ASCII.GetString(buffer, 157, 100).Trim('\0', ' ');
header.LinkedFile = temp;
// Done
return header;
}
/// <summary>
/// Reads a file header.
/// </summary>
/// <returns>True if another header was read, false otherwise.</returns>
private async Task<bool> ReadNextFileHeader()
{
byte[] buffer = new byte[512];
// Check current position
if (stream.Position >= stream.Length)
return false;
// Read header
await stream.ReadAsync(buffer, 0, 512);
// Parse header fields
this.header = this.ParseHeaderFields(buffer);
// Verify checksum
uint checksum = this.CalculateChecksum(buffer);
if (checksum == 256) // If 256 (only the checksum bytes different than 0), then
return false; // we most likely hit an invalid entry, probably marking the
// end of the file
if (checksum != header.Checksum)
throw new IOException("Invalid checksum!");
// Done
return true;
}
#endregion
#region File system helpers
/// <summary>
/// Creates a temporary folder.
/// </summary>
private async Task<StorageFolder> CreateTempFolder()
{
// Generate file name
string name = "tar" + DateTime.Now.Ticks.ToString();
// Create file
var temp = ApplicationData.Current.TemporaryFolder;
return await temp.CreateFolderAsync(name, CreationCollisionOption.GenerateUniqueName);
}
#endregion
#region Unpack
/// <summary>
/// Unpacks a file using the information from the header.
/// The function assumes the header was previously read.
/// </summary>
/// <param name="destination">The destination file.</param>
private async Task UnpackNextFile(StorageFile destination)
{
// Open destination file
var str = await destination.OpenAsync(FileAccessMode.ReadWrite);
var iostr = str.AsStream();
// Write data
var buffer = new byte[512];
int read = 0, total = 0;
while (total < this.header.Size)
{
read = await this.stream.ReadAsync(buffer, 0, 512);
await iostr.WriteAsync(buffer, 0, Math.Min(read, this.header.Size - total));
total += read;
}
// Cleanup
await iostr.FlushAsync();
iostr.Dispose();
}
/// <summary>
/// Unpacks the files from the loaded tarball.
/// </summary>
/// <param name="destination">Destination folder.</param>
private async Task UnpackFiles(StorageFolder destination)
{
if (this.stream == null)
throw new ArgumentNullException("No file opened!");
while (await this.ReadNextFileHeader())
{
// Directory?
if (this.header.FileName.EndsWith("/"))
await IOHelper.CreateFolderRelativeAsync(destination, this.header.FileName);
// Create file
else
{
var file = await IOHelper.CreateFileRelativeAsync(destination, this.header.FileName);
await this.UnpackNextFile(file);
}
}
}
#endregion
}
}

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 KiB

After

Width:  |  Height:  |  Size: 325 KiB

View File

@ -89,56 +89,10 @@
<image>Images/plate.png</image>
<imagePressed>Images/platePressed.png</imagePressed>
<sounds>
<sound intensity="0">Sounds/Ride04.wav</sound>
<sound intensity="0">Sounds/Ride06.wav</sound>
</sounds>
</drum>
</drums>
<!--
[Kick]
position=.41,.2
size=.3
image=ms-appx:///Assets/Drums/big_drum_of.png
sound,0=ms-appx:///Assets/Sounds/Kick07.wav
[Snare]
position=.16,.34
size=.25
image=ms-appx:///Assets/Drums/drum_of.png
sound,0=ms-appx:///Assets/Sounds/Snare08.wav
[High Tom]
position=.33,.05
size=.22
image=ms-appx:///Assets/Drums/drum_of.png
sound,0=ms-appx:///Assets/Sounds/TomHigh04.wav
[Low Tom]
position=.55,.05
size=.22
image=ms-appx:///Assets/Drums/drum_of.png
sound,0=ms-appx:///Assets/Sounds/TomLow04.wav
[Floor Tom]
position=.66,.44
size=.29
image=ms-appx:///Assets/Drums/drum_of.png
sound,0=ms-appx:///Assets/Sounds/Floor04.wav
[Hi-Hat Closed]
position=.10,.87
size=.05
image=ms-appx:///Assets/Drums/HiHat_off.png
sound,0=ms-appx:///Assets/Sounds/HiHatClosed04.wav
[Hi-Hat Opened]
position=.03,.55
size=.21
image=ms-appx:///Assets/Drums/plate_off.png
sound,0=ms-appx:///Assets/Sounds/HiHatOpen04.wav
[Crash]
position=.1,.02
size=.25
image=ms-appx:///Assets/Drums/plate_off.png
sound,0=ms-appx:///Assets/Sounds/Crash05.wav
[Ride]
position=.72,.04
size=.25
image=ms-appx:///Assets/Drums/plate_off.png
sound,0=ms-appx:///Assets/Sounds/Ride04.wav-->
</drumkit>

View File

@ -2,76 +2,222 @@
<drumkitLayoutCollection>
<items>
<!-- Standard layout - all views -->
<drumkitLayout>
<name>Standard layout</name>
<targetView>Snapped|Landscape|Filled|Portrait</targetView>
<isDefault>true</isDefault>
<items>
<!-- Standard layout - all views -->
<drumkitLayout>
<name>Standard layout</name>
<targetView>All</targetView>
<isDefault>true</isDefault>
<drums>
<drumLayout targetId="defaultkick">
<size>.3</size>
<x>.41</x>
<y>.2</y>
<zindex>0</zindex>
</drumLayout>
<drumLayout targetId="defaultsnare">
<size>.25</size>
<x>.16</x>
<y>.34</y>
<zindex>2</zindex>
<angle>61</angle>
</drumLayout>
<drumLayout targetId="defaulthitom">
<size>.22</size>
<x>.33</x>
<y>.05</y>
<zindex>1</zindex>
<angle>150</angle>
</drumLayout>
<drumLayout targetId="defaultlotom">
<size>.22</size>
<x>.55</x>
<y>.05</y>
<zindex>1</zindex>
<angle>150</angle>
</drumLayout>
<drumLayout targetId="defaultfltom">
<size>.29</size>
<x>.66</x>
<y>.44</y>
<zindex>1</zindex>
<angle>-30</angle>
</drumLayout>
<drumLayout targetId="defaulthihatcl">
<size>.055</size>
<x>.11</x>
<y>.89</y>
<zindex>3</zindex>
</drumLayout>
<drumLayout targetId="defaulthihatop">
<size>.21</size>
<x>.03</x>
<y>.55</y>
<zindex>4</zindex>
<angle>80</angle>
</drumLayout>
<drumLayout targetId="defaultcrash">
<size>.26</size>
<x>.1</x>
<y>.02</y>
<zindex>4</zindex>
<angle>80</angle>
</drumLayout>
<drumLayout targetId="defaultride">
<size>.25</size>
<x>.72</x>
<y>.04</y>
<zindex>4</zindex>
</drumLayout>
</drums>
</drumkitLayout>
<drumkitLayout>
<name>Portrait layout</name>
<targetView>Portrait</targetView>
<isDefault>true</isDefault>
<drums>
<drumLayout targetId="defaultkick">
<size>0.53359375</size>
<x>.2</x>
<y>.39</y>
<zindex>0</zindex>
<angle>-90</angle>
</drumLayout>
<drumLayout targetId="defaultsnare">
<size>0.4446614583</size>
<x>.34</x>
<y>.64</y>
<zindex>2</zindex>
<angle>-29</angle>
</drumLayout>
<drumLayout targetId="defaulthitom">
<size>0.3913020833</size>
<x>.05</x>
<y>.47</y>
<zindex>1</zindex>
<angle>60</angle>
</drumLayout>
<drumLayout targetId="defaultlotom">
<size>0.3913020833</size>
<x>.05</x>
<y>.25</y>
<zindex>1</zindex>
<angle>60</angle>
</drumLayout>
<drumLayout targetId="defaultfltom">
<size>0.5158072917</size>
<x>.44</x>
<y>.14</y>
<zindex>1</zindex>
<angle>-120</angle>
</drumLayout>
<drumLayout targetId="defaulthihatcl">
<size>0.0978255208</size>
<x>.89</x>
<y>.69</y>
<zindex>3</zindex>
<angle>-90</angle>
</drumLayout>
<drumLayout targetId="defaulthihatop">
<size>0.373515625</size>
<x>.55</x>
<y>.77</y>
<zindex>4</zindex>
<angle>-10</angle>
</drumLayout>
<drumLayout targetId="defaultcrash">
<size>0.4624479167</size>
<x>.02</x>
<y>.7</y>
<zindex>4</zindex>
<angle>-10</angle>
</drumLayout>
<drumLayout targetId="defaultride">
<size>0.4446614583</size>
<x>.04</x>
<y>.08</y>
<zindex>4</zindex>
<angle>-90</angle>
</drumLayout>
</drums>
</drumkitLayout>
<drumkitLayout>
<name>Snapped layout</name>
<targetView>Snapped</targetView>
<isDefault>true</isDefault>
<drums>
<drumLayout targetId="defaultkick">
<size>0.6</size>
<x>0.49444900512695339</x>
<y>0.32627955277760762</y>
<zindex>0</zindex>
<angle>-90</angle>
</drumLayout>
<drumLayout targetId="defaultsnare">
<size>0.5</size>
<x>0.39433132171630869</x>
<y>0.56396647930145249</y>
<zindex>2</zindex>
<angle>61</angle>
</drumLayout>
<drumLayout targetId="defaulthitom">
<size>0.44</size>
<x>0.057991533279419152</x>
<y>0.43292328516642276</y>
<zindex>1</zindex>
<angle>60</angle>
</drumLayout>
<drumLayout targetId="defaultlotom">
<size>0.44</size>
<x>0.087597298622131434</x>
<y>0.26619099378585825</y>
<zindex>1</zindex>
<angle>60</angle>
</drumLayout>
<drumLayout targetId="defaultfltom">
<size>0.58</size>
<x>0.47881852149963317</x>
<y>0.10023623943328863</y>
<zindex>1</zindex>
<angle>-120</angle>
</drumLayout>
<drumLayout targetId="defaulthihatcl">
<size>0.11</size>
<x>0.83815117835998587</x>
<y>0.80136797269185378</y>
<zindex>3</zindex>
<angle>-90</angle>
</drumLayout>
<drumLayout targetId="defaulthihatop">
<size>0.42</size>
<x>0.45826869487762456</x>
<y>0.74660433133443138</y>
<zindex>4</zindex>
<angle>-10</angle>
</drumLayout>
<drumLayout targetId="defaultcrash">
<size>0.52</size>
<x>-0.015512061119079568</x>
<y>0.62290350516637261</y>
<zindex>4</zindex>
<angle>-10</angle>
</drumLayout>
<drumLayout targetId="defaultride">
<size>0.5</size>
<x>0.019840950965881135</x>
<y>0.06086617549260457</y>
<zindex>4</zindex>
<angle>-90</angle>
</drumLayout>
</drums>
</drumkitLayout>
</items>
<drums>
<drumLayout targetId="defaultkick">
<size>.3</size>
<x>.41</x>
<y>.2</y>
<zindex>0</zindex>
</drumLayout>
<drumLayout targetId="defaultsnare">
<size>.25</size>
<x>.16</x>
<y>.34</y>
<zindex>2</zindex>
<angle>61</angle>
</drumLayout>
<drumLayout targetId="defaulthitom">
<size>.22</size>
<x>.33</x>
<y>.05</y>
<zindex>1</zindex>
<angle>150</angle>
</drumLayout>
<drumLayout targetId="defaultlotom">
<size>.22</size>
<x>.55</x>
<y>.05</y>
<zindex>1</zindex>
<angle>150</angle>
</drumLayout>
<drumLayout targetId="defaultfltom">
<size>.29</size>
<x>.66</x>
<y>.44</y>
<zindex>1</zindex>
<angle>-30</angle>
</drumLayout>
<drumLayout targetId="defaulthihatcl">
<size>.055</size>
<x>.11</x>
<y>.89</y>
<zindex>3</zindex>
</drumLayout>
<drumLayout targetId="defaulthihatop">
<size>.21</size>
<x>.03</x>
<y>.55</y>
<zindex>4</zindex>
<angle>80</angle>
</drumLayout>
<drumLayout targetId="defaultcrash">
<size>.26</size>
<x>.1</x>
<y>.02</y>
<zindex>4</zindex>
<angle>80</angle>
</drumLayout>
<drumLayout targetId="defaultride">
<size>.25</size>
<x>.72</x>
<y>.04</y>
<zindex>4</zindex>
</drumLayout>
</drums>
</drumkitLayout>
</items>
</drumkitLayoutCollection>

View File

@ -27,7 +27,10 @@
</ResourceDictionary.ThemeDictionaries>
<x:String x:Key="ChevronGlyph">&#xE26B;</x:String>
<!-- User defined brushes -->
<SolidColorBrush x:Key="ApplicationBackgroundColor" Color="#164646" />
<!-- RichTextBlock styles -->
<Style x:Key="BasicRichTextStyle" TargetType="RichTextBlock">
@ -233,6 +236,11 @@
<Setter Property="Foreground" Value="{StaticResource ApplicationSecondaryForegroundThemeBrush}"/>
</Style>
<Style x:Key="MyButtonStyle" TargetType="Button" BasedOn="{StaticResource TextButtonStyle}">
<Setter Property="Margin" Value="0,0,14,0" />
</Style>
<!--
TextRadioButtonStyle is used to style a RadioButton using subheader-styled text with no other adornment.
This style is used in the SearchResultsPage to allow selection among filters.
@ -429,8 +437,20 @@
<Setter Property="AutomationProperties.Name" Value="Video"/>
<Setter Property="Content" Value="&#xE116;"/>
</Style>
<!--
<Style x:Key="DeleteAppBarButtonStyle" TargetType="ButtonBase" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="DeleteAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Delete"/>
<Setter Property="Content" Value="&#xE106;"/>
</Style>
<Style x:Key="SaveAppBarButtonStyle" TargetType="ButtonBase" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="SaveAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Save"/>
<Setter Property="Content" Value="&#xE105;"/>
</Style>
<!--
<Style x:Key="SkipBackAppBarButtonStyle" TargetType="ButtonBase" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="SkipBackAppBarButton"/>
@ -443,16 +463,7 @@
<Setter Property="Content" Value="&#xE101;"/>
</Style>
<Style x:Key="SaveAppBarButtonStyle" TargetType="ButtonBase" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="SaveAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Save"/>
<Setter Property="Content" Value="&#xE105;"/>
</Style>
<Style x:Key="DeleteAppBarButtonStyle" TargetType="ButtonBase" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="DeleteAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Delete"/>
<Setter Property="Content" Value="&#xE106;"/>
</Style>
<Style x:Key="DiscardAppBarButtonStyle" TargetType="ButtonBase" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="DiscardAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Discard"/>
@ -523,12 +534,15 @@
<Setter Property="AutomationProperties.Name" Value="Photo"/>
<Setter Property="Content" Value="&#xE114;"/>
</Style>
-->
<Style x:Key="SettingsAppBarButtonStyle" TargetType="ButtonBase" BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId" Value="SettingsAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Settings"/>
<Setter Property="Content" Value="&#xE115;"/>
<Setter Property="Content" Value="&#xE115;" />
</Style>
-->
<!--
@ -1833,4 +1847,10 @@
</Setter.Value>
</Setter>
</Style>
<SolidColorBrush x:Key="ListViewItemSelectedBackgroundThemeBrush" Color="#075369"></SolidColorBrush>
<SolidColorBrush x:Key="ListViewItemPointerOverBackgroundThemeBrush" Color="#30ffffff"></SolidColorBrush>
<SolidColorBrush x:Key="ListViewItemSelectedPointerOverBackgroundThemeBrush" Color="#ab188DAD"></SolidColorBrush>
<SolidColorBrush x:Key="ListViewItemSelectedPointerOverBorderThemeBrush" Color="#ab188DAD"></SolidColorBrush>
</ResourceDictionary>

View File

@ -0,0 +1,155 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="TextBoxBackgroundThemeBrush" Color="#ffff" />
<SolidColorBrush x:Key="TextBoxBorderThemeBrush" Color="#efff" />
<SolidColorBrush x:Key="TextBoxDisabledBackgroundThemeBrush" Color="Transparent" />
<SolidColorBrush x:Key="TextBoxDisabledBorderThemeBrush" Color="#66FFFFFF" />
<SolidColorBrush x:Key="TextBoxDisabledForegroundThemeBrush" Color="#FF666666" />
<SolidColorBrush x:Key="TextBoxForegroundThemeBrush" Color="#f000" />
<x:Double x:Key="TextControlBackgroundThemeOpacity">0</x:Double>
<x:Double x:Key="TextControlBorderThemeOpacity">0</x:Double>
<x:Double x:Key="TextControlPointerOverBackgroundThemeOpacity">0.17</x:Double>
<x:Double x:Key="TextControlPointerOverBorderThemeOpacity">0.17</x:Double>
<x:Double x:Key="TextControlThemeMinHeight">32</x:Double>
<x:Double x:Key="TextControlThemeMinWidth">64</x:Double>
<Thickness x:Key="TextControlBorderThemeThickness">2</Thickness>
<Thickness x:Key="TextControlThemePadding">10,3,10,5</Thickness>
<Style x:Key="MyTextBoxStyle" TargetType="TextBox">
<Setter Property="MinWidth" Value="{StaticResource TextControlThemeMinWidth}" />
<Setter Property="MinHeight" Value="{StaticResource TextControlThemeMinHeight}" />
<Setter Property="Foreground" Value="{StaticResource TextBoxForegroundThemeBrush}" />
<Setter Property="Background" Value="{StaticResource TextBoxBackgroundThemeBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource TextBoxBorderThemeBrush}" />
<Setter Property="BorderThickness" Value="{StaticResource TextControlBorderThemeThickness}" />
<Setter Property="FontFamily" Value="{StaticResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{StaticResource ControlContentThemeFontSize}" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
<Setter Property="Padding" Value="{StaticResource TextControlThemePadding}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TextBoxDisabledBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TextBoxDisabledBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TextBoxDisabledForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="EditIconElement"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="White" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="0" />
<DoubleAnimation Storyboard.TargetName="BorderElement"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="0" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="White" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="0.1" />
<DoubleAnimation Storyboard.TargetName="BorderElement"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="0.1" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="White" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="EditIconElement"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="Gray" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="0" />
</Grid.ColumnDefinitions>
<Border x:Name="BackgroundElement"
Background="{TemplateBinding Background}"
Margin="{TemplateBinding BorderThickness}"
Grid.ColumnSpan="3"/>
<Border x:Name="BorderElement"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Grid.ColumnSpan="3"/>
<TextBlock x:Name="EditIconElement"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Margin="5,5,0,5"
Foreground="#8fff"
FontFamily="{StaticResource SymbolThemeFontFamily}"
FontStyle="Normal" FontSize="14"
Opacity=".6"
Text="&#xe104;" />
<ScrollViewer x:Name="ContentElement"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
IsTabStop="False"
ZoomMode="Disabled"
Grid.Column="1"/>
<Button x:Name="DeleteButton"
IsTabStop="False"
Grid.Column="2"
Visibility="Collapsed"
Opacity="0"
IsEnabled="False" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DrumKit
{
class ControllerException : Exception
{
public ControllerException() :
base() { }
public ControllerException(string message) :
base(message) { }
public ControllerException(string message, Exception innerException) :
base(message, innerException) { }
}
}

View File

@ -0,0 +1,440 @@
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
/// <summary>
/// Gets application's installation info
/// </summary>
public static AppInstallInfo InstallInfo
{
get
{
return (DataRepo == null) ? null : DataRepo.InstallInfo;
}
}
/// <summary>
/// Gets application's settings.
/// </summary>
public static AppSettings Settings
{
get
{
return (DataRepo == null) ? null : DataRepo.Settings;
}
}
/// <summary>
/// Gets the list of available drumkits.
/// </summary>
public static Dictionary<string, Drumkit> AvailableDrumkits
{
get
{
return (DrumkitRepo == null) ? null : DrumkitRepo.AvailableDrumKits;
}
}
/// <summary>
/// Gets or sets the current drumkit.
/// </summary>
public static Drumkit CurrentDrumkit
{
get
{
return AvailableDrumkits[CurrentDrumkitName];
}
set
{
CurrentDrumkitName = value.Name;
}
}
/// <summary>
/// Gets the current drumkit names.
/// </summary>
public static string CurrentDrumkitName { get; private set; }
/// <summary>
/// Gets the current drumkit layouts.
/// </summary>
public static DrumkitLayoutCollection CurrentLayouts { get; private set; }
/// <summary>
/// Gets the current drums configuration.
/// </summary>
public static DrumkitConfig CurrentConfig { get; private set; }
/// <summary>
/// Gets or sets the master volume.
/// </summary>
public static float MasterVolume
{
get {
return Settings.MasterVolume;
}
set {
Settings.MasterVolume = value;
SoundPool.MasterVolume = value;
}
}
#endregion
#region Events
/// <summary>
/// Triggered when the progress of the initialize method changed.
/// </summary>
public static event EventHandler<KeyValuePair<int, string>> ProgressChanged;
#endregion
#region Initialization
/// <summary>
/// Initializes everything.
/// </summary>
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();
}
/// <summary>
/// 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.
/// </summary>
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;
}
/// <summary>
/// Initializes the data: loads settings, app install info, performs after install actions.
/// </summary>
private static async Task InitializeData()
{
DataRepo = new Repository.DataRepository();
await DataRepo.Initialize(ApplicationData.Current);
}
/// <summary>
/// Initializes the drumkit repository: loads information about every drumkit
/// </summary>
private static async Task InitializeDrumkits()
{
StorageFolder repo = await ApplicationData.Current.RoamingFolder.CreateFolderAsync("Drumkits", CreationCollisionOption.OpenIfExists);
DrumkitRepo = new Repository.DrumkitRepository();
await DrumkitRepo.Initialize(repo);
}
/// <summary>
/// Initializes the sound repository: loads all the drums associated with the current drumkit, creates soundpool.
/// </summary>
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;
}
/// <summary>
/// Determines the current drumkit
/// </summary>
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!");
}
/// <summary>
/// Loads the drum images
/// </summary>
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
/// <summary>
/// Resets to factory settings
/// </summary>
public static async Task FactoryReset()
{
await ApplicationData.Current.ClearAsync();
}
#region Private methods
/// <summary>
/// Reports current progress (calls event).
/// </summary>
/// <param name="percent">Percentage of task completed.</param>
/// <param name="info">What is happening, like a message to the user.</param>
private static void ReportProgress(int percent, string info)
{
if (ProgressChanged != null)
ProgressChanged(null, new KeyValuePair<int, string>(percent, info));
}
#endregion
#region Playback
/// <summary>
/// Plays a sound if loaded.
/// </summary>
/// <param name="drum_id">ID of the drum the sound belongs to.</param>
/// <param name="intensity">Intensity of sound</param>
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
/// <summary>
/// Deletes a drumkit from the system.
/// </summary>
/// <param name="name">Name (identifier) of drumkit</param>
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);
}
/// <summary>
/// Installs a drumkit package.
/// </summary>
/// <param name="tarball">A .tar file</param>
public static async Task InstallDrumkit(StorageFile tarball)
{
await DrumkitRepo.InstallTarball(tarball);
}
/// <summary>
/// Exports a drumkit package.
/// </summary>
/// <param name="drumkit_key">The key of the drumkit to export</param>
/// <param name="tarball">The destination file</param>
public static async Task ExportDrumkit(string drumkit_key, StorageFile tarball)
{
await DrumkitRepo.ExportTarball(drumkit_key, tarball);
}
/// <summary>
/// Creates a new layout
/// </summary>
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
/// <summary>
/// Saves the drum configuration settings for current drumkit.
/// </summary>
public static void SaveConfig()
{
saveConfigTimer.Stop();
saveConfigTimer.Start();
}
/// <summary>
/// Saves the drum layout settings for current drumkit.
/// </summary>
public static void SaveLayout()
{
saveLayoutTimer.Stop();
saveLayoutTimer.Start();
}
/// <summary>
/// Saves the applications settings.
/// </summary>
public static void SaveSettings()
{
saveSettingsTimer.Stop();
saveSettingsTimer.Start();
}
/// <summary>
/// Save settings timer.
/// </summary>
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();
}
/// <summary>
/// Save layouts timer
/// </summary>
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();
}
/// <summary>
/// Save drum configuration timer.
/// </summary>
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
/// <summary>
/// Saves settings and other stuff
/// </summary>
public static void Dispose()
{
DrumkitRepo.Dispose();
SoundRepository.Dispose();
SoundPool.Dispose();
}
}
}

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using System.Reflection;
namespace DrumKit
{
[XmlType("DrumkitInstalled")]
public class AppInstallInfo
{
[XmlElement("when")]
public DateTime When { get; set; }
[XmlElement("version")]
public int Version { get; set; }
public AppInstallInfo()
{
this.When = DateTime.Now;
var ver = typeof(AppInstallInfo).GetTypeInfo().Assembly.GetName().Version;
this.Version = ver.Major * 1000 + ver.Minor;
}
}
}

View File

@ -19,11 +19,23 @@ namespace DrumKit
[XmlElement("animations")]
public bool Animations { get; set; }
[XmlElement("masterVolume")]
public float MasterVolume { get; set; }
[XmlElement("debugMode")]
public bool DebugMode { get; set; }
[XmlElement("polyphony")]
public int Polyphony { get; set; }
public AppSettings()
{
this.CurrentKit = "Default";
this.ShowKeyBindings = false;
this.Animations = true;
this.MasterVolume = 0.8f;
this.DebugMode = false;
this.Polyphony = 64;
}
}
}

View File

@ -26,12 +26,24 @@ namespace DrumKit
[XmlElement("image")]
public string ImageSource { get; set; }
/// <summary>
/// Gets or sets the image loaded into memory.
/// </summary>
[XmlIgnore()]
public Windows.UI.Xaml.Media.ImageSource LoadedImageSource { get; set; }
/// <summary>
/// Gets or sets the image uri.
/// </summary>
[XmlElement("imagePressed")]
public string ImagePressedSource { get; set; }
/// <summary>
/// Gets or sets the pressed image loaded into memory.
/// </summary>
[XmlIgnore()]
public Windows.UI.Xaml.Media.ImageSource LoadedImagePressedSource { get; set; }
/// <summary>
/// Gets or sets the list of sound sources.
/// </summary>
@ -45,6 +57,10 @@ namespace DrumKit
this.Name = null;
this.ImageSource = null;
this.ImagePressedSource = null;
this.LoadedImageSource = null;
this.LoadedImagePressedSource = null;
this.Sounds = new List<SoundSource>();
}

View File

@ -36,9 +36,30 @@ namespace DrumKit
[XmlElement("volumeR")]
public double VolumeR { get; set; }
[XmlElement("vkey")]
[XmlIgnore()]
public Windows.System.VirtualKey Key { get; set; }
[XmlElement("vkey")]
public string KeyString
{
get {
if (Enum.IsDefined(typeof(Windows.System.VirtualKey), this.Key))
return Enum.GetName(typeof(Windows.System.VirtualKey), this.Key);
return Convert.ToString((int)this.Key);
}
set
{
Windows.System.VirtualKey key;
if (Enum.TryParse(value, out key))
this.Key = key;
else this.Key = (Windows.System.VirtualKey) int.Parse(value);
}
}
public DrumConfig()
{
this.TargetId = null;

View File

@ -22,8 +22,29 @@ namespace DrumKit
[XmlElement("layoutfile")]
public string LayoutFilePath { get; set; }
[XmlIgnore()]
public Dictionary<string, Drum> Drums { get; private set; }
[XmlArray("drums")]
public List<Drum> Drums { get; set; }
public Drum[] DrumsList {
get {
List<Drum> drums = new List<Drum>();
foreach (var i in Drums)
drums.Add(i.Value);
return drums.ToArray();
}
set {
foreach (var i in value)
Drums.Add(i.Id, i);
}
}
[XmlIgnore()]
public Windows.Storage.StorageFolder RootFolder { get; set; }
public Drumkit()
{
@ -31,7 +52,8 @@ namespace DrumKit
this.Description = null;
this.ConfigFilePath = null;
this.LayoutFilePath = null;
this.Drums = new List<Drum>();
this.Drums = new Dictionary<string,Drum>();
this.RootFolder = null;
}
}
}

View File

@ -10,7 +10,35 @@ namespace DrumKit
[XmlType("drumkitConfig")]
public class DrumkitConfig
{
[XmlIgnore()]
public Dictionary<string, DrumConfig> Drums { get; private set; }
[XmlArray("drums")]
public List<DrumConfig> Drums { get; set; }
public DrumConfig[] DrumsList
{
get
{
List<DrumConfig> configs = new List<DrumConfig>();
foreach (var i in Drums)
configs.Add(i.Value);
return configs.ToArray();
}
set
{
foreach (var i in value)
Drums.Add(i.TargetId, i);
}
}
/// <summary>
/// Constructor
/// </summary>
public DrumkitConfig()
{
this.Drums = new Dictionary<string, DrumConfig>();
}
}
}

View File

@ -17,7 +17,7 @@ namespace DrumKit
public DrumkitLayoutTargetView TargetView { get; set; }
[XmlElement("targetView")]
private string TargetViewSerialize
public string TargetViewSerialize
{
get
{
@ -65,15 +65,36 @@ namespace DrumKit
[XmlElement("isDefault")]
public bool IsDefault { get; set; }
[XmlIgnore()]
public Dictionary<string, DrumLayout> Drums { get; set; }
[XmlArray("drums")]
public List<DrumLayout> Drums { get; set; }
public DrumLayout[] DrumsList
{
get
{
List<DrumLayout> layouts = new List<DrumLayout>();
foreach (var i in this.Drums)
layouts.Add(i.Value);
return layouts.ToArray();
}
set
{
foreach (var i in value)
this.Drums.Add(i.TargetId, i);
}
}
public DrumkitLayout()
{
this.Name = null;
this.IsDefault = false;
this.Drums = new List<DrumLayout>();
this.Drums = new Dictionary<string, DrumLayout>();
this.TargetView = DrumkitLayoutTargetView.All;
}
}

17
DrumKit/Domain/Sound.cs Normal file
View File

@ -0,0 +1,17 @@
using SharpDX.Multimedia;
using SharpDX.XAudio2;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DrumKit
{
public struct Sound
{
public AudioBuffer Buffer { get; set; }
public uint[] DecodedPacketsInfo { get; set; }
public WaveFormat WaveFormat { get; set; }
}
}

View File

@ -106,11 +106,49 @@
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="Archiving\TarballReader.cs" />
<Compile Include="Controller\DataController.cs" />
<Compile Include="Controller\ControllerException.cs" />
<Compile Include="Domain\AppInstallInfo.cs" />
<Compile Include="Domain\AppSettings.cs" />
<Compile Include="IOHelper.cs" />
<Compile Include="Domain\Sound.cs" />
<Compile Include="Recorder.cs" />
<Compile Include="UI\DrumPlayUI.xaml.cs">
<DependentUpon>DrumPlayUI.xaml</DependentUpon>
</Compile>
<Compile Include="UI\DrumEditUI.xaml.cs">
<DependentUpon>DrumEditUI.xaml</DependentUpon>
</Compile>
<Compile Include="UI\EditorPage.xaml.cs">
<DependentUpon>EditorPage.xaml</DependentUpon>
</Compile>
<Compile Include="UI\Settings\LayoutsSettingsControl.xaml.cs">
<DependentUpon>LayoutsSettingsControl.xaml</DependentUpon>
</Compile>
<Compile Include="Utils\UIHelper.cs" />
<Compile Include="UI\Settings\ExperimentsSettingsControl.xaml.cs">
<DependentUpon>ExperimentsSettingsControl.xaml</DependentUpon>
</Compile>
<Compile Include="UI\CommonControls\FileControl.xaml.cs">
<DependentUpon>FileControl.xaml</DependentUpon>
</Compile>
<Compile Include="UI\Settings\DrumsSettingsControl.xaml.cs">
<DependentUpon>DrumsSettingsControl.xaml</DependentUpon>
</Compile>
<Compile Include="UI\Settings\DrumkitsSettingsControl.xaml.cs">
<DependentUpon>DrumkitsSettingsControl.xaml</DependentUpon>
</Compile>
<Compile Include="UI\Settings\GeneralSettingsControl.xaml.cs">
<DependentUpon>GeneralSettingsControl.xaml</DependentUpon>
</Compile>
<Compile Include="Repository\LogRepository.cs" />
<Compile Include="Repository\DataRepository.cs" />
<Compile Include="Repository\SoundRepository.cs" />
<Compile Include="UI\SettingsPage.xaml.cs">
<DependentUpon>SettingsPage.xaml</DependentUpon>
</Compile>
<Compile Include="Repository\RepositoryException.cs" />
<Compile Include="Utils\IOHelper.cs" />
<Compile Include="Log.cs" />
<Compile Include="Managers\DataManager.cs" />
<Compile Include="Domain\Drum.cs" />
<Compile Include="Domain\DrumConfig.cs" />
<Compile Include="Domain\Drumkit.cs" />
@ -119,26 +157,26 @@
<Compile Include="Domain\DrumkitLayoutCollection.cs" />
<Compile Include="Domain\DrumkitLayoutTargetView.cs" />
<Compile Include="Domain\DrumLayout.cs" />
<Compile Include="Managers\DrumsManager.cs" />
<Compile Include="Managers\UIManager.cs" />
<Compile Include="UI\DrumUI.cs" />
<Compile Include="Repository\DrumkitRepository.cs" />
<Compile Include="UI\LoadingPage.xaml.cs">
<DependentUpon>LoadingPage.xaml</DependentUpon>
</Compile>
<Compile Include="UI\MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
<Compile Include="Recorder.cs" />
<Compile Include="Managers\SoundManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SoundPool.cs" />
<Compile Include="Domain\SoundSource.cs" />
<Compile Include="UI\Settings\LogControl.xaml.cs">
<DependentUpon>LogControl.xaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
<Content Include="Assets\ApplicationData.tar" />
<Content Include="Features.txt" />
<None Include="Build\7z.exe" />
<None Include="Build\ApplicationData\Drumkits\Default\config.xml" />
<None Include="Build\ApplicationData\Drumkits\Default\drumkit.xml" />
@ -185,6 +223,51 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Common\TextButtonStyles.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Page>
<Page Include="UI\DrumPlayUI.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UI\DrumEditUI.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UI\EditorPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UI\Settings\LayoutsSettingsControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UI\Settings\ExperimentsSettingsControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UI\CommonControls\FileControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UI\Settings\DrumsSettingsControl.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="UI\Settings\DrumkitsSettingsControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UI\Settings\GeneralSettingsControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UI\SettingsPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UI\LoadingPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@ -193,6 +276,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="UI\Settings\LogControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Reference Include="SharpDX, Version=2.4.2.0, Culture=neutral, PublicKeyToken=627a3d6d1956f55a, processorArchitecture=MSIL">
@ -204,7 +291,12 @@
<HintPath>..\..\..\..\WebDownloads\SharpDX242\Bin\Signed-winrt\SharpDX.XAudio2.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup />
<ItemGroup>
<ProjectReference Include="..\Tarball\Tarball.csproj">
<Project>{5cb567d7-572e-4bae-802f-7e3f62cddf64}</Project>
<Name>Tarball</Name>
</ProjectReference>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '11.0' ">
<VisualStudioVersion>11.0</VisualStudioVersion>
</PropertyGroup>

10
DrumKit/Features.txt Normal file
View File

@ -0,0 +1,10 @@
Feature ideas:
* drum hit intensity
* audio effects (echo & stuff)
* additional drum sets
* create/delete drums
* create drum kits
* z index in editor
* recording
* sequencer

View File

@ -10,54 +10,42 @@ namespace DrumKit
{
static class Log
{
private static StreamWriter output = null;
public static async Task Initialize()
{
// Create "Logs" folder if not created
var folder = await ApplicationData.Current.RoamingFolder.CreateFolderAsync("AppLogs", CreationCollisionOption.OpenIfExists);
// Create a log file
var file = await folder.CreateFileAsync(DateTime.Now.Ticks.ToString() + ".csv", CreationCollisionOption.GenerateUniqueName);
// Open stream
var stream = await file.OpenAsync(FileAccessMode.ReadWrite);
var iostream = stream.AsStream();
output = new StreamWriter(iostream);
output.AutoFlush = true;
// Write an initial message
Write("Session started");
// Initialize the log repository
await Repository.LogRepository.Initialize(folder);
}
public static void Write(string format, params object[] args)
{
if (output == null) return;
// Prepare data
string res = string.Format(format, args);
string final = string.Format("{0} INFO: {1}", DateTime.Now, res);
// Write data
output.WriteLine("{0},Information,{1}", DateTime.Now, res);
// Write
Repository.LogRepository.WriteLine(final);
}
public static void Error(string format, params object[] args)
{
if (output == null) return;
// Prepare data
string res = string.Format(format, args);
string final = string.Format("{0} ERROR: {1}", DateTime.Now, res);
// Write data
output.WriteLine("{0},Error,{1}", DateTime.Now, res);
// Write
Repository.LogRepository.WriteLine(final);
}
public static void Except(Exception ex)
{
if (output == null) return;
// Prepare data
string final = string.Format("{0} EXCEPTION: {1}", DateTime.Now, ex.ToString());
// Prepare
string stack = ex.StackTrace.Replace("\n", ",,,,");
// Write data
output.WriteLine("{0},Exception,{1},{2},{3}", DateTime.Now, ex.Message, ex.Source, stack);
// Write
Repository.LogRepository.WriteLine(final);
}
}
}

View File

@ -1,179 +0,0 @@
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

@ -1,120 +0,0 @@
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

@ -1,147 +0,0 @@
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

@ -1,183 +0,0 @@
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();
}
}
}

View File

@ -240,7 +240,6 @@
<Language Code="pt-br" InMinimumRequirementSet="true" />
<Language Code="pt-pt" InMinimumRequirementSet="true" />
<Language Code="quc-latn" InMinimumRequirementSet="false" />
<Language Code="qut" InMinimumRequirementSet="false" />
<Language Code="qut-gt" InMinimumRequirementSet="false" />
<Language Code="qut-latn" InMinimumRequirementSet="false" />
<Language Code="quz" InMinimumRequirementSet="false" />
@ -292,9 +291,10 @@
<Language Code="ti" InMinimumRequirementSet="false" />
<Language Code="ti-et" InMinimumRequirementSet="false" />
<Language Code="tk-cyrl" InMinimumRequirementSet="false" />
<Language Code="tk-cyrl-tr" InMinimumRequirementSet="false" />
<Language Code="tk-latn" InMinimumRequirementSet="false" />
<Language Code="tk-latn-tr" InMinimumRequirementSet="false" />
<Language Code="tk-tm" InMinimumRequirementSet="false" />
<Language Code="tk-tr" InMinimumRequirementSet="false" />
<Language Code="tn" InMinimumRequirementSet="false" />
<Language Code="tn-bw" InMinimumRequirementSet="false" />
<Language Code="tn-za" InMinimumRequirementSet="false" />
@ -342,11 +342,13 @@
<ReservedName>DrumKit</ReservedName>
</ReservedNames>
</ProductReservedInfo>
<AccountPackageIdentityNames />
<AccountPackageIdentityNames>
<MainPackageIdentityName>35555TiberiuChibici.Harmonia</MainPackageIdentityName>
</AccountPackageIdentityNames>
<PackageInfoList LandingUrl="https://appdev.microsoft.com:443/StorePortals/Developer/Catalog/ReleaseAnchor/a07735fd-3955-4470-aa48-5356c8ae5c91">
<PackageInfo>
<PackageArchitecture>neutral</PackageArchitecture>
<PackageMaxArchitectureVersion>1.0.0.6</PackageMaxArchitectureVersion>
<PackageMaxArchitectureVersion>2.1.0.26</PackageMaxArchitectureVersion>
</PackageInfo>
</PackageInfoList>
</StoreAssociation>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest">
<Identity Name="35555TiberiuChibici.DrumKit" Publisher="CN=B6F45FE5-D749-4D29-874C-8323B266F3C8" Version="1.1.0.14" />
<Identity Name="35555TiberiuChibici.DrumKit" Publisher="CN=B6F45FE5-D749-4D29-874C-8323B266F3C8" Version="2.2.0.27" />
<Properties>
<DisplayName>DrumKit</DisplayName>
<PublisherDisplayName>Tiberiu Chibici</PublisherDisplayName>
@ -19,7 +19,9 @@
<DefaultTile ShowName="allLogos" WideLogo="Assets\Logos\WideLogo.png" />
<SplashScreen Image="Assets\Logos\SplashScreen.png" />
<InitialRotationPreference>
<Rotation Preference="portrait" />
<Rotation Preference="landscape" />
<Rotation Preference="portraitFlipped" />
<Rotation Preference="landscapeFlipped" />
</InitialRotationPreference>
</VisualElements>

View File

@ -8,9 +8,9 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTitle("DrumKit")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyCompany("Chibici Tiberiu")]
[assembly: AssemblyProduct("DrumKit")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyCopyright("Copyright © Chibici Tiberiu 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@ -23,7 +23,7 @@ using System.Runtime.InteropServices;
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyVersion("2.2.*")]
//[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]

View 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()
{
}
}
}

View 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();
}
}
}

View 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);
}
}
}

View 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) { }
}
}

View 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();
}
}
}

View File

@ -9,33 +9,74 @@ using SharpDX.Multimedia;
namespace DrumKit
{
class SoundPool
public class SoundPool
{
List<SourceVoice> voices;
private XAudio2 Device { get; set; }
private MasteringVoice MasterVoice { get; set; }
private Queue<SourceVoice> Channels { get; set; }
public SoundPool(XAudio2 device, WaveFormat format)
/// <summary>
/// Gets or sets the master volume
/// </summary>
public float MasterVolume
{
voices = new List<SourceVoice>();
get {
return this.MasterVoice.Volume;
}
for (int i = 0; i < 64; i++)
voices.Add(new SourceVoice(device, format, true));
set {
this.MasterVoice.SetVolume(value);
}
}
/// <summary>
/// Initializes a new sound pool.
/// </summary>
/// <param name="poly">How many sounds will be able to play simultaneously. Default is 64.</param>
public SoundPool(WaveFormat format, int poly = 64)
{
// Create and initialize device
this.Device = new XAudio2();
this.Device.StartEngine();
// Create voices
this.MasterVoice = new MasteringVoice(this.Device);
this.Channels = new Queue<SourceVoice>();
for (int i = 0; i < poly; i++)
{
SourceVoice voice = new SourceVoice(this.Device, format, true);
this.Channels.Enqueue(voice);
}
}
public void PlayBuffer(AudioBuffer buffer, uint[] packetinfo)
/// <summary>
/// Plays a sound buffer through one of the free channels.
/// </summary>
/// <param name="sound">The sound object</param>
public void PlayBuffer(Sound sound, float volumeL = 1.0f, float volumeR = 1.0f)
{
int preferred = -1;
float[] volumes = { volumeL, volumeR };
for (int i = 0; i < voices.Count; i++)
if (voices[i].State.BuffersQueued == 0)
preferred = i;
SourceVoice top = this.Channels.Dequeue();
top.Stop();
top.FlushSourceBuffers();
top.SubmitSourceBuffer(sound.Buffer, sound.DecodedPacketsInfo);
top.SetChannelVolumes(2, volumes);
top.Start();
this.Channels.Enqueue(top);
}
if (preferred != -1)
{
// voices[preferred].FlushSourceBuffers();
voices[preferred].SubmitSourceBuffer(buffer, packetinfo);
voices[preferred].Start();
}
/// <summary>
/// Cleans up used resources
/// </summary>
public void Dispose()
{
this.Channels.Clear();
this.MasterVoice.Dispose();
Device.StopEngine();
Device.Dispose();
}
}
}

View File

@ -0,0 +1,36 @@
<UserControl
x:Class="DrumKit.FileControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DrumKit"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="120"
d:DesignWidth="400">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Name="textName" Style="{StaticResource TitleTextStyle}"
VerticalAlignment="Center"
Margin="0,0,0,8">Test</TextBlock>
<Image Grid.Row="1" Name="image"
VerticalAlignment="Stretch"
HorizontalAlignment="Left" Width="120"/>
<Button Name="buttonBrowse" Style="{StaticResource TextButtonStyle}"
Grid.Column="1" Margin="10,5,10,5">...</Button>
</Grid>
</UserControl>

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
namespace DrumKit
{
public sealed partial class FileControl : UserControl
{
public FileControl()
{
this.InitializeComponent();
}
}
}

211
DrumKit/UI/DrumEditUI.xaml Normal file
View File

@ -0,0 +1,211 @@
<UserControl
x:Class="DrumKit.DrumEditUI"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DrumKit"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400"
SizeChanged="DrumEditUl_SizeChanged">
<UserControl.Resources>
<!-- Translation thumb -->
<SolidColorBrush x:Key="TranslationThumbBackgroundBrush" Color="Transparent" />
<LinearGradientBrush x:Key="TranslationThumbBackgroundFocusedBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#2fff" Offset="1" />
<GradientStop Color="#5fff" Offset="0" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="TranslationThumbBackgroundPressedBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#1fff" Offset="1" />
<GradientStop Color="#3fff" Offset="0" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="TranslationThumbBorderBrush" StartPoint="0,0" EndPoint="0,1" >
<GradientStop Color="#2fff" Offset="1" />
<GradientStop Color="#5fff" Offset="0" />
</LinearGradientBrush>
<!-- Drum name background -->
<LinearGradientBrush x:Key="DrumNameBackgroundBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#0000" Offset="1" />
<GradientStop Color="#2000" Offset="0.7" />
<GradientStop Color="#a000" Offset="0" />
</LinearGradientBrush>
<!-- Round thumb -->
<SolidColorBrush x:Key="RoundThumbBackgroundBrush" Color="WhiteSmoke" />
<SolidColorBrush x:Key="RoundThumbBorderBrush" Color="LightGray" />
<SolidColorBrush x:Key="RoundThumbForegroundBrush" Color="Gray" />
<!-- Rotation thumb -->
<SolidColorBrush x:Key="RotationTranslationThumbBackgroundBrush" Color="Coral" />
<SolidColorBrush x:Key="RotationTranslationThumbBorderBrush" Color="LightCoral" />
<SolidColorBrush x:Key="RotationDrumForegroundBrush" Color="Brown" />
<!-- Translation thumb style -->
<Style x:Name="TranslationThumbStyle" TargetType="Thumb">
<Setter Property="Background" Value="{StaticResource TranslationThumbBackgroundBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource TranslationThumbBorderBrush}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" >
<Storyboard>
<DoubleAnimation Storyboard.TargetName="normalRectangle"
Storyboard.TargetProperty="Opacity"
Duration="0" To="1" />
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="focusedRectangle"
Storyboard.TargetProperty="Opacity"
Duration="0" To="1" />
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="pressedRectangle"
Storyboard.TargetProperty="Opacity"
Duration="0" To="1" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle Name="normalRectangle"
Fill="{TemplateBinding Background}"
Stroke="{TemplateBinding BorderBrush}"
StrokeThickness="{TemplateBinding BorderThickness}"
Opacity="0" />
<Rectangle Name="focusedRectangle"
Fill="{StaticResource TranslationThumbBackgroundFocusedBrush}"
Stroke="{TemplateBinding BorderBrush}"
StrokeThickness="{TemplateBinding BorderThickness}"
Opacity="0" />
<Rectangle Name="pressedRectangle"
Fill="{StaticResource TranslationThumbBackgroundPressedBrush}"
Stroke="{TemplateBinding BorderBrush}"
StrokeThickness="{TemplateBinding BorderThickness}"
Opacity="0" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Round thumb style -->
<Style x:Key="RoundThumbStyle" TargetType="Thumb">
<Setter Property="Background" Value="{StaticResource RoundThumbBackgroundBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource RoundThumbBorderBrush}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Foreground" Value="{StaticResource RoundThumbForegroundBrush}" />
<Setter Property="Height" Value="16" />
<Setter Property="Width" Value="16" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Grid>
<Ellipse
Fill="{TemplateBinding Background}"
Stroke="{TemplateBinding BorderBrush}"
StrokeThickness="{TemplateBinding BorderThickness}" />
<TextBlock
Foreground="{TemplateBinding Foreground}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Text="{TemplateBinding Tag}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Rotation thumb style -->
<Style x:Key="RotationThumbStyle" TargetType="Thumb" BasedOn="{StaticResource RoundThumbStyle}" >
<Setter Property="Background" Value="{StaticResource RotationTranslationThumbBackgroundBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource RotationTranslationThumbBorderBrush}" />
<Setter Property="Foreground" Value="{StaticResource RotationDrumForegroundBrush}" />
<Setter Property="FontFamily" Value="{StaticResource SymbolThemeFontFamily}" />
<Setter Property="FontSize" Value="10" />
<Setter Property="FontStyle" Value="Normal" />
<Setter Property="Tag" Value="&#xe14a;" />
</Style>
</UserControl.Resources>
<Grid>
<Grid Name="rotateGrid" IsHitTestVisible="False">
<Image Name="image" IsHitTestVisible="False"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
</Grid>
<Border HorizontalAlignment="Stretch"
VerticalAlignment="Top"
IsHitTestVisible="False"
Background="{StaticResource DrumNameBackgroundBrush}">
<TextBlock
IsHitTestVisible="False"
Name="nameText" HorizontalAlignment="Center"
Style="{StaticResource TitleTextStyle}"
Margin="0,2,0,16"/>
</Border>
<Border BorderBrush="Black" BorderThickness="1">
<Thumb
Name="translationThumb"
Style="{StaticResource TranslationThumbStyle}"
DragDelta="translationThumb_DragDelta" />
</Border>
<Thumb
Name="rotationThumb"
Style="{StaticResource RotationThumbStyle}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
DragStarted="rotationThumb_DragStarted"
DragDelta="rotationThumb_DragDelta" >
</Thumb>
<Thumb
Name="scaleThumb" Grid.Row="1"
Style="{StaticResource RoundThumbStyle}"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
DragDelta="scaleThumb_DragDelta" >
<Thumb.RenderTransform>
<TranslateTransform X="8" Y="8" />
</Thumb.RenderTransform>
</Thumb>
</Grid>
</UserControl>

View File

@ -0,0 +1,180 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
namespace DrumKit
{
public sealed partial class DrumEditUI : UserControl
{
#region Constants
const double RotationHandleOffset = 8;
#endregion
#region Public events
/// <summary>
/// Triggered when the item was dragged.
/// </summary>
public event DragDeltaEventHandler DragDelta;
/// <summary>
/// Triggered when the angle changes
/// </summary>
public event EventHandler AngleChanged;
#endregion
#region Public properties
/// <summary>
/// Gets or sets the drum rotation
/// </summary>
public double Angle
{
get
{
// Get rotated grid
var transform = rotateGrid.RenderTransform as RotateTransform;
// Get angle
if (transform != null)
return transform.Angle;
// No rotation
return 0;
}
set
{
// Set rotation transformation
RotateTransform rot = new RotateTransform();
rot.CenterX = this.Width / 2;
rot.CenterY = this.Height / 2;
rot.Angle = value;
rotateGrid.RenderTransform = rot;
// Set thumb position
TranslateTransform tr = new TranslateTransform();
double radius = this.Height / 2 + RotationHandleOffset;
double rads = Math.PI * (value - 90) / 180;
tr.X = radius * Math.Cos(rads);
tr.Y = radius * Math.Sin(rads);
rotationThumb.RenderTransform = tr;
// Call event
if (AngleChanged != null)
AngleChanged(this, new EventArgs());
}
}
/// <summary>
/// Gets the drum id.
/// </summary>
public string DrumID { get; private set; }
#endregion
#region Private fields
private double rotationDragX = 0, rotationDragY = 0;
#endregion
#region Constructor
/// <summary>
/// Creates a new instance of DrumEditUI
/// </summary>
public DrumEditUI(Drum drum)
{
// Initialize
this.InitializeComponent();
// Set drum properties
this.DrumID = drum.Id;
this.nameText.Text = drum.Name;
// Set image
this.image.Source = drum.LoadedImageSource;
}
#endregion
#region UI handlers
/// <summary>
/// Handles the "rotation handle drag started" event.
/// </summary>
private void rotationThumb_DragStarted(object sender, DragStartedEventArgs e)
{
var transl = this.rotationThumb.RenderTransform as TranslateTransform;
double x = (transl == null) ? 0 : transl.X;
double y = (transl == null) ? 0 : transl.Y;
rotationDragX = x;
rotationDragY = y;
}
/// <summary>
/// Handles the "rotation handle dragged" event.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void rotationThumb_DragDelta(object sender, DragDeltaEventArgs e)
{
rotationDragX += e.HorizontalChange;
rotationDragY += e.VerticalChange;
double angle = Math.Atan2(rotationDragY, rotationDragX) * 180.0 / Math.PI + 90;
this.Angle = angle;
}
/// <summary>
/// Handles the "scale handle dragged" event.
/// </summary>
private void scaleThumb_DragDelta(object sender, DragDeltaEventArgs e)
{
double new_w = this.Width + e.HorizontalChange;
// double new_h = this.Height + e.VerticalChange;
this.Width = Math.Max(0, new_w);
this.Height = Math.Max(0, new_w);
}
/// <summary>
/// Handles the translation drag delta event.
/// </summary>
private void translationThumb_DragDelta(object sender, DragDeltaEventArgs e)
{
if (this.DragDelta != null)
this.DragDelta(this, e);
}
/// <summary>
/// Handles the size changed event.
/// </summary>
private void DrumEditUl_SizeChanged(object sender, SizeChangedEventArgs e)
{
this.Angle = Angle;
}
#endregion
}
}

View File

@ -0,0 +1,65 @@
<UserControl
x:Class="DrumKit.DrumPlayUI"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DrumKit"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid Name="grid" Background="Transparent"
PointerPressed="Grid_PointerPressed">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="DrumGroups">
<VisualState x:Name="DrumNormal">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="imagePressed"
Storyboard.TargetProperty="Opacity"
BeginTime="0:0:0.1" Duration="0:0:0.7" To="0" >
<DoubleAnimation.EasingFunction>
<SineEase EasingMode="EaseInOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation Storyboard.TargetName="image"
Storyboard.TargetProperty="Opacity"
Duration="0:0:0.3" To="1" >
<DoubleAnimation.EasingFunction>
<SineEase EasingMode="EaseIn" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</VisualState>
<VisualState x:Name="DrumHit">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="imagePressed"
Storyboard.TargetProperty="Opacity"
Duration="0" To="1" />
<DoubleAnimation Storyboard.TargetName="image"
Storyboard.TargetProperty="Opacity"
Duration="0" To=".3" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Image Name="image" IsHitTestVisible="False"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
<Image Name="imagePressed" IsHitTestVisible="False"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Opacity="0" />
</Grid>
</UserControl>

View File

@ -0,0 +1,122 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
namespace DrumKit
{
public sealed partial class DrumPlayUI : UserControl
{
#region Public events
public event PointerEventHandler Hit;
#endregion
#region Properties
/// <summary>
/// Gets or sets the rotation of the drum
/// </summary>
public double Angle
{
get
{
// Get rotated grid
var transform = grid.RenderTransform as RotateTransform;
// Get angle
if (transform != null)
return transform.Angle;
// No rotation
return 0;
}
set
{
// Set rotation transformation
RotateTransform rot = new RotateTransform();
rot.CenterX = this.Width / 2;
rot.CenterY = this.Height / 2;
rot.Angle = value;
grid.RenderTransform = rot;
}
}
/// <summary>
/// Gets the drum id.
/// </summary>
public string DrumID { get; private set; }
/// <summary>
/// Enables or disables the hit animation.
/// </summary>
private bool IsAnimationEnabled {
get {
return DataController.Settings.Animations;
}
}
#endregion
#region Constructor
/// <summary>
/// Creates a new instance of DrumPlayUI
/// </summary>
/// <param name="drum"></param>
public DrumPlayUI(Drum drum)
{
// Initialize
this.InitializeComponent();
// Set drum properties
this.DrumID = drum.Id;
// TODO: key
this.image.Source = drum.LoadedImageSource;
this.imagePressed.Source = drum.LoadedImagePressedSource;
}
#endregion
#region UI handlers
/// <summary>
/// Handles the drum pressed event.
/// </summary>
private void Grid_PointerPressed(object sender, PointerRoutedEventArgs e)
{
// Call hit event immediately
if (this.Hit != null)
this.Hit(this, e);
// Play animation
this.PerformHit();
}
#endregion
#region Misc
public void PerformHit()
{
// Play animation
if (this.IsAnimationEnabled)
{
VisualStateManager.GoToState(this, "DrumHit", true);
VisualStateManager.GoToState(this, "DrumNormal", true);
}
}
#endregion
}
}

View File

@ -1,178 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation;
using Windows.UI.Xaml.Media.Imaging;
namespace DrumKit
{
class DrumUI
{
#region Private attributes
private Thumb thumb;
private Image image, imagePressed;
private Grid grid;
private Storyboard hitAnimation;
#endregion
#region Public properties
/// <summary>
/// Gets the ui element which will be put in a canvas.
/// </summary>
public FrameworkElement Element { get { return grid; } }
/// <summary>
/// Gets the drum id.
/// </summary>
public string DrumID { get; private set; }
public event Windows.UI.Xaml.Input.PointerEventHandler PointerPressed
{
add {
grid.PointerPressed += value;
}
remove {
grid.PointerPressed -= value;
}
}
public event DragDeltaEventHandler DragDelta
{
add {
thumb.DragDelta += value;
}
remove {
thumb.DragDelta -= value;
}
}
#endregion
#region Initialization
private void GridAddChild(FrameworkElement element)
{
grid.Children.Add(element);
element.HorizontalAlignment = HorizontalAlignment.Stretch;
element.VerticalAlignment = VerticalAlignment.Stretch;
}
private void InitializeCreateObjects()
{
// Create thumb
this.thumb = new Thumb()
{
Background = new SolidColorBrush(Colors.Green),
Opacity = .3,
Visibility = Visibility.Collapsed
};
// Create image
this.image = new Image();
// Create pressed image
this.imagePressed = new Image()
{
Opacity = 0
};
// Create grid
this.grid = new Grid();
// Create animation
DoubleAnimation fade = new DoubleAnimation();
fade.Duration = TimeSpan.FromSeconds(.6);
fade.From = 1;
fade.To = 0;
Storyboard.SetTarget(fade, this.imagePressed);
Storyboard.SetTargetProperty(fade, "Opacity");
this.hitAnimation = new Storyboard();
this.hitAnimation.Children.Add(fade);
// grid.Resources.Add("hitanimation", this.hitAnimation);
}
private void InitializeParenting()
{
this.GridAddChild(this.image);
this.GridAddChild(this.imagePressed);
this.GridAddChild(this.thumb);
}
public async Task InitializeDrum(Drum drum, StorageFolder root)
{
// Set path
Uri rootpath = new Uri(root.Path);
// Set drum id
this.DrumID = drum.Id;
// Set images
this.image.Source = await IOHelper.GetImageAsync(root, drum.ImageSource);
this.imagePressed.Source = await IOHelper.GetImageAsync(root, drum.ImagePressedSource);
// Set tags
this.thumb.Tag = drum.Id;
this.grid.Tag = drum.Id;
}
#endregion
public DrumUI()
{
// Create objects
this.InitializeCreateObjects();
this.InitializeParenting();
}
public void UpdateLayout(DrumLayout layout, double canvasWidth, double canvasHeight)
{
// Set up size
this.grid.Width = layout.Size * canvasWidth;
this.grid.Height = layout.Size * canvasWidth;
// Set up position
Canvas.SetLeft(this.grid, layout.X * canvasWidth);
Canvas.SetTop(this.grid, layout.Y * canvasHeight);
Canvas.SetZIndex(this.grid, layout.ZIndex);
// Rotation
RotateTransform transform = new RotateTransform();
transform.Angle = layout.Angle;
transform.CenterX = this.grid.Width / 2;
transform.CenterY = this.grid.Height / 2;
this.image.RenderTransform = transform;
this.imagePressed.RenderTransform = transform;
}
public void Hit()
{
// Perform a drum hit
this.hitAnimation.Begin();
}
public void EnableEdit()
{
// Thumb becomes visible
this.thumb.Visibility = Visibility.Visible;
}
public void DisableEdit()
{
// Thumb becomes invisible
this.thumb.Visibility = Visibility.Collapsed;
}
}
}

View File

@ -0,0 +1,34 @@
<Page
x:Class="DrumKit.EditorPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DrumKit"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<ImageBrush x:Key="EditorBackgroundBrush" ImageSource="ms-appx:///Assets/bg.png" Stretch="UniformToFill" />
</Page.Resources>
<Canvas
Name="container"
Background="{StaticResource EditorBackgroundBrush}">
<Button Name="buttonBack" Canvas.Left="10" Canvas.Top="10" Canvas.ZIndex="1"
Style="{StaticResource BackButtonStyle}"
Click="buttonBack_Click" />
</Canvas>
<!--<Page.BottomAppBar>
<AppBar>
<StackPanel Orientation="Horizontal">
<Button>Change order</Button>
<Button>Bring all drums into view</Button>
</StackPanel>
</AppBar>
</Page.BottomAppBar>-->
</Page>

View File

@ -0,0 +1,244 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace DrumKit
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class EditorPage : Page
{
#region Private properties
private int LayoutIndex { get; set; }
private DrumkitLayout Layout {
get {
if (this.LayoutIndex == -1)
return null;
return DataController.CurrentLayouts.Items[LayoutIndex];
}
set {
this.LayoutIndex = DataController.CurrentLayouts.Items.IndexOf(value);
}
}
private Dictionary<string, DrumEditUI> DrumUIs { get; set; }
private bool IgnoreEvent = false;
#endregion
#region Constructor, initialization
/// <summary>
/// Creates a new instance of EditorPage.
/// </summary>
public EditorPage()
{
this.InitializeComponent();
this.DrumUIs = new Dictionary<string, DrumEditUI>();
this.LayoutIndex = -1;
this.SizeChanged += EditorPage_SizeChanged;
this.Loaded += EditorPage_Loaded;
this.InitializeDrums();
}
/// <summary>
/// Handles the page loaded event.
/// </summary>
void EditorPage_Loaded(object sender, RoutedEventArgs e)
{
ReloadLayout();
}
/// <summary>
/// Creates the drums.
/// </summary>
void InitializeDrums()
{
foreach (var i in DataController.CurrentDrumkit.Drums)
{
// Create drum edit UI
var ui = new DrumEditUI(i.Value);
// Set up events
ui.DragDelta += Drum_Dragged;
ui.SizeChanged += Drum_SizeChanged;
ui.AngleChanged += Drum_AngleChanged;
// Add to canvas and dictionary
this.container.Children.Add(ui);
this.DrumUIs.Add(i.Key, ui);
}
}
#endregion
#region Reload layout
/// <summary>
/// Updates the layout of the drums
/// </summary>
void ReloadLayout()
{
// Get current size
double w = container.ActualWidth;
double h = container.ActualHeight;
if (double.IsNaN(w) || double.IsNaN(h) || double.IsInfinity(w) || double.IsInfinity(h))
return;
// Flag that tells event handlers to ignore event
this.IgnoreEvent = true;
// Set layouts
foreach (var i in Layout.Drums)
{
// Set angle
DrumUIs[i.Key].Angle = i.Value.Angle;
// Set scale
DrumUIs[i.Key].Width = i.Value.Size * w;
DrumUIs[i.Key].Height = i.Value.Size * w;
// Set position
Canvas.SetLeft(DrumUIs[i.Key], w * i.Value.X);
Canvas.SetTop(DrumUIs[i.Key], h * i.Value.Y);
}
// Ignore no more
this.IgnoreEvent = false;
}
#endregion
#region UI: Page events
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
Log.Write("Navigated to editor page.");
// When we arrive here, we should have a layout
var layout = e.Parameter as DrumkitLayout;
if (layout == null)
Frame.GoBack();
// Set layout
this.Layout = layout;
this.ReloadLayout();
}
/// <summary>
/// Handles the page resize event.
/// </summary>
private void EditorPage_SizeChanged(object sender, SizeChangedEventArgs e)
{
ReloadLayout();
}
#endregion
#region UI: Buttons events
/// <summary>
/// Handles the "Back" button click event.
/// </summary>
private void buttonBack_Click(object sender, RoutedEventArgs e)
{
Frame.GoBack();
}
#endregion
#region UI: Drum events
/// <summary>
/// Triggered when the angle is changed.
/// </summary>
void Drum_AngleChanged(object sender, EventArgs e)
{
var drumui = sender as DrumEditUI;
if (sender != null && !IgnoreEvent)
{
this.Layout.Drums[drumui.DrumID].Angle = drumui.Angle;
DataController.SaveLayout();
}
}
/// <summary>
/// Triggered when the size of a drum is changed.
/// </summary>
void Drum_SizeChanged(object sender, SizeChangedEventArgs e)
{
var drumui = sender as DrumEditUI;
if (drumui != null && !IgnoreEvent)
{
this.Layout.Drums[drumui.DrumID].Size = drumui.ActualWidth / container.ActualWidth;
DataController.SaveLayout();
}
}
/// <summary>
/// Triggered when the drum is dragged.
/// We have to perform the move ourselves.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void Drum_Dragged(object sender, DragDeltaEventArgs e)
{
var drumui = sender as DrumEditUI;
if (drumui != null && !IgnoreEvent)
{
// Get old position
double old_x = Canvas.GetLeft(drumui);
double old_y = Canvas.GetTop(drumui);
// Calculate new position
double new_x = old_x + e.HorizontalChange;
double new_y = old_y + e.VerticalChange;
// Save layout
Layout.Drums[drumui.DrumID].X = new_x / container.ActualWidth;
Layout.Drums[drumui.DrumID].Y = new_y / container.ActualHeight;
// Move object
Canvas.SetLeft(drumui, new_x);
Canvas.SetTop(drumui, new_y);
// Save modification
DataController.SaveLayout();
}
}
#endregion
}
}

View File

@ -7,13 +7,20 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="#164646">
<Grid Background="{StaticResource ApplicationBackgroundColor}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid HorizontalAlignment="Center"
VerticalAlignment="Center">
<Image Source="ms-appx:///Assets/Logos/SplashScreen.png"
Stretch="None"/>
</Grid>
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
@ -21,10 +28,15 @@
Margin="20">
<ProgressRing Width="40" Height="40" IsActive="True" Foreground="White" />
<TextBlock
Name="TextLoading"
Name="textLoading"
Style="{StaticResource SubheaderTextStyle}" Margin="10,0,0,0">
Loading resources...</TextBlock>
</StackPanel>
<ProgressBar
Name="progressBar" Grid.Row="1"
Foreground="#53AB6D" Background="#20FFFFFF"
Minimum="0" Maximum="100"/>
</Grid>
</Page>

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
@ -24,10 +25,8 @@ namespace DrumKit
public LoadingPage()
{
this.InitializeComponent();
this.Loaded += LoadingPage_Loaded;
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
@ -35,38 +34,70 @@ namespace DrumKit
/// property is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
LoadStuff(e.Parameter);
}
private async void LoadingPage_Loaded(object sender, RoutedEventArgs e)
private async Task DoFactoryReset()
{
DataController.Dispose();
await DataController.FactoryReset();
}
/// <summary>
/// Performs the loading of the application stuff.
/// </summary>
/// <param name="arg"></param>
private async void LoadStuff(object arg)
{
bool error = false;
DataController.ProgressChanged += DataController_ProgressChanged;
// Application restart?
if (arg is string && (string) arg == "restart")
DataController.Dispose();
// Factory reset?
if (arg is string && (string) arg == "reset")
await DoFactoryReset();
// Perform initializations
try
{
TextLoading.Text = "Loading data...";
await DataManager.Initialize();
await Log.Initialize();
await DrumsManager.Initialize(DataManager.Settings);
TextLoading.Text = "Loading sounds...";
SoundManager.Initialize();
await SoundManager.LoadDrumkit(DrumsManager.CurrentDrumkit, DrumsManager.CurrentDrumkitLocation);
TextLoading.Text = "Loading interface...";
UIManager.Initialize();
await UIManager.ReloadDrumkit();
await UIManager.ReloadConfig();
try {
await DataController.Initialize();
Frame.Navigate(typeof(MainPage));
}
// Error handling
catch (Exception ex)
{
TextLoading.Text = "Failure: " + ex.Message;
catch (Exception ex) {
error = true;
Log.Error("Failure during loading!");
Log.Except(ex);
}
if (error) {
var dialog = new Windows.UI.Popups.MessageDialog("A problem occurred, and the application could not be loaded.", "An error occurred!");
dialog.Commands.Add(new Windows.UI.Popups.UICommand("Close", new Windows.UI.Popups.UICommandInvokedHandler(UICommandCloseHandler)));
dialog.CancelCommandIndex = dialog.DefaultCommandIndex = 0;
await dialog.ShowAsync();
}
}
/// <summary>
/// Application failed to load
/// </summary>
private async void UICommandCloseHandler(Windows.UI.Popups.IUICommand cmd)
{
await System.Threading.Tasks.Task.Delay(1000);
Windows.ApplicationModel.Core.CoreApplication.Exit();
}
/// <summary>
/// Progress event
/// </summary>
void DataController_ProgressChanged(object sender, KeyValuePair<int, string> e)
{
progressBar.Value = e.Key;
textLoading.Text = e.Value;
}
}
}

View File

@ -6,21 +6,19 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Transitions>
<TransitionCollection>
<EntranceThemeTransition />
</TransitionCollection>
</Page.Transitions>
<Grid
Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Image Source="ms-appx:///Assets/bg.png"
Stretch="UniformToFill"/>
<Grid Name="canvasContainer" />
<Grid Visibility="Collapsed">
<Page.Resources>
<ImageBrush x:Key="MainpageBackgroundBrush" ImageSource="ms-appx:///Assets/bg.png" Stretch="UniformToFill" />
</Page.Resources>
<Grid
Background="{StaticResource MainpageBackgroundBrush}">
<Canvas Name="canvas" />
<!--<Grid Visibility="Collapsed">
<Border Margin="7"
CornerRadius="10"
BorderBrush="Red"
@ -51,34 +49,49 @@
</EventTrigger>
</Canvas.Triggers>
</Canvas>
<!--<StackPanel Orientation="Horizontal"
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<Button>Record</Button>
<Button>Stop</Button>
</StackPanel>-->
</Grid>
</StackPanel>
</Grid>-->
</Grid>
<Page.BottomAppBar>
<AppBar>
<StackPanel Orientation="Horizontal">
<ToggleButton
Name="buttonAnimations"
Click="buttonAnimations_Click"
AutomationProperties.Name="Animations"
IsChecked="True"
Style="{StaticResource VideoAppBarButtonStyle}" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ToggleButton
Name="buttonEditMode"
Click="buttonEditMode_Click"
Style="{StaticResource EditAppBarButtonStyle}" />
</StackPanel>
<StackPanel Grid.Column="0" Orientation="Horizontal">
<ToggleButton
Name="buttonAnimations"
Click="buttonAnimations_Click"
AutomationProperties.Name="Animations"
IsChecked="True"
Style="{StaticResource VideoAppBarButtonStyle}" />
<Button
Name="buttonEditMode"
Click="ButtonEditMode_Click"
Style="{StaticResource EditAppBarButtonStyle}" />
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal" >
<Button
Name="buttonSettings"
Click="ButtonSettings_Click"
AutomationProperties.Name="Settings"
Style="{StaticResource SettingsAppBarButtonStyle}" />
</StackPanel>
</Grid>
</AppBar>
</Page.BottomAppBar>
</Page>

View File

@ -2,9 +2,13 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Storage;
using Windows.System;
using Windows.UI.ApplicationSettings;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
@ -22,31 +26,263 @@ namespace DrumKit
/// </summary>
public sealed partial class MainPage : Page
{
#region Fields: Private members
private Dictionary<string, DrumPlayUI> DrumUIs { get; set; }
private Dictionary<VirtualKey, string> Keymap { get; set; }
private int CurrentLayout { get; set; }
#endregion
#region Initialization
/// <summary>
/// Creates a new instance of MainPage.
/// </summary>
public MainPage()
{
// Create private members
this.DrumUIs = new Dictionary<string, DrumPlayUI>();
this.Keymap = new Dictionary<VirtualKey, string>();
CurrentLayout = 0;
// Initialize page
this.InitializeComponent();
this.SizeChanged += MainPage_SizeChanged;
this.Loaded += MainPage_Loaded;
this.canvasContainer.Children.Add(UIManager.TheCanvas);
SettingsPane.GetForCurrentView().CommandsRequested += MainPage_CommandsRequested;
// Initialize drums
this.InitializeDrums();
}
/// <summary>
/// Sets up a single drum
/// </summary>
/// <param name="drum">The drum.</param>
private void InitializeDrum(Drum drum)
{
// Create object
DrumPlayUI d = new DrumPlayUI(drum);
// Set up callbacks
d.Hit += HandlerDrumPointerPressed;
// Add to lists
canvas.Children.Add(d);
this.DrumUIs.Add(drum.Id, d);
}
/// <summary>
/// Sets up the drums.
/// </summary>
private void InitializeDrums()
{
// Clear previous stuff if any
this.DrumUIs.Clear();
this.Keymap.Clear();
// Load drums
foreach (var i in DataController.CurrentDrumkit.DrumsList)
InitializeDrum(i);
// Load drum configurations
foreach (var i in DataController.CurrentConfig.DrumsList)
{
// Unload if disabled
if (!i.IsEnabled)
{
canvas.Children.Remove(this.DrumUIs[i.TargetId]);
this.DrumUIs.Remove(i.TargetId);
}
// Keyboard mapping
if (!Keymap.ContainsKey(i.Key))
Keymap.Add(i.Key, i.TargetId);
}
}
#endregion
#region UI: Settings charm
/// <summary>
/// Triggered when the settings pane requests commands/
/// </summary>
void MainPage_CommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
{
args.Request.ApplicationCommands.Clear();
SettingsCommand general = new SettingsCommand("general", "General", new Windows.UI.Popups.UICommandInvokedHandler(MainPage_SettingsCommand));
SettingsCommand drumkits = new SettingsCommand("drumkits", "Manage drumkits", new Windows.UI.Popups.UICommandInvokedHandler(MainPage_SettingsCommand));
SettingsCommand drums = new SettingsCommand("drums", "Manage drums", new Windows.UI.Popups.UICommandInvokedHandler(MainPage_SettingsCommand));
SettingsCommand layouts = new SettingsCommand("layouts", "Layouts", new Windows.UI.Popups.UICommandInvokedHandler(MainPage_SettingsCommand));
args.Request.ApplicationCommands.Add(general);
args.Request.ApplicationCommands.Add(drumkits);
args.Request.ApplicationCommands.Add(drums);
args.Request.ApplicationCommands.Add(layouts);
}
/// <summary>
/// Handles the settings charms
/// </summary>
void MainPage_SettingsCommand(Windows.UI.Popups.IUICommand command)
{
Frame.Navigate(typeof(SettingsPage), command.Id);
}
#endregion
#region Layouts
/// <summary>
/// Figures out which is the best layout available, and uses it.
/// </summary>
private int PickBestLayout()
{
// Smaller index is better
int[] picks = {-1, -1, -1, -1, -1, -1};
// Get current layout
var view = UIHelper.ToDrumkitLayoutView(Windows.UI.ViewManagement.ApplicationView.Value);
// Find best option
for (int index = 0; index < DataController.CurrentLayouts.Items.Count; index++ )
{
var i = DataController.CurrentLayouts.Items[index];
bool isSame = (i.TargetView == view);
bool contains = (i.TargetView & view) > 0;
bool all = i.TargetView == DrumkitLayoutTargetView.All;
if (i.IsDefault)
{
if (isSame) picks[0] = index;
if (contains) picks[1] = index;
if (all) picks[2] = index;
}
else
{
if (isSame) picks[3] = index;
if (contains) picks[4] = index;
if (all) picks[5] = index;
}
}
// Return first value different than -1, or 0
foreach (var i in picks)
if (i != -1) return i;
return 0;
}
/// <summary>
/// Sets up the layout
/// </summary>
private void ReloadLayout()
{
// Get current size
double w = canvas.ActualWidth;
double h = canvas.ActualHeight;
if (double.IsNaN(w) || double.IsNaN(h) || double.IsInfinity(w) || double.IsInfinity(h))
return;
// Pick a layout
this.CurrentLayout = PickBestLayout();
Log.Write("Layout change: picked_layout={0}, w={1}, h={2}", this.CurrentLayout, w, h);
// Apply layout
foreach (var i in DataController.CurrentLayouts.Items[CurrentLayout].Drums)
{
if (!DrumUIs.ContainsKey(i.Key))
continue;
// Set angle
DrumUIs[i.Key].Angle = i.Value.Angle;
// Set scale
DrumUIs[i.Key].Width = i.Value.Size * w;
DrumUIs[i.Key].Height = i.Value.Size * w;
// Set position
Canvas.SetLeft(DrumUIs[i.Key], w * i.Value.X);
Canvas.SetTop(DrumUIs[i.Key], h * i.Value.Y);
}
}
#endregion
#region UI: Drums
/// <summary>
/// Handles drum hit using mouse/finger
/// </summary>
void HandlerDrumPointerPressed(object sender, PointerRoutedEventArgs e)
{
var button = sender as DrumPlayUI;
if (button != null)
this.HandlerDrumClickedCommon(button.DrumID);
}
/// <summary>
/// Handles drum hit using keyboard
/// </summary>
public 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 (this.Keymap.TryGetValue(args.VirtualKey, out drum))
HandlerDrumClickedCommon(drum);
}
/// <summary>
/// Handles drum hit.
/// </summary>
private void HandlerDrumClickedCommon(string drum_id)
{
try
{
DataController.PlaySound(drum_id, 0);
if (DataController.Settings.Animations)
this.DrumUIs[drum_id].PerformHit();
}
catch (Exception ex)
{
Log.Error("Error at playback!!! Drum id: {0}", drum_id);
Log.Except(ex);
}
}
#endregion
#region UI: Page events
/// <summary>
/// Handles page size change event.
/// </summary>
void MainPage_SizeChanged(object sender, SizeChangedEventArgs e)
{
// TODO: Find best layout, and change it
DrumsManager.SetLayout();
UIManager.ReloadLayout();
this.ReloadLayout();
this.ReloadLayout();
}
/// <summary>
/// Handles page load event.
/// </summary>
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
// Set layout
DrumsManager.SetLayout();
UIManager.ReloadLayout();
this.ReloadLayout();
// Set toggles
buttonAnimations.IsChecked = DataManager.Settings.Animations;
buttonAnimations.IsChecked = DataController.Settings.Animations;
}
/// <summary>
@ -56,29 +292,33 @@ namespace DrumKit
/// property is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
Window.Current.CoreWindow.KeyDown += UIManager.HandlerKeyDown;
Log.Write("Navigated to main page.");
Window.Current.CoreWindow.KeyDown += this.HandlerKeyDown;
}
/// <summary>
/// Invoked when the page is about to be destroyed.
/// </summary>
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
Window.Current.CoreWindow.KeyDown -= UIManager.HandlerKeyDown;
Window.Current.CoreWindow.KeyDown -= this.HandlerKeyDown;
}
private void buttonEditMode_Click(object sender, RoutedEventArgs e)
#endregion
#region UI: Buttons
/// <summary>
/// Handles the edit button, going into the editor.
/// </summary>
private void ButtonEditMode_Click(object sender, RoutedEventArgs e)
{
var button = sender as ToggleButton;
if (button == null) return;
bool isChecked = (button.IsChecked.HasValue && button.IsChecked.Value);
// Fix togglebuton style bug
VisualStateManager.GoToState(button, isChecked ? "Checked" : "Unchecked", false);
// Change visibility of thumbs
if (isChecked) UIManager.EnterEdit();
else UIManager.ExitEdit();
Frame.Navigate(typeof(EditorPage), DataController.CurrentLayouts.Items[CurrentLayout]);
}
/// <summary>
/// Handles the animations enabled toggle button.
/// </summary>
private void buttonAnimations_Click(object sender, RoutedEventArgs e)
{
var button = sender as ToggleButton;
@ -90,8 +330,21 @@ namespace DrumKit
VisualStateManager.GoToState(button, isChecked ? "Checked" : "Unchecked", false);
// Change animation setting
DataManager.Settings.Animations = isChecked;
DataController.Settings.Animations = isChecked;
// Save modified setting
DataController.SaveSettings();
}
/// <summary>
/// Goes to application settings.
/// </summary>
private void ButtonSettings_Click(object sender, RoutedEventArgs e)
{
Frame.Navigate(typeof(SettingsPage), this);
}
#endregion
}
}

View File

@ -0,0 +1,108 @@
<UserControl
x:Class="DrumKit.DrumkitsSettingsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DrumKit"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="321.429"
d:DesignWidth="696.617">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Common/TextButtonStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
<DataTemplate x:Key="DrumkitListDataTemplate">
<Grid Name="theGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<!-- Left thing -->
<Border Name="orangeBorder"
Grid.Column="0" Grid.RowSpan="3"
Background="OrangeRed" Width="10" />
<!--<Image MinWidth="10"
Source="{Binding Thumbnail}" />-->
<!-- Name -->
<TextBox Grid.Column="1" Grid.Row="0" Margin="15,2,15,0"
FontSize="15.3"
Style="{StaticResource MyTextBoxStyle}"
IsReadOnly="True"
Text="{Binding Name}"
TextChanged="NameTextChanged"/>
<!-- Description -->
<TextBox Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="1" Margin="15,0,15,2"
Style="{StaticResource MyTextBoxStyle}"
Text="{Binding Description}"
TextChanged="DescriptionTextChanged"
FontSize="13"
FontStyle="Italic"
IsReadOnly="True"
AcceptsReturn="True"
TextWrapping="Wrap"
Height="80" />
</Grid>
</DataTemplate>
<Style x:Key="ListViewStretchItemStyle" TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<!-- Drumkit list -->
<ListView Name="listDrumkits"
Grid.Row="0" Grid.Column="0"
ItemTemplate="{StaticResource DrumkitListDataTemplate}"
ItemContainerStyle="{StaticResource ListViewStretchItemStyle}"
SelectionMode="Single" >
</ListView>
<ProgressRing
Name="progressRing"
Foreground="White"
Width="50" Height="50" />
<!-- Buttons -->
<StackPanel Grid.Row="1" Grid.ColumnSpan="2" Orientation="Horizontal">
<!--<Button Style="{StaticResource MyButtonStyle}" Click="ButtonCreate_Click">Create</Button>-->
<Button Style="{StaticResource MyButtonStyle}" Click="ButtonImport_Click">Import</Button>
<Button Style="{StaticResource MyButtonStyle}" Click="ButtonExport_Click">Export</Button>
<Border Width="20" />
<Button Style="{StaticResource MyButtonStyle}" Click="ButtonDelete_Click">Delete</Button>
<Button Style="{StaticResource MyButtonStyle}" Click="ButtonSetCurrent_Clicked">Set current</Button>
</StackPanel>
</Grid>
</UserControl>

View File

@ -0,0 +1,319 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Data.Xml.Dom;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI;
using Windows.UI.Notifications;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace DrumKit
{
public sealed partial class DrumkitsSettingsControl : UserControl
{
#region Initialization
/// <summary>
/// Creates a new instance of DrumkitsSettingsControl
/// </summary>
public DrumkitsSettingsControl()
{
this.InitializeComponent();
this.Loaded += DrumkitsSettingsControl_Loaded;
}
/// <summary>
/// Loads drumkit list at startup
/// </summary>
void DrumkitsSettingsControl_Loaded(object sender, RoutedEventArgs e)
{
ReloadDrumkits();
}
#endregion
#region Reload drumkit list
/// <summary>
/// Reloads the list of drumkits from the data controller
/// </summary>
async void ReloadDrumkits()
{
// Remove previous stuff
this.listDrumkits.Items.Clear();
// Add new stuff
foreach (var i in DataController.AvailableDrumkits)
this.listDrumkits.Items.Add(i.Value);
// Wait containers to be generated
await System.Threading.Tasks.Task.Delay(50);
// Update visual stuff
foreach (var i in this.listDrumkits.Items)
{
var it = i as Drumkit;
// Is current?
if (DataController.Settings.CurrentKit == it.Name)
{
// Get border and grid
var container = listDrumkits.ItemContainerGenerator.ContainerFromItem(it) as FrameworkElement;
Border b = UIHelper.FindChildByName(container, "orangeBorder") as Border;
Grid g = UIHelper.FindChildByName(container, "theGrid") as Grid;
// Change look
if (b != null) b.Background = new SolidColorBrush(Color.FromArgb(0xff, 0xff, 0x78, 0x33));
if (g != null) g.Background = new SolidColorBrush(Color.FromArgb(0x1f, 0xff, 0xef, 0xdf));
}
}
}
#endregion
#region UI Handlers: Text boxes
/// <summary>
/// Handles drumkit name change
/// </summary>
private void NameTextChanged(object sender, TextChangedEventArgs e)
{
var drumkit = (sender as FrameworkElement).DataContext as Drumkit;
throw new NotImplementedException();
}
/// <summary>
/// Handles drumkit description change
/// </summary>
private void DescriptionTextChanged(object sender, TextChangedEventArgs e)
{
var drumkit = (sender as FrameworkElement).DataContext as Drumkit;
throw new NotImplementedException();
}
#endregion
#region UI Handlers: Buttons
/// <summary>
/// Handles the Create button
/// </summary>
private void ButtonCreate_Click(object sender, RoutedEventArgs e)
{
throw new NotImplementedException();
}
/// <summary>
/// Handles the Import button
/// </summary>
private async void ButtonImport_Click(object sender, RoutedEventArgs e)
{
// Error handling
string error = null;
// Create file picker
Windows.Storage.Pickers.FileOpenPicker picker = new Windows.Storage.Pickers.FileOpenPicker();
picker.CommitButtonText = "Select drum package";
picker.FileTypeFilter.Add(".tar");
picker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.Downloads;
// Pick a tarball
var tarball = await picker.PickSingleFileAsync();
if (tarball == null)
return;
// Enable progress ring
progressRing.IsActive = true;
// See if it works
try
{
await DataController.InstallDrumkit(tarball);
ReloadDrumkits();
}
catch (Repository.RepositoryException ex)
{
error = "A drumkit package with the same name already exists!";
Log.Except(ex);
}
catch (ArgumentException ex)
{
error = "The selected file is not a valid drumkit package!";
Log.Except(ex);
}
catch (IOException ex)
{
error = "The selected file is not a valid drumkit package!";
Log.Except(ex);
}
catch (Exception ex)
{
error = "An unexpected error occured while importing the drumkit package!";
Log.Except(ex);
}
// Disable progress ring
progressRing.IsActive = false;
// Show error if any occured
if (!string.IsNullOrEmpty(error))
{
MessageDialog err = new MessageDialog(error, "An error occured!");
await err.ShowAsync();
}
}
/// <summary>
/// Handles the Delete button
/// </summary>
private async void ButtonDelete_Click(object sender, RoutedEventArgs e)
{
// Get the selected drumkit
Drumkit selected = listDrumkits.SelectedItem as Drumkit;
string error = null;
// Try to delete
if (selected != null)
try
{
await DataController.RemoveDrumkit(selected.Name);
ReloadDrumkits();
}
catch (ControllerException ex)
{
error = "There has to be at least one drumkit remaining!";
Log.Except(ex);
}
catch (ArgumentException ex)
{
error = "Cannot delete the currently loaded drumkit!";
Log.Except(ex);
}
catch (Exception ex)
{
error = "An unexpected error occured while deleting the drumkit!";
Log.Except(ex);
}
// Show error if any occured
if (!string.IsNullOrEmpty(error))
{
MessageDialog err = new MessageDialog(error, "An error occured!");
await err.ShowAsync();
}
}
/// <summary>
/// Handles the Export button
/// </summary>
private async void ButtonExport_Click(object sender, RoutedEventArgs e)
{
// Variables
Drumkit selected = listDrumkits.SelectedItem as Drumkit;
string error = null;
// Make sure there is something selected
if (selected == null) return;
// Pick a file
Windows.Storage.Pickers.FileSavePicker picker = new Windows.Storage.Pickers.FileSavePicker();
picker.CommitButtonText = "Export drum package";
picker.FileTypeChoices.Add("Tarball", new string[] { ".tar" } );
picker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.Desktop;
var file = await picker.PickSaveFileAsync();
if (file == null) return;
// Enable progress ring
progressRing.IsActive = true;
// See if it works
try {
await DataController.ExportDrumkit(selected.Name, file);
}
catch (IOException ex)
{
error = "An unexpected error occured while exporting the drumkit package!";
Log.Except(ex);
}
catch (Exception ex)
{
error = "An unexpected error occured while exporting the drumkit package!";
Log.Except(ex);
}
// Disable progress ring
progressRing.IsActive = false;
// Show error if any occured
if (!string.IsNullOrEmpty(error))
{
MessageDialog err = new MessageDialog(error, "An error occured!");
await err.ShowAsync();
}
}
/// <summary>
/// Handles the SetCurrent button
/// </summary>
private async void ButtonSetCurrent_Clicked(object sender, RoutedEventArgs e)
{
var drumkit = listDrumkits.SelectedItem as Drumkit;
if (drumkit != null && drumkit.Name != DataController.Settings.CurrentKit)
{
// Change drumkit
DataController.Settings.CurrentKit = drumkit.Name;
DataController.SaveSettings();
// Reload list
ReloadDrumkits();
// Notify that the application needs to be restarted
MessageDialog dialog = new MessageDialog("The application needs to be restarted in " +
"order to change the current drumkit. If not restarted now, the selected drumkit " +
"will be loaded the next time the application is started. ", "Application restart required");
dialog.Commands.Add(new UICommand("Restart application", new UICommandInvokedHandler(UICommandRestartHandler)));
dialog.Commands.Add(new UICommand("Close"));
dialog.DefaultCommandIndex = 1;
await dialog.ShowAsync();
}
}
/// <summary>
/// UI Command that restarts the application, when current drumkit changes
/// </summary>
private void UICommandRestartHandler(Windows.UI.Popups.IUICommand cmd)
{
if (Window.Current.Content is Frame)
{
Frame frame = (Frame)Window.Current.Content;
frame.Navigate(typeof(LoadingPage), "drumkitchange");
}
}
#endregion
}
}

View File

@ -0,0 +1,164 @@
<UserControl
x:Class="DrumKit.DrumsSettingsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DrumKit"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="400"
d:DesignWidth="400">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Common/TextButtonStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
<DataTemplate x:Key="DrumsListDataTemplate">
<Grid Name="theGrid"
MinWidth="380">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!-- Left thing -->
<Border Name="yellowBorder"
Grid.Column="0" Grid.RowSpan="3"
Background="Yellow" Width="10" />
<!-- Thumbnail -->
<Image Grid.Row="0" Grid.RowSpan="2"
Grid.Column="2"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Width="60" Height="60"
Source="{Binding LoadedImageSource}"
Stretch="Uniform" />
<!-- Name -->
<TextBox Grid.Column="1" Grid.Row="0" Margin="15,2,15,0"
FontSize="15.3"
Style="{StaticResource MyTextBoxStyle}"
Text="{Binding Name}"
IsReadOnly="True" />
<!-- Configuration -->
<Grid
Grid.Column="1" Grid.Row="1" Margin="15,0,15,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ToggleButton
Name="toggleEnabled" Grid.Column="0"
Margin="0,-4,20,0" Padding="5,1"
Content="Enabled"
Click="ToggleEnabled_Click" />
<TextBlock
Grid.Column="1"
Style="{StaticResource TitleTextStyle}"
Text="Key:" />
<TextBox
Grid.Column="2"
Name="textKey"
Style="{StaticResource MyTextBoxStyle}"
KeyUp="TextKey_KeyUp" />
</Grid>
<Grid Grid.Column="1" Grid.Row="2" Margin="15,2,15,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Style="{StaticResource TitleTextStyle}"
Text="Volume left:" />
<Slider Name="sliderVolumeL"
Grid.Column="1"
Margin="5,-8,5,0"
Height="34"
Minimum="0" Maximum="1"
StepFrequency=".01"
ValueChanged="sliderVolumeL_ValueChanged"/>
<TextBlock
Margin="10,0,0,0"
Grid.Column="2"
Style="{StaticResource TitleTextStyle}"
Text="Right:" />
<Slider Name="sliderVolumeR"
Grid.Column="3"
Margin="5,-8,5,0"
Height="34"
Minimum="0" Maximum="1"
StepFrequency=".01"
ValueChanged="sliderVolumeR_ValueChanged" />
</Grid>
</Grid>
</DataTemplate>
<Style x:Key="GridViewStretchItemStyle" TargetType="GridViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<!-- Drums list -->
<GridView Name="listDrums"
Grid.Row="0" Grid.Column="0"
ItemTemplate="{StaticResource DrumsListDataTemplate}"
ItemContainerStyle="{StaticResource GridViewStretchItemStyle}"
SelectionMode="Single" >
<local:Drum ImageSource="/Assets/bg.png" Id="adda" Name="Hello world!" />
</GridView>
<!-- Buttons -->
<!--<StackPanel Grid.Row="1" Grid.ColumnSpan="2" Orientation="Horizontal">
<Button Style="{StaticResource MyButtonStyle}" Click="ButtonCreate_Click">Create</Button>
<Button Style="{StaticResource MyButtonStyle}" Click="ButtonDelete_Click">Delete</Button>
</StackPanel>-->
</Grid>
</UserControl>

View File

@ -0,0 +1,236 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
namespace DrumKit
{
public sealed partial class DrumsSettingsControl : UserControl
{
#region Initialization
/// <summary>
/// Creates a new instance of DrumsSettingsControl
/// </summary>
public DrumsSettingsControl()
{
this.InitializeComponent();
this.Loaded += DrumsSettingsControl_Loaded;
}
/// <summary>
/// Loads drum list at startup
/// </summary>
void DrumsSettingsControl_Loaded(object sender, RoutedEventArgs e)
{
ReloadDrums();
}
#endregion
#region Reloads the list of drums
/// <summary>
/// Reloads the list of drums
/// </summary>
async void ReloadDrums()
{
// Clear previous stuff
listDrums.Items.Clear();
// Add new stuff
foreach (var i in DataController.CurrentDrumkit.Drums)
this.listDrums.Items.Add(i.Value);
// Wait for containers to be generated
await System.Threading.Tasks.Task.Delay(50);
// Update visual stuff
DrumConfig config = null;
foreach (var i in this.listDrums.Items)
{
// Get drum and configuration
var drum = i as Drum;
if (drum != null)
DataController.CurrentConfig.Drums.TryGetValue(drum.Id, out config);
// No drum, no configuration?
if (drum == null || config == null)
continue;
// Set up other properties
var container = listDrums.ItemContainerGenerator.ContainerFromItem(i) as FrameworkElement;
ToggleButton enabled = UIHelper.FindChildByName(container, "toggleEnabled") as ToggleButton;
if (enabled != null) enabled.IsChecked = config.IsEnabled;
Slider volumeL = UIHelper.FindChildByName(container, "sliderVolumeL") as Slider;
if (volumeL != null) volumeL.Value = config.VolumeL;
Slider volumeR = UIHelper.FindChildByName(container, "sliderVolumeR") as Slider;
if (volumeR != null) volumeR.Value = config.VolumeR;
}
ReloadKeys();
}
void ReloadKeys()
{
DrumConfig config = null;
foreach (var i in this.listDrums.Items)
{
// Get drum and configuration
var drum = i as Drum;
if (drum != null)
DataController.CurrentConfig.Drums.TryGetValue(drum.Id, out config);
// No drum, no configuration?
if (drum == null || config == null)
continue;
// Set up key
var container = listDrums.ItemContainerGenerator.ContainerFromItem(i) as FrameworkElement;
TextBox key = UIHelper.FindChildByName(container, "textKey") as TextBox;
if (key != null)
{
if (Enum.IsDefined(typeof(VirtualKey), config.Key))
{
// Get name
string text = Enum.GetName(typeof(VirtualKey), config.Key);
// Prettify the name
if (text.StartsWith("Number"))
text = text.Substring("Number".Length);
text = System.Text.RegularExpressions.Regex.Replace(text, "([a-z])([A-Z])", "${1} ${2}");
// Set the text
key.Text = text;
}
else key.Text = string.Format("Unnamed ({0})", (int)config.Key);
}
}
}
#endregion
#region UI Handlers: Items
/// <summary>
/// Handles "Landscape" toggle button.
/// </summary>
private void ToggleEnabled_Click(object sender, RoutedEventArgs e)
{
// Get drum object
var button = sender as ToggleButton;
var drum = (sender as FrameworkElement).DataContext as Drum;
// Change enabled property
if (drum != null && DataController.CurrentConfig.Drums.ContainsKey(drum.Id))
{
DataController.CurrentConfig.Drums[drum.Id].IsEnabled = button.IsChecked.HasValue && button.IsChecked.Value;
DataController.SaveConfig();
}
}
/// <summary>
/// Handles the "key press" event in the textbox
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void TextKey_KeyUp(object sender, KeyRoutedEventArgs e)
{
// Get drum object
var text = sender as TextBox;
var drum = (sender as FrameworkElement).DataContext as Drum;
// Set key
if (text != null && drum != null && DataController.CurrentConfig.Drums.ContainsKey(drum.Id))
{
// Remove duplicates
RemoveKeys(e.Key, drum.Id);
// Set key
DataController.CurrentConfig.Drums[drum.Id].Key = e.Key;
// Display
ReloadKeys();
// Save
DataController.SaveConfig();
}
}
private void sliderVolumeL_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
// Get drum object
var slider = sender as Slider;
var drum = (sender as FrameworkElement).DataContext as Drum;
// Set value
if (slider != null && drum != null && DataController.CurrentConfig.Drums.ContainsKey(drum.Id))
{
DataController.CurrentConfig.Drums[drum.Id].VolumeL = e.NewValue;
DataController.SaveConfig();
}
}
private void sliderVolumeR_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
// Get drum object
var slider = sender as Slider;
var drum = (sender as FrameworkElement).DataContext as Drum;
// Set value
if (slider != null && drum != null && DataController.CurrentConfig.Drums.ContainsKey(drum.Id))
{
DataController.CurrentConfig.Drums[drum.Id].VolumeR = e.NewValue;
DataController.SaveConfig();
}
}
#endregion
#region Misc
/// <summary>
/// Sets the keyboart shortcut to None for all the drums that have this key.
/// </summary>
/// <param name="key">The keyboard shortcut</param>
private void RemoveKeys(VirtualKey key, string exception_id=null)
{
// See if any other drum has the same key
foreach (var i in DataController.CurrentConfig.Drums)
if (i.Value.Key == key && i.Key != exception_id)
{
// Set to none
i.Value.Key = VirtualKey.None;
// Get drum
var drum = DataController.CurrentDrumkit.Drums[i.Key];
// Get key text box
var container = listDrums.ItemContainerGenerator.ContainerFromItem(drum) as FrameworkElement;
TextBox keytxt = UIHelper.FindChildByName(container, "textKey") as TextBox;
keytxt.Text = Enum.GetName(typeof(VirtualKey), i.Value.Key);
}
}
#endregion
}
}

View File

@ -0,0 +1,26 @@
<UserControl
x:Class="DrumKit.ExperimentsSettingsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DrumKit"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Common/TextButtonStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Canvas Name="canvas">
<StackPanel>
<TextBox Style="{StaticResource MyTextBoxStyle}" Width="200" Text="Hello world!"/>
</StackPanel>
</Canvas>
</UserControl>

View File

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
namespace DrumKit
{
public sealed partial class ExperimentsSettingsControl : UserControl
{
public ExperimentsSettingsControl()
{
this.InitializeComponent();
DrumPlayUI ui = new DrumPlayUI(DataController.CurrentDrumkit.Drums.First().Value);
canvas.Children.Add(ui);
Canvas.SetTop(ui, 100);
Canvas.SetLeft(ui, 300);
}
}
}

View File

@ -0,0 +1,174 @@
<UserControl
x:Class="DrumKit.GeneralSettingsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DrumKit"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="635.463"
d:DesignWidth="1075.987">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.Resources>
<Style x:Key="MyTitleTextStyle" TargetType="TextBlock" BasedOn="{StaticResource TitleTextStyle}">
<Setter Property="Margin" Value="20,24,2,2" />
<Setter Property="Foreground" Value="#59FFFF" />
</Style>
<Style x:Key="MyItemTextStyle" TargetType="TextBlock" BasedOn="{StaticResource ItemTextStyle}">
<Setter Property="Margin" Value="2,12,2,2" />
</Style>
</Grid.Resources>
<!-- About section -->
<TextBlock Style="{StaticResource MyTitleTextStyle}"
Grid.Row="0" Margin="20,4,2,2">
About</TextBlock>
<!-- About section: Website -->
<TextBlock Style="{StaticResource ItemTextStyle}"
Grid.Row="1" Margin="2,12,2,2">
Drumkit website</TextBlock>
<Button Name="buttonWebsite"
Style="{StaticResource TextButtonStyle}"
Grid.Row="1" Grid.Column="1" VerticalAlignment="Bottom">
drumkit8.blogspot.com</Button>
<!-- About section: Support -->
<TextBlock Style="{StaticResource ItemTextStyle}"
Grid.Row="2" Margin="2,12,2,2">
Support</TextBlock>
<Button Name="buttonSupport"
Style="{StaticResource TextButtonStyle}"
Grid.Row="2" Grid.Column="1" VerticalAlignment="Bottom">
chibicitiberiu@outlook.com</Button>
<!-- About section: Version -->
<TextBlock Style="{StaticResource ItemTextStyle}"
Grid.Row="3" Margin="2,12,2,2">
Version</TextBlock>
<TextBlock Name="textVersion"
Grid.Row="3" Grid.Column="1" VerticalAlignment="Bottom"
Margin="0,2,2,2"
Style="{StaticResource BodyTextStyle}" >
1.0
</TextBlock>
<!-- Sound section -->
<TextBlock Style="{StaticResource MyTitleTextStyle}"
Grid.Row="6">
Sound</TextBlock>
<!-- Sound section: Master volume -->
<TextBlock Style="{StaticResource ItemTextStyle}"
Grid.Row="7" Margin="2,7,2,2">
Master volume</TextBlock>
<Slider Name="masterVolumeSlider"
Grid.Row="7" Grid.Column="1"
Minimum="0" Maximum="100"
StepFrequency="1"
SmallChange=".05" LargeChange=".2"
Width="100" Height="48"
HorizontalAlignment="Left"/>
<!-- Sound section: Polyphony -->
<TextBlock Style="{StaticResource ItemTextStyle}"
Grid.Row="8" Margin="2,7,2,2">
Polyphony*</TextBlock>
<Slider Name="polyphonySlider"
Grid.Row="8" Grid.Column="1"
Minimum="1" Maximum="256"
StepFrequency="1"
SmallChange="1" LargeChange="5"
Width="100" Height="48"
HorizontalAlignment="Left"/>
<!-- Interface section -->
<TextBlock Style="{StaticResource MyTitleTextStyle}"
Grid.Row="9">
Interface</TextBlock>
<!-- Interface section: Animations -->
<TextBlock Style="{StaticResource ItemTextStyle}"
Grid.Row="10" Margin="2,12,2,2">
Animations</TextBlock>
<ToggleSwitch Name="animationsToggle"
Grid.Row="10" Grid.Column="1"/>
<!-- Interface section: Key bindings -->
<!--<TextBlock Style="{StaticResource ItemTextStyle}"
Grid.Row="11" Margin="2,12,2,2">
Display key bindings</TextBlock>
<ToggleSwitch Name="keyBindingsToggle"
Grid.Row="11" Grid.Column="1"/>-->
<!-- Miscellaneous section -->
<TextBlock Style="{StaticResource MyTitleTextStyle}"
Grid.Row="12">
Miscellaneous</TextBlock>
<!-- Miscellaneous section: Debugging mode -->
<TextBlock Style="{StaticResource ItemTextStyle}"
Grid.Row="13" Margin="2,12,2,2">
Debugging mode</TextBlock>
<ToggleSwitch Name="debuggingModeToggle"
Grid.Row="13" Grid.Column="1"/>
<TextBlock Style="{StaticResource ItemTextStyle}"
Grid.Row="14" Margin="2,12,2,2">
Factory reset*</TextBlock>
<Button Name="buttonReset"
Style="{StaticResource TextButtonStyle}"
Grid.Row="14" Grid.Column="1" VerticalAlignment="Bottom">
Reset</Button>
<!-- Notes section -->
<TextBlock Grid.Row="100" Style="{StaticResource MyItemTextStyle}"
FontSize="11"
Foreground="Silver">
* Will be applied after the application is restarted.
</TextBlock>
</Grid>
</UserControl>

View File

@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using System.Reflection;
using Windows.UI.Popups;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
namespace DrumKit
{
public sealed partial class GeneralSettingsControl : UserControl
{
public GeneralSettingsControl()
{
this.InitializeComponent();
this.LoadSettings();
}
private void LoadSettings()
{
// Version
var version = typeof(GeneralSettingsControl).GetTypeInfo().Assembly.GetName().Version;
this.textVersion.Text = String.Format("{0}.{1}", version.Major, version.Minor);
// Other
this.masterVolumeSlider.Value = DataController.MasterVolume * 100;
this.polyphonySlider.Value = DataController.Settings.Polyphony;
this.animationsToggle.IsOn = DataController.Settings.Animations;
//this.keyBindingsToggle.IsOn = DataController.Settings.ShowKeyBindings;
this.debuggingModeToggle.IsOn = DataController.Settings.DebugMode;
// Set up events
masterVolumeSlider.ValueChanged += masterVolumeSlider_ValueChanged;
polyphonySlider.ValueChanged += polyphonySlider_ValueChanged;
animationsToggle.Toggled += animationsToggle_Toggled;
//keyBindingsToggle.Toggled += keyBindingsToggle_Toggled;
buttonWebsite.Click += buttonWebsite_Click;
buttonSupport.Click += buttonSupport_Click;
buttonReset.Click += buttonReset_Click;
debuggingModeToggle.Toggled += debuggingModeToggle_Toggled;
}
private void masterVolumeSlider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
DataController.MasterVolume = Convert.ToSingle(masterVolumeSlider.Value) / 100.0f;
DataController.SaveSettings();
}
void polyphonySlider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
DataController.Settings.Polyphony = Convert.ToInt32(polyphonySlider.Value);
DataController.SaveSettings();
}
private void animationsToggle_Toggled(object sender, RoutedEventArgs e)
{
DataController.Settings.Animations = this.animationsToggle.IsOn;
DataController.SaveSettings();
}
//private void keyBindingsToggle_Toggled(object sender, RoutedEventArgs e)
//{
// DataController.Settings.ShowKeyBindings = this.keyBindingsToggle.IsOn;
// DataController.SaveSettings();
//}
private async void buttonWebsite_Click(object sender, RoutedEventArgs e)
{
await Windows.System.Launcher.LaunchUriAsync(new Uri("http://drumkit8.blogspot.com/"));
}
private async void buttonSupport_Click(object sender, RoutedEventArgs e)
{
await Windows.System.Launcher.LaunchUriAsync(new Uri("mailto:chibicitiberiu@outlook.com"));
}
private async void buttonReset_Click(object sender, RoutedEventArgs e)
{
// Notify that the application needs to be restarted
MessageDialog dialog = new MessageDialog("The application needs to be restarted in " +
"order to reset to factory settings. Note that every customisation will be deleted.",
"Application restart required");
dialog.Commands.Add(new UICommand("Continue", new UICommandInvokedHandler(UICommandFactoryResetHandler)));
dialog.Commands.Add(new UICommand("Cancel"));
dialog.DefaultCommandIndex = 1;
await dialog.ShowAsync();
}
/// <summary>
/// UI Command that restarts the application, when current drumkit changes
/// </summary>
private void UICommandFactoryResetHandler(Windows.UI.Popups.IUICommand cmd)
{
if (Window.Current.Content is Frame)
{
Frame frame = (Frame) Window.Current.Content;
frame.Navigate(typeof(LoadingPage), "reset");
}
}
private void debuggingModeToggle_Toggled(object sender, RoutedEventArgs e)
{
DataController.Settings.DebugMode = this.debuggingModeToggle.IsOn;
DataController.SaveSettings();
}
}
}

View File

@ -0,0 +1,92 @@
<UserControl
x:Class="DrumKit.LayoutsSettingsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DrumKit"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<UserControl.Resources>
<ResourceDictionary>
<DataTemplate x:Key="DrumkitListDataTemplate">
<Grid Name="theGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<!-- Left thing -->
<Border Name="greenBorder"
Grid.Column="0" Grid.RowSpan="3"
Background="GreenYellow" Width="10" />
<!-- Name -->
<TextBox Grid.Column="1" Grid.Row="0" Margin="15,2,15,0"
FontSize="15.3"
Style="{StaticResource MyTextBoxStyle}"
Text="{Binding Name}"
TextChanged="NameTextChanged" />
<!-- Description -->
<StackPanel Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="1" Margin="15,0,15,2"
Orientation="Horizontal">
<ToggleButton Name="toggleLandscape" Click="ToggleLandscape_Click">Landscape</ToggleButton>
<ToggleButton Name="togglePortrait" Click="TogglePortrait_Click">Portrait</ToggleButton>
<ToggleButton Name="toggleFilled" Click="ToggleFilled_Click">Filled</ToggleButton>
<ToggleButton Name="toggleSnapped" Click="ToggleSnapped_Click">Snapped</ToggleButton>
</StackPanel>
</Grid>
</DataTemplate>
<Style x:Key="ListViewStretchItemStyle" TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<!-- Drumkit list -->
<ListView Name="listLayouts"
Grid.Row="0" Grid.Column="0"
ItemTemplate="{StaticResource DrumkitListDataTemplate}"
ItemContainerStyle="{StaticResource ListViewStretchItemStyle}"
SelectionMode="Single" >
<local:DrumkitLayout IsDefault="True" Name="Hello world" TargetViewSerialize="All" />
<TextBlock>Hello world!</TextBlock>
</ListView>
<!-- Buttons -->
<StackPanel Grid.Row="1" Grid.ColumnSpan="2" Orientation="Horizontal">
<Button Style="{StaticResource MyButtonStyle}" Click="ButtonCreate_Click">Create</Button>
<Button Style="{StaticResource MyButtonStyle}" Click="ButtonEdit_Click">Edit</Button>
<Button Style="{StaticResource MyButtonStyle}" Click="ButtonDelete_Click">Delete</Button>
<Button Style="{StaticResource MyButtonStyle}" Click="ButtonToggleActive_Click">Toggle active</Button>
</StackPanel>
</Grid>
</UserControl>

Some files were not shown because too many files have changed in this diff Show More