diff --git a/logo/ico_512.png b/logo/ico_512.png
new file mode 100644
index 00000000..34b324c1
Binary files /dev/null and b/logo/ico_512.png differ
diff --git a/logo/installer_background.png b/logo/installer_background.png
new file mode 100644
index 00000000..41020b31
Binary files /dev/null and b/logo/installer_background.png differ
diff --git a/logo/installer_background.svg b/logo/installer_background.svg
new file mode 100644
index 00000000..7024faaa
--- /dev/null
+++ b/logo/installer_background.svg
@@ -0,0 +1,109 @@
+
+
+
+
diff --git a/logo/installer_banner.png b/logo/installer_banner.png
new file mode 100644
index 00000000..8c61a683
Binary files /dev/null and b/logo/installer_banner.png differ
diff --git a/logo/installer_banner.svg b/logo/installer_banner.svg
new file mode 100644
index 00000000..58144d9e
--- /dev/null
+++ b/logo/installer_banner.svg
@@ -0,0 +1,99 @@
+
+
+
+
\ No newline at end of file
diff --git a/logo/logo_512.png b/logo/logo_512.png
index 0c738ef7..3a067435 100644
Binary files a/logo/logo_512.png and b/logo/logo_512.png differ
diff --git a/src/AudioBand.AudioSource/AudioBand.AudioSource.csproj b/src/AudioBand.AudioSource/AudioBand.AudioSource.csproj
index 2ce713ca..59cabdbe 100644
--- a/src/AudioBand.AudioSource/AudioBand.AudioSource.csproj
+++ b/src/AudioBand.AudioSource/AudioBand.AudioSource.csproj
@@ -46,6 +46,37 @@
prompt
..\AudioBandRules.ruleset
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE
+ bin\Debug\AudioBand.AudioSource.xml
+ full
+ x64
+ prompt
+ ..\AudioBandRules.ruleset
+
+
+ bin\x64\Release\
+ TRACE
+ bin\Release\AudioBand.AudioSource.xml
+ true
+ pdbonly
+ x64
+ prompt
+ ..\AudioBandRules.ruleset
+
+
+ true
+ bin\x64\Test\
+ CODE_ANALYSIS;CODE_ANALYSIS;DEBUG;TRACE
+ bin\Debug\AudioBand.AudioSource.xml
+ full
+ x64
+ true
+ prompt
+ ..\AudioBandRules.ruleset
+
diff --git a/src/AudioBand.Logging/AudioBand.Logging.csproj b/src/AudioBand.Logging/AudioBand.Logging.csproj
index 2bc28b3c..6e5a9557 100644
--- a/src/AudioBand.Logging/AudioBand.Logging.csproj
+++ b/src/AudioBand.Logging/AudioBand.Logging.csproj
@@ -42,6 +42,34 @@
prompt
..\AudioBandRules.ruleset
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE
+ bin\Debug\AudioBand.Logging.xml
+ full
+ x64
+ prompt
+ ..\AudioBandRules.ruleset
+
+
+ bin\x64\Release\
+ TRACE
+ true
+ pdbonly
+ x64
+ prompt
+ ..\AudioBandRules.ruleset
+
+
+ true
+ bin\x64\Test\
+ DEBUG;TRACE
+ full
+ x64
+ prompt
+ ..\AudioBandRules.ruleset
+
diff --git a/src/AudioBand.Test/AudioBand.Test.csproj b/src/AudioBand.Test/AudioBand.Test.csproj
index 73136727..7331766e 100644
--- a/src/AudioBand.Test/AudioBand.Test.csproj
+++ b/src/AudioBand.Test/AudioBand.Test.csproj
@@ -51,6 +51,33 @@
prompt
MinimumRecommendedRules.ruleset
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE
+ full
+ x64
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+ bin\x64\Release\
+ TRACE
+ true
+ pdbonly
+ x64
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+ true
+ bin\x64\Test\
+ DEBUG;TRACE
+ full
+ x64
+ prompt
+ MinimumRecommendedRules.ruleset
+
diff --git a/src/AudioBand.Test/AudioBandViewModelTests.cs b/src/AudioBand.Test/AudioBandViewModelTests.cs
index cbe7861e..6f3adeaf 100644
--- a/src/AudioBand.Test/AudioBandViewModelTests.cs
+++ b/src/AudioBand.Test/AudioBandViewModelTests.cs
@@ -29,7 +29,7 @@ public void AudioBandViewModelListensToProfileChanges()
_appSettings.SetupSequence(m => m.AudioBand)
.Returns(first)
.Returns(second);
- var vm = new AudioBandViewModel(_appSettings.Object);
+ var vm = new AudioBandViewModel(_appSettings.Object, new Mock().Object);
bool raised = false;
vm.PropertyChanged += (_, __) => raised = true;
diff --git a/src/AudioBand.sln b/src/AudioBand.sln
index f7bc850a..34643bd1 100644
--- a/src/AudioBand.sln
+++ b/src/AudioBand.sln
@@ -19,58 +19,118 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AudioSourceHost", "AudioSou
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AudioBand.Logging", "AudioBand.Logging\AudioBand.Logging.csproj", "{D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}"
EndProject
+Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "AudioBandInstaller", "AudioBandInstaller\AudioBandInstaller.wixproj", "{4E9EEE47-23F6-45B7-9DDB-A34731D6AE4A}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
Test|Any CPU = Test|Any CPU
+ Test|x64 = Test|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B69832AD-8373-47AC-A52A-183238903896}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B69832AD-8373-47AC-A52A-183238903896}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B69832AD-8373-47AC-A52A-183238903896}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B69832AD-8373-47AC-A52A-183238903896}.Debug|x64.Build.0 = Debug|Any CPU
{B69832AD-8373-47AC-A52A-183238903896}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B69832AD-8373-47AC-A52A-183238903896}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B69832AD-8373-47AC-A52A-183238903896}.Release|x64.ActiveCfg = Release|Any CPU
+ {B69832AD-8373-47AC-A52A-183238903896}.Release|x64.Build.0 = Release|Any CPU
{B69832AD-8373-47AC-A52A-183238903896}.Test|Any CPU.ActiveCfg = Test|Any CPU
{B69832AD-8373-47AC-A52A-183238903896}.Test|Any CPU.Build.0 = Test|Any CPU
+ {B69832AD-8373-47AC-A52A-183238903896}.Test|x64.ActiveCfg = Test|Any CPU
+ {B69832AD-8373-47AC-A52A-183238903896}.Test|x64.Build.0 = Test|Any CPU
{30F2BFEA-788A-494D-88E7-F2070528EBEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{30F2BFEA-788A-494D-88E7-F2070528EBEA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {30F2BFEA-788A-494D-88E7-F2070528EBEA}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {30F2BFEA-788A-494D-88E7-F2070528EBEA}.Debug|x64.Build.0 = Debug|Any CPU
{30F2BFEA-788A-494D-88E7-F2070528EBEA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{30F2BFEA-788A-494D-88E7-F2070528EBEA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {30F2BFEA-788A-494D-88E7-F2070528EBEA}.Release|x64.ActiveCfg = Release|Any CPU
+ {30F2BFEA-788A-494D-88E7-F2070528EBEA}.Release|x64.Build.0 = Release|Any CPU
{30F2BFEA-788A-494D-88E7-F2070528EBEA}.Test|Any CPU.ActiveCfg = Test|Any CPU
{30F2BFEA-788A-494D-88E7-F2070528EBEA}.Test|Any CPU.Build.0 = Test|Any CPU
+ {30F2BFEA-788A-494D-88E7-F2070528EBEA}.Test|x64.ActiveCfg = Test|Any CPU
+ {30F2BFEA-788A-494D-88E7-F2070528EBEA}.Test|x64.Build.0 = Test|Any CPU
{43B57D81-7FAE-40D0-921E-E29F7E848288}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{43B57D81-7FAE-40D0-921E-E29F7E848288}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {43B57D81-7FAE-40D0-921E-E29F7E848288}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {43B57D81-7FAE-40D0-921E-E29F7E848288}.Debug|x64.Build.0 = Debug|Any CPU
{43B57D81-7FAE-40D0-921E-E29F7E848288}.Release|Any CPU.ActiveCfg = Release|Any CPU
{43B57D81-7FAE-40D0-921E-E29F7E848288}.Release|Any CPU.Build.0 = Release|Any CPU
+ {43B57D81-7FAE-40D0-921E-E29F7E848288}.Release|x64.ActiveCfg = Release|Any CPU
+ {43B57D81-7FAE-40D0-921E-E29F7E848288}.Release|x64.Build.0 = Release|Any CPU
{43B57D81-7FAE-40D0-921E-E29F7E848288}.Test|Any CPU.ActiveCfg = Test|Any CPU
+ {43B57D81-7FAE-40D0-921E-E29F7E848288}.Test|x64.ActiveCfg = Test|Any CPU
+ {43B57D81-7FAE-40D0-921E-E29F7E848288}.Test|x64.Build.0 = Test|Any CPU
{E5E9CB59-C8CF-4042-9C13-F216153334B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E5E9CB59-C8CF-4042-9C13-F216153334B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E5E9CB59-C8CF-4042-9C13-F216153334B6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {E5E9CB59-C8CF-4042-9C13-F216153334B6}.Debug|x64.Build.0 = Debug|Any CPU
{E5E9CB59-C8CF-4042-9C13-F216153334B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5E9CB59-C8CF-4042-9C13-F216153334B6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E5E9CB59-C8CF-4042-9C13-F216153334B6}.Release|x64.ActiveCfg = Release|Any CPU
+ {E5E9CB59-C8CF-4042-9C13-F216153334B6}.Release|x64.Build.0 = Release|Any CPU
{E5E9CB59-C8CF-4042-9C13-F216153334B6}.Test|Any CPU.ActiveCfg = Test|Any CPU
{E5E9CB59-C8CF-4042-9C13-F216153334B6}.Test|Any CPU.Build.0 = Test|Any CPU
+ {E5E9CB59-C8CF-4042-9C13-F216153334B6}.Test|x64.ActiveCfg = Test|Any CPU
+ {E5E9CB59-C8CF-4042-9C13-F216153334B6}.Test|x64.Build.0 = Test|Any CPU
{6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Debug|x64.Build.0 = Debug|Any CPU
{6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Release|x64.ActiveCfg = Release|Any CPU
+ {6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Release|x64.Build.0 = Release|Any CPU
{6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Test|Any CPU.ActiveCfg = Test|Any CPU
+ {6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Test|x64.ActiveCfg = Test|Any CPU
+ {6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Test|x64.Build.0 = Test|Any CPU
{741DB79C-921D-4D91-85F1-CD10C746F46E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{741DB79C-921D-4D91-85F1-CD10C746F46E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {741DB79C-921D-4D91-85F1-CD10C746F46E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {741DB79C-921D-4D91-85F1-CD10C746F46E}.Debug|x64.Build.0 = Debug|Any CPU
{741DB79C-921D-4D91-85F1-CD10C746F46E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{741DB79C-921D-4D91-85F1-CD10C746F46E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {741DB79C-921D-4D91-85F1-CD10C746F46E}.Release|x64.ActiveCfg = Release|Any CPU
+ {741DB79C-921D-4D91-85F1-CD10C746F46E}.Release|x64.Build.0 = Release|Any CPU
{741DB79C-921D-4D91-85F1-CD10C746F46E}.Test|Any CPU.ActiveCfg = Test|Any CPU
+ {741DB79C-921D-4D91-85F1-CD10C746F46E}.Test|x64.ActiveCfg = Test|Any CPU
+ {741DB79C-921D-4D91-85F1-CD10C746F46E}.Test|x64.Build.0 = Test|Any CPU
{D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Debug|x64.Build.0 = Debug|Any CPU
{D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Release|x64.ActiveCfg = Release|Any CPU
+ {D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Release|x64.Build.0 = Release|Any CPU
{D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Test|Any CPU.ActiveCfg = Test|Any CPU
{D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Test|Any CPU.Build.0 = Test|Any CPU
+ {D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Test|x64.ActiveCfg = Test|Any CPU
+ {D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Test|x64.Build.0 = Test|Any CPU
{D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Debug|x64.Build.0 = Debug|Any CPU
{D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Release|x64.ActiveCfg = Release|Any CPU
+ {D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Release|x64.Build.0 = Release|Any CPU
{D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Test|Any CPU.ActiveCfg = Test|Any CPU
{D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Test|Any CPU.Build.0 = Test|Any CPU
+ {D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Test|x64.ActiveCfg = Test|Any CPU
+ {D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Test|x64.Build.0 = Test|Any CPU
+ {4E9EEE47-23F6-45B7-9DDB-A34731D6AE4A}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {4E9EEE47-23F6-45B7-9DDB-A34731D6AE4A}.Debug|x64.ActiveCfg = Debug|x64
+ {4E9EEE47-23F6-45B7-9DDB-A34731D6AE4A}.Release|Any CPU.ActiveCfg = Release|x64
+ {4E9EEE47-23F6-45B7-9DDB-A34731D6AE4A}.Release|x64.ActiveCfg = Release|x64
+ {4E9EEE47-23F6-45B7-9DDB-A34731D6AE4A}.Release|x64.Build.0 = Release|x64
+ {4E9EEE47-23F6-45B7-9DDB-A34731D6AE4A}.Test|Any CPU.ActiveCfg = Release|x64
+ {4E9EEE47-23F6-45B7-9DDB-A34731D6AE4A}.Test|x64.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/AudioBand/AudioBand.csproj b/src/AudioBand/AudioBand.csproj
index d51e1dbe..5205809e 100644
--- a/src/AudioBand/AudioBand.csproj
+++ b/src/AudioBand/AudioBand.csproj
@@ -55,6 +55,34 @@
prompt
..\AudioBandRules.ruleset
+
+ true
+ bin\x64\Debug\
+ TRACE;DEBUG;DESKBAND_WPF
+ bin\Debug\AudioBand.xml
+ full
+ x64
+ prompt
+ ..\AudioBandRules.ruleset
+
+
+ bin\x64\Release\
+ TRACE;DESKBAND_WPF
+ true
+ pdbonly
+ x64
+ prompt
+ ..\AudioBandRules.ruleset
+
+
+ true
+ bin\x64\Test\
+ TRACE;DEBUG;DESKBAND_WPF
+ full
+ x64
+ prompt
+ ..\AudioBandRules.ruleset
+
@@ -71,6 +99,7 @@
+
@@ -82,6 +111,7 @@
+
@@ -97,9 +127,12 @@
+
+
+
@@ -115,7 +148,7 @@
-
+
@@ -149,6 +182,7 @@
+
@@ -164,6 +198,7 @@
+
@@ -282,6 +317,10 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
@@ -310,6 +349,10 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
@@ -358,6 +401,10 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
diff --git a/src/AudioBand/Behaviors/CanvasPositioning.cs b/src/AudioBand/Behaviors/CanvasPositioning.cs
new file mode 100644
index 00000000..3dd81cd3
--- /dev/null
+++ b/src/AudioBand/Behaviors/CanvasPositioning.cs
@@ -0,0 +1,141 @@
+using System.Windows;
+using System.Windows.Controls;
+using AudioBand.Models;
+
+namespace AudioBand.Behaviors
+{
+ ///
+ /// Attached properties for changing positioning based on values.
+ ///
+ public static class CanvasPositioning
+ {
+ ///
+ /// Identifies the attached property.
+ ///
+ public static readonly DependencyProperty AnchorProperty
+ = DependencyProperty.RegisterAttached("Anchor", typeof(PositionAnchor), typeof(CanvasPositioning), new PropertyMetadata(PositionAnchor.TopLeft, AnchorPropertyChangedCallback));
+
+ ///
+ /// Identifies the attached property.
+ ///
+ public static readonly DependencyProperty AnchorXDistanceProperty
+ = DependencyProperty.RegisterAttached("AnchorXDistance", typeof(double), typeof(CanvasPositioning), new PropertyMetadata(0.0, AnchorXPropertyChangedCallback));
+
+ ///
+ /// Identifies the attached property.
+ ///
+ public static readonly DependencyProperty AnchorYDistanceProperty
+ = DependencyProperty.RegisterAttached("AnchorYDistance", typeof(double), typeof(CanvasPositioning), new PropertyMetadata(0.0, AnchorYPropertyChangedCallback));
+
+ ///
+ /// Gets the value of the property.
+ ///
+ /// The element.
+ /// The anchor value.
+ public static PositionAnchor GetAnchor(UIElement d)
+ {
+ return (PositionAnchor)d.GetValue(AnchorProperty);
+ }
+
+ ///
+ /// Sets the value of the property.
+ ///
+ /// The element.
+ /// The value to set.
+ public static void SetAnchor(UIElement d, PositionAnchor anchor)
+ {
+ d.SetValue(AnchorProperty, anchor);
+ }
+
+ ///
+ /// Gets the value of the property.
+ ///
+ /// The element.
+ /// The anchor x distance.
+ public static double GetAnchorXDistance(UIElement d)
+ {
+ return (double)d.GetValue(AnchorXDistanceProperty);
+ }
+
+ ///
+ /// Sets the value of the property.
+ ///
+ /// The element.
+ /// The value to set.
+ public static void SetAnchorXDistance(UIElement d, double value)
+ {
+ d.SetValue(AnchorXDistanceProperty, value);
+ }
+
+ ///
+ /// Gets the value of the property.
+ ///
+ /// The element.
+ /// The anchor y distance.
+ public static double GetAnchorYDistance(UIElement d)
+ {
+ return (double)d.GetValue(AnchorYDistanceProperty);
+ }
+
+ ///
+ /// Sets the value of the property.
+ ///
+ /// The element.
+ /// The value to set.
+ public static void SetAnchorYDistance(UIElement d, double value)
+ {
+ d.SetValue(AnchorYDistanceProperty, value);
+ }
+
+ private static void AnchorPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ d.SetValue(Canvas.LeftProperty, DependencyProperty.UnsetValue);
+ d.SetValue(Canvas.RightProperty, DependencyProperty.UnsetValue);
+ d.SetValue(Canvas.TopProperty, DependencyProperty.UnsetValue);
+ d.SetValue(Canvas.BottomProperty, DependencyProperty.UnsetValue);
+
+ UpdateX((UIElement)d);
+ UpdateY((UIElement)d);
+ }
+
+ private static void AnchorXPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ UpdateX((UIElement)d);
+ }
+
+ private static void AnchorYPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ UpdateY((UIElement)d);
+ }
+
+ private static void UpdateX(UIElement element)
+ {
+ var anchor = GetAnchor(element);
+ var x = GetAnchorXDistance(element);
+
+ if (anchor.HasFlag(PositionAnchor.Left))
+ {
+ Canvas.SetLeft(element, x);
+ }
+ else if (anchor.HasFlag(PositionAnchor.Right))
+ {
+ Canvas.SetRight(element, x);
+ }
+ }
+
+ private static void UpdateY(UIElement element)
+ {
+ var anchor = GetAnchor(element);
+ var y = GetAnchorYDistance(element);
+
+ if (anchor.HasFlag(PositionAnchor.Top))
+ {
+ Canvas.SetTop(element, y);
+ }
+ else if (anchor.HasFlag(PositionAnchor.Bottom))
+ {
+ Canvas.SetBottom(element, y);
+ }
+ }
+ }
+}
diff --git a/src/AudioBand/Extensions/DescriptorIgnoreAttribute.cs b/src/AudioBand/Extensions/DescriptorIgnoreAttribute.cs
new file mode 100644
index 00000000..ca82f86e
--- /dev/null
+++ b/src/AudioBand/Extensions/DescriptorIgnoreAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace AudioBand.Extensions
+{
+ ///
+ /// Marks enum field as ignored.
+ ///
+ [AttributeUsage(AttributeTargets.Field)]
+ public class DescriptorIgnoreAttribute : Attribute
+ {
+ }
+}
diff --git a/src/AudioBand/Extensions/EnumExtensions.cs b/src/AudioBand/Extensions/EnumExtensions.cs
index 6b9c6901..cd5fb519 100644
--- a/src/AudioBand/Extensions/EnumExtensions.cs
+++ b/src/AudioBand/Extensions/EnumExtensions.cs
@@ -27,6 +27,7 @@ string GetDescription(FieldInfo fieldInfo)
return enumType
.GetFields(BindingFlags.Static | BindingFlags.Public)
+ .Where(field => field.GetCustomAttribute() == null)
.Select(field => new EnumDescriptor((T)field.GetValue(null), GetDescription(field)));
}
}
diff --git a/src/AudioBand/Models/AlbumArt.cs b/src/AudioBand/Models/AlbumArt.cs
index 20d1b744..f488ead9 100644
--- a/src/AudioBand/Models/AlbumArt.cs
+++ b/src/AudioBand/Models/AlbumArt.cs
@@ -3,58 +3,19 @@
///
/// Model for the album art.
///
- public class AlbumArt : ModelBase
+ public class AlbumArt : LayoutModelBase
{
- private bool _isVisible = true;
- private double _width = 30;
- private double _height = 30;
- private double _xPosition = 245;
- private double _yPosition = 0;
private string _placeholderPath = "";
///
- /// Gets or sets a value indicating whether the album art is visible.
+ /// Initializes a new instance of the class.
///
- public bool IsVisible
+ public AlbumArt()
{
- get => _isVisible;
- set => SetProperty(ref _isVisible, value);
- }
-
- ///
- /// Gets or sets the width of the album art.
- ///
- public double Width
- {
- get => _width;
- set => SetProperty(ref _width, value);
- }
-
- ///
- /// Gets or sets the height of the album art.
- ///
- public double Height
- {
- get => _height;
- set => SetProperty(ref _height, value);
- }
-
- ///
- /// Gets or sets the x position of the album art.
- ///
- public double XPosition
- {
- get => _xPosition;
- set => SetProperty(ref _xPosition, value);
- }
-
- ///
- /// Gets or sets the y position of the album art.
- ///
- public double YPosition
- {
- get => _yPosition;
- set => SetProperty(ref _yPosition, value);
+ Width = 30;
+ Height = 30;
+ XPosition = 245;
+ YPosition = 0;
}
///
diff --git a/src/AudioBand/Models/AudioBand.cs b/src/AudioBand/Models/AudioBand.cs
index 2a4426db..c6f7c634 100644
--- a/src/AudioBand/Models/AudioBand.cs
+++ b/src/AudioBand/Models/AudioBand.cs
@@ -1,4 +1,6 @@
-namespace AudioBand.Models
+using System.Windows.Media;
+
+namespace AudioBand.Models
{
///
/// The model for the toolbar.
@@ -7,6 +9,7 @@ public class AudioBand : ModelBase
{
private double _width = 500;
private double _height = 30;
+ private Color _backgroundColor = Colors.Transparent;
///
/// Gets or sets the width of the toolbar.
@@ -25,5 +28,14 @@ public double Height
get => _height;
set => SetProperty(ref _height, value);
}
+
+ ///
+ /// Gets or sets the background color of the toolbar.
+ ///
+ public Color BackgroundColor
+ {
+ get => _backgroundColor;
+ set => SetProperty(ref _backgroundColor, value);
+ }
}
}
diff --git a/src/AudioBand/Models/ButtonModelBase.cs b/src/AudioBand/Models/ButtonModelBase.cs
index bfbaa808..1278da14 100644
--- a/src/AudioBand/Models/ButtonModelBase.cs
+++ b/src/AudioBand/Models/ButtonModelBase.cs
@@ -5,62 +5,12 @@ namespace AudioBand.Models
///
/// Base model for buttons.
///
- public class ButtonModelBase : ModelBase
+ public class ButtonModelBase : LayoutModelBase
{
- private bool _isVisible = true;
- private double _width;
- private double _height;
- private double _xPosition;
- private double _yPosition;
private Color _backgroundColor = Colors.Transparent;
private Color _hoveredBackgroundColor = Color.FromArgb(25, 255, 255, 255);
private Color _clickedBackgroundColor = Color.FromArgb(15, 255, 255, 255);
- ///
- /// Gets or sets a value indicating whether the button is visible.
- ///
- public bool IsVisible
- {
- get => _isVisible;
- set => SetProperty(ref _isVisible, value);
- }
-
- ///
- /// Gets or sets the width of the button.
- ///
- public double Width
- {
- get => _width;
- set => SetProperty(ref _width, value);
- }
-
- ///
- /// Gets or sets the height of the button.
- ///
- public double Height
- {
- get => _height;
- set => SetProperty(ref _height, value);
- }
-
- ///
- /// Gets or sets the x position of the button.
- ///
- public double XPosition
- {
- get => _xPosition;
- set => SetProperty(ref _xPosition, value);
- }
-
- ///
- /// Gets or sets the y position of the button.
- ///
- public double YPosition
- {
- get => _yPosition;
- set => SetProperty(ref _yPosition, value);
- }
-
///
/// Gets or sets the background color.
///
diff --git a/src/AudioBand/Models/CustomLabel.cs b/src/AudioBand/Models/CustomLabel.cs
index dbf844b9..d0c21aa8 100644
--- a/src/AudioBand/Models/CustomLabel.cs
+++ b/src/AudioBand/Models/CustomLabel.cs
@@ -5,13 +5,8 @@ namespace AudioBand.Models
///
/// Model for a custom label.
///
- public class CustomLabel : ModelBase
+ public class CustomLabel : LayoutModelBase
{
- private bool _isVisible = true;
- private double _width = 220;
- private double _height = 15;
- private double _xPosition = 0;
- private double _yPosition = 0;
private string _fontFamily = "Segoe UI";
private float _fontSize = 8.5f;
private Color _color = Colors.White;
@@ -25,6 +20,17 @@ public class CustomLabel : ModelBase
private double _leftFadeOffset = 0.1;
private double _rightFadeOffset = 0.9;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public CustomLabel()
+ {
+ Width = 220;
+ Height = 15;
+ YPosition = 0;
+ XPosition = 0;
+ }
+
///
/// Specifies the alignment of the text in the label.
///
@@ -46,51 +52,6 @@ public enum TextAlignment
Center,
}
- ///
- /// Gets or sets a value indicating whether if the label is visible.
- ///
- public bool IsVisible
- {
- get => _isVisible;
- set => SetProperty(ref _isVisible, value);
- }
-
- ///
- /// Gets or sets the width of the label.
- ///
- public double Width
- {
- get => _width;
- set => SetProperty(ref _width, value);
- }
-
- ///
- /// Gets or sets the height of the label.
- ///
- public double Height
- {
- get => _height;
- set => SetProperty(ref _height, value);
- }
-
- ///
- /// Gets or sets the x position of the label.
- ///
- public double XPosition
- {
- get => _xPosition;
- set => SetProperty(ref _xPosition, value);
- }
-
- ///
- /// Gets or sets the y position of the label.
- ///
- public double YPosition
- {
- get => _yPosition;
- set => SetProperty(ref _yPosition, value);
- }
-
///
/// Gets or sets the font family of the label.
///
diff --git a/src/AudioBand/Models/LayoutModelBase.cs b/src/AudioBand/Models/LayoutModelBase.cs
new file mode 100644
index 00000000..2fe85784
--- /dev/null
+++ b/src/AudioBand/Models/LayoutModelBase.cs
@@ -0,0 +1,69 @@
+namespace AudioBand.Models
+{
+ ///
+ /// Base model that contains support for layout.
+ ///
+ public class LayoutModelBase : ModelBase
+ {
+ private bool _isVisible = true;
+ private double _width;
+ private double _height;
+ private double _xPosition;
+ private double _yPosition;
+ private PositionAnchor _positionAnchor = PositionAnchor.TopLeft;
+
+ ///
+ /// Gets or sets a value indicating whether it is visible.
+ ///
+ public bool IsVisible
+ {
+ get => _isVisible;
+ set => SetProperty(ref _isVisible, value);
+ }
+
+ ///
+ /// Gets or sets the width.
+ ///
+ public double Width
+ {
+ get => _width;
+ set => SetProperty(ref _width, value);
+ }
+
+ ///
+ /// Gets or sets the height.
+ ///
+ public double Height
+ {
+ get => _height;
+ set => SetProperty(ref _height, value);
+ }
+
+ ///
+ /// Gets or sets the x position.
+ ///
+ public double XPosition
+ {
+ get => _xPosition;
+ set => SetProperty(ref _xPosition, value);
+ }
+
+ ///
+ /// Gets or sets the y position.
+ ///
+ public double YPosition
+ {
+ get => _yPosition;
+ set => SetProperty(ref _yPosition, value);
+ }
+
+ ///
+ /// Gets or sets the positioning.
+ ///
+ public PositionAnchor Anchor
+ {
+ get => _positionAnchor;
+ set => SetProperty(ref _positionAnchor, value);
+ }
+ }
+}
diff --git a/src/AudioBand/Models/PositionAnchor.cs b/src/AudioBand/Models/PositionAnchor.cs
new file mode 100644
index 00000000..3edf4cb9
--- /dev/null
+++ b/src/AudioBand/Models/PositionAnchor.cs
@@ -0,0 +1,61 @@
+using System;
+using System.ComponentModel;
+using AudioBand.Extensions;
+
+namespace AudioBand.Models
+{
+ ///
+ /// Specifies the anchor behavior of the position of controls.
+ ///
+ [Flags]
+ public enum PositionAnchor
+ {
+ ///
+ /// Anchor to the top.
+ ///
+ [DescriptorIgnore]
+ Top = 1,
+
+ ///
+ /// Anchor to the right.
+ ///
+ [DescriptorIgnore]
+ Right = 1 << 1,
+
+ ///
+ /// Anchor to the bottom.
+ ///
+ [DescriptorIgnore]
+ Bottom = 1 << 2,
+
+ ///
+ /// Anchor to the left.
+ ///
+ [DescriptorIgnore]
+ Left = 1 << 3,
+
+ ///
+ /// Anchor to top left.
+ ///
+ [Description("Relative to top left")]
+ TopLeft = Top | Left,
+
+ ///
+ /// Anchor to top right.
+ ///
+ [Description("Relative to top right")]
+ TopRight = Top | Right,
+
+ ///
+ /// Anchor to bottom right.
+ ///
+ [Description("Relative to bottom right")]
+ BottomRight = Bottom | Right,
+
+ ///
+ /// Anchor to bottom left.
+ ///
+ [Description("Relative to bottom left")]
+ BottomLeft = Bottom | Left,
+ }
+}
diff --git a/src/AudioBand/Models/PositionAnchors.cs b/src/AudioBand/Models/PositionAnchors.cs
new file mode 100644
index 00000000..3a2e7d35
--- /dev/null
+++ b/src/AudioBand/Models/PositionAnchors.cs
@@ -0,0 +1,16 @@
+using System.Collections.Generic;
+using AudioBand.Extensions;
+
+namespace AudioBand.Models
+{
+ ///
+ /// Static properties for .
+ ///
+ public static class PositionAnchors
+ {
+ ///
+ /// Gets the values for a .
+ ///
+ public static IEnumerable> Values { get; } = typeof(PositionAnchor).GetEnumDescriptors();
+ }
+}
diff --git a/src/AudioBand/Models/ProgressBar.cs b/src/AudioBand/Models/ProgressBar.cs
index 5b4637c0..99ae31cc 100644
--- a/src/AudioBand/Models/ProgressBar.cs
+++ b/src/AudioBand/Models/ProgressBar.cs
@@ -5,16 +5,22 @@ namespace AudioBand.Models
///
/// Model for the progress bar.
///
- public class ProgressBar : ModelBase
+ public class ProgressBar : LayoutModelBase
{
private Color _foregroundColor = Colors.DodgerBlue;
private Color _backgroundColor = Colors.DimGray;
private Color _hoverColor = Colors.DeepSkyBlue;
- private bool _isVisible = true;
- private double _xPosition = 325;
- private double _yPosition = 22;
- private double _width = 130;
- private double _height = 4;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ProgressBar()
+ {
+ Width = 130;
+ Height = 4;
+ XPosition = 325;
+ YPosition = 22;
+ }
///
/// Gets or sets the foreground color.
@@ -42,50 +48,5 @@ public Color HoverColor
get => _hoverColor;
set => SetProperty(ref _hoverColor, value);
}
-
- ///
- /// Gets or sets a value indicating whether the progress bar is visible.
- ///
- public bool IsVisible
- {
- get => _isVisible;
- set => SetProperty(ref _isVisible, value);
- }
-
- ///
- /// Gets or sets the width of the progress bar.
- ///
- public double Width
- {
- get => _width;
- set => SetProperty(ref _width, value);
- }
-
- ///
- /// Gets or sets the height of the progress bar.
- ///
- public double Height
- {
- get => _height;
- set => SetProperty(ref _height, value);
- }
-
- ///
- /// Gets or sets the x position of the progress bar.
- ///
- public double XPosition
- {
- get => _xPosition;
- set => SetProperty(ref _xPosition, value);
- }
-
- ///
- /// Gets or sets the y position of the progress bar.
- ///
- public double YPosition
- {
- get => _yPosition;
- set => SetProperty(ref _yPosition, value);
- }
}
}
diff --git a/src/AudioBand/NativeMethods.cs b/src/AudioBand/NativeMethods.cs
index fc53aade..056e5a4f 100644
--- a/src/AudioBand/NativeMethods.cs
+++ b/src/AudioBand/NativeMethods.cs
@@ -50,27 +50,35 @@ public static void SetWindowAppId(IntPtr hwnd, string appId)
PROPVARIANT.ClearProp(appid);
}
- // Fix blur in windows 1903 causing lag by falling back to old blur behind.
- public static void FixWindowComposition(Window w)
+ public static void DisableAcrylic(Window w)
{
- var win1903 = new Version(10, 0, 18362);
- if (Environment.OSVersion.Version < win1903)
- {
- return;
- }
+ ChangeComposition(w, AccentState.ACCENT_ENABLE_BLURBEHIND);
+ }
- var accent = default(AccentPolicy);
- accent.AccentFlags = 2;
- accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND;
+ public static void EnableAcrylic(Window w)
+ {
+ ChangeComposition(w, AccentState.ACCENT_ENABLE_ACRYLICBLURBEHIND);
+ }
+
+ private static void ChangeComposition(Window w, AccentState state)
+ {
+ var accent = new AccentPolicy
+ {
+ AccentState = state,
+ AccentFlags = 2,
+ GradientColor = 0x00FFFFFF,
+ };
var accentStructSize = Marshal.SizeOf(accent);
var accentPtr = Marshal.AllocHGlobal(accentStructSize);
Marshal.StructureToPtr(accent, accentPtr, false);
- var data = default(WindowCompositionAttributeData);
- data.Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY;
- data.SizeOfData = accentStructSize;
- data.Data = accentPtr;
+ var data = new WindowCompositionAttributeData
+ {
+ Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY,
+ SizeOfData = accentStructSize,
+ Data = accentPtr,
+ };
SetWindowCompositionAttribute(new WindowInteropHelper(w).Handle, ref data);
Marshal.FreeHGlobal(accentPtr);
diff --git a/src/AudioBand/Resources/ButtonStyles.xaml b/src/AudioBand/Resources/ButtonStyles.xaml
index b47b1d66..8a69c0b5 100644
--- a/src/AudioBand/Resources/ButtonStyles.xaml
+++ b/src/AudioBand/Resources/ButtonStyles.xaml
@@ -30,7 +30,8 @@
-
+
@@ -85,8 +86,8 @@
-
+
@@ -145,7 +146,7 @@
diff --git a/src/AudioBand/Resources/ComboBoxStyles.xaml b/src/AudioBand/Resources/ComboBoxStyles.xaml
index 44e51bec..a355f219 100644
--- a/src/AudioBand/Resources/ComboBoxStyles.xaml
+++ b/src/AudioBand/Resources/ComboBoxStyles.xaml
@@ -89,7 +89,9 @@
VerticalContentAlignment="Center" Foreground="{TemplateBinding Foreground}"
Focusable="True" Background="Transparent"
Visibility="Hidden"
- IsReadOnly="{TemplateBinding IsReadOnly}"/>
+ IsReadOnly="{TemplateBinding IsReadOnly}"
+ ContextMenu="{StaticResource StandardInputContextMenu}">
+
@@ -104,7 +106,7 @@
-
+
diff --git a/src/AudioBand/Resources/ContextMenuStyles.xaml b/src/AudioBand/Resources/ContextMenuStyles.xaml
new file mode 100644
index 00000000..546bf264
--- /dev/null
+++ b/src/AudioBand/Resources/ContextMenuStyles.xaml
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/AudioBand/Resources/NavigationPaneStyles.xaml b/src/AudioBand/Resources/NavigationPaneStyles.xaml
index 7ce37b0e..6ce96978 100644
--- a/src/AudioBand/Resources/NavigationPaneStyles.xaml
+++ b/src/AudioBand/Resources/NavigationPaneStyles.xaml
@@ -44,7 +44,7 @@
Opacity="0" StrokeThickness="0"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Fill="{StaticResource RevealHoverLightBrush}"/>
-
-
+
+
\ No newline at end of file
diff --git a/src/AudioBand/Settings/AppSettings.cs b/src/AudioBand/Settings/AppSettings.cs
index 22795b21..6e2b0f20 100644
--- a/src/AudioBand/Settings/AppSettings.cs
+++ b/src/AudioBand/Settings/AppSettings.cs
@@ -283,7 +283,7 @@ private void LoadSettingsFromPath(string path)
}
else
{
- // Check for new settings that were added to the current configuration version.
+ // Fix any null values
var initial = new SettingsV3();
var settings = tomlFile.Get();
new MapperConfiguration(cfg => cfg.AddProfile()).CreateMapper().Map(settings, initial);
diff --git a/src/AudioBand/Settings/Migrations/V2ToV3.cs b/src/AudioBand/Settings/Migrations/V2ToV3.cs
index b180d1b4..21707816 100644
--- a/src/AudioBand/Settings/Migrations/V2ToV3.cs
+++ b/src/AudioBand/Settings/Migrations/V2ToV3.cs
@@ -28,6 +28,7 @@ private MapperConfiguration GetMapConfig()
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap()
+ .ForMember(dest => dest.Anchor, opt => opt.MapFrom(source => PositionAnchor.TopLeft))
.ForMember(dest => dest.ScrollBehavior, opt => opt.Ignore())
.ForMember(dest => dest.TextOverflow, opt => opt.Ignore())
.ForMember(dest => dest.LeftFadeOffset, opt => opt.Ignore())
@@ -35,6 +36,7 @@ private MapperConfiguration GetMapConfig()
.ForMember(dest => dest.FadeEffect, opt => opt.Ignore());
cfg.CreateMap();
cfg.CreateMap()
+ .ForMember(dest => dest.Anchor, opt => opt.MapFrom(source => PositionAnchor.TopLeft))
.ForMember(dest => dest.Content, opt => opt.MapFrom(source => new ButtonContent()))
.ForPath(dest => dest.Content.ImagePath, opt => opt.MapFrom(source => source.ImagePath))
.ForPath(dest => dest.Content.HoveredImagePath, opt => opt.MapFrom(source => source.ImagePath))
@@ -49,6 +51,7 @@ private MapperConfiguration GetMapConfig()
.ForPath(dest => dest.Content.HoveredTextColor, opt => opt.Ignore())
.ForPath(dest => dest.Content.ClickedTextColor, opt => opt.Ignore());
cfg.CreateMap()
+ .ForMember(dest => dest.Anchor, opt => opt.MapFrom(source => PositionAnchor.TopLeft))
.ForMember(dest => dest.Content, opt => opt.MapFrom(source => new ButtonContent()))
.ForPath(dest => dest.Content.ImagePath, opt => opt.MapFrom(source => source.ImagePath))
.ForPath(dest => dest.Content.HoveredImagePath, opt => opt.MapFrom(source => source.ImagePath))
@@ -63,6 +66,7 @@ private MapperConfiguration GetMapConfig()
.ForPath(dest => dest.Content.HoveredTextColor, opt => opt.Ignore())
.ForPath(dest => dest.Content.ClickedTextColor, opt => opt.Ignore());
cfg.CreateMap()
+ .ForMember(dest => dest.Anchor, opt => opt.MapFrom(source => PositionAnchor.TopLeft))
.ForMember(dest => dest.BackgroundColor, opt => opt.Ignore())
.ForMember(dest => dest.HoveredBackgroundColor, opt => opt.Ignore())
.ForMember(dest => dest.ClickedBackgroundColor, opt => opt.Ignore())
@@ -87,7 +91,12 @@ private MapperConfiguration GetMapConfig()
.ForPath(dest => dest.PauseContent.HoveredTextColor, opt => opt.Ignore())
.ForPath(dest => dest.PauseContent.ClickedTextColor, opt => opt.Ignore());
cfg.CreateMap()
+ .ForMember(dest => dest.Anchor, opt => opt.MapFrom(source => PositionAnchor.TopLeft))
.ForMember(dest => dest.HoverColor, opt => opt.Ignore());
+ cfg.CreateMap()
+ .ForMember(dest => dest.BackgroundColor, opt => opt.Ignore());
+ cfg.CreateMap()
+ .ForMember(dest => dest.Anchor, opt => opt.MapFrom(source => PositionAnchor.TopLeft));
cfg.CreateMap()
.ForMember(dest => dest.AlbumArtPopupSettings, opt => opt.MapFrom(source => source.AlbumArtPopupSettings))
.ForMember(dest => dest.AlbumArtSettings, opt => opt.MapFrom(source => source.AlbumArtSettings))
diff --git a/src/AudioBand/Settings/Profiles/SettingsV3Profile.cs b/src/AudioBand/Settings/Profiles/SettingsV3Profile.cs
index ad7abe8e..95beb86a 100644
--- a/src/AudioBand/Settings/Profiles/SettingsV3Profile.cs
+++ b/src/AudioBand/Settings/Profiles/SettingsV3Profile.cs
@@ -1,11 +1,12 @@
-using AudioBand.Models;
+using System.Collections.Generic;
+using AudioBand.Models;
using AudioBand.Settings.Models.v3;
using AutoMapper;
namespace AudioBand.Settings.Profiles
{
///
- /// Fixes new values that are added to the configuration.
+ /// Fixes null settings.
///
internal class SettingsV3Profile : Profile
{
@@ -16,7 +17,15 @@ public SettingsV3Profile()
{
CreateMap();
CreateMap()
- .ForMember(dest => dest.RepeatModeButtonSettings, opt => opt.NullSubstitute(new RepeatModeButton())) // Repeat mode button was added after
+ .ForMember(dest => dest.AlbumArtPopupSettings, opt => opt.NullSubstitute(new AlbumArtPopup()))
+ .ForMember(dest => dest.AlbumArtSettings, opt => opt.NullSubstitute(new AlbumArt()))
+ .ForMember(dest => dest.AudioBandSettings, opt => opt.NullSubstitute(new AudioBand.Models.AudioBand()))
+ .ForMember(dest => dest.CustomLabelSettings, opt => opt.NullSubstitute(new List()))
+ .ForMember(dest => dest.NextButtonSettings, opt => opt.NullSubstitute(new NextButton()))
+ .ForMember(dest => dest.PlayPauseButtonSettings, opt => opt.NullSubstitute(new PlayPauseButton()))
+ .ForMember(dest => dest.PreviousButtonSettings, opt => opt.NullSubstitute(new PreviousButton()))
+ .ForMember(dest => dest.ProgressBarSettings, opt => opt.NullSubstitute(new ProgressBar()))
+ .ForMember(dest => dest.RepeatModeButtonSettings, opt => opt.NullSubstitute(new RepeatModeButton()))
.ForMember(dest => dest.ShuffleModeButtonSettings, opt => opt.NullSubstitute(new ShuffleModeButton()));
}
}
diff --git a/src/AudioBand/ValueConverters/Converters.cs b/src/AudioBand/ValueConverters/Converters.cs
index bab95d5e..9344ba01 100644
--- a/src/AudioBand/ValueConverters/Converters.cs
+++ b/src/AudioBand/ValueConverters/Converters.cs
@@ -1,4 +1,6 @@
-namespace AudioBand.ValueConverters
+using System.Windows.Data;
+
+namespace AudioBand.ValueConverters
{
///
/// Static class that contains converts.
@@ -69,5 +71,15 @@ public static class Converters
/// Gets a .
///
public static EmptyStringToBoolConverter EmptyStringToBool { get; } = new EmptyStringToBoolConverter();
+
+ ///
+ /// Gets a brush to color converter.
+ ///
+ public static IValueConverter BrushToColor { get; } = new ReverseConverter(new ColorToBrushConverter());
+
+ ///
+ /// Gets a .
+ ///
+ public static FlagToBoolConverter HasFlag { get; } = new FlagToBoolConverter();
}
}
diff --git a/src/AudioBand/ValueConverters/FlagToBoolConverter.cs b/src/AudioBand/ValueConverters/FlagToBoolConverter.cs
new file mode 100644
index 00000000..9c25bf0b
--- /dev/null
+++ b/src/AudioBand/ValueConverters/FlagToBoolConverter.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace AudioBand.ValueConverters
+{
+ ///
+ /// Converts enum flag to bool.
+ ///
+ [ValueConversion(typeof(Enum), typeof(bool))]
+ public class FlagToBoolConverter : IValueConverter
+ {
+ ///
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value == null || value == DependencyProperty.UnsetValue || parameter == null)
+ {
+ return false;
+ }
+
+ return ((Enum)value).HasFlag((Enum)parameter);
+ }
+
+ ///
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/AudioBand/ValueConverters/ReverseConverter.cs b/src/AudioBand/ValueConverters/ReverseConverter.cs
index 6d94db94..29078e74 100644
--- a/src/AudioBand/ValueConverters/ReverseConverter.cs
+++ b/src/AudioBand/ValueConverters/ReverseConverter.cs
@@ -12,21 +12,27 @@ namespace AudioBand.ValueConverters
[ContentProperty("Converter")]
public class ReverseConverter : IValueConverter
{
+ private readonly IValueConverter _converter;
+
///
- /// Gets or sets he converter to revrse.
+ /// Initializes a new instance of the class with the converter to reverse.
///
- public IValueConverter Converter { get; set; }
+ /// The converter to reverse.
+ public ReverseConverter(IValueConverter converter)
+ {
+ _converter = converter;
+ }
///
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
- return Converter.ConvertBack(value, targetType, parameter, culture);
+ return _converter.ConvertBack(value, targetType, parameter, culture);
}
///
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
- return Converter.Convert(value, targetType, parameter, culture);
+ return _converter.Convert(value, targetType, parameter, culture);
}
}
}
diff --git a/src/AudioBand/ValueConverters/TimeSpanToMsConverter.cs b/src/AudioBand/ValueConverters/TimeSpanToMsConverter.cs
index 871755e0..25a7530e 100644
--- a/src/AudioBand/ValueConverters/TimeSpanToMsConverter.cs
+++ b/src/AudioBand/ValueConverters/TimeSpanToMsConverter.cs
@@ -1,5 +1,6 @@
using System;
using System.Globalization;
+using System.Windows;
using System.Windows.Data;
namespace AudioBand.ValueConverters
@@ -13,12 +14,22 @@ public class TimeSpanToMsConverter : IValueConverter
///
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
+ if (value == null || value == DependencyProperty.UnsetValue)
+ {
+ return 0;
+ }
+
return ((TimeSpan)value).TotalMilliseconds;
}
///
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
+ if (value == null || value == DependencyProperty.UnsetValue)
+ {
+ return TimeSpan.Zero;
+ }
+
return TimeSpan.FromMilliseconds((double)value);
}
}
diff --git a/src/AudioBand/ViewModels/AboutDialogViewModel.cs b/src/AudioBand/ViewModels/AboutDialogViewModel.cs
index 75edd71e..fd9b4974 100644
--- a/src/AudioBand/ViewModels/AboutDialogViewModel.cs
+++ b/src/AudioBand/ViewModels/AboutDialogViewModel.cs
@@ -1,5 +1,8 @@
-using System.Diagnostics;
+using System;
+using System.Diagnostics;
+using System.IO;
using System.Reflection;
+using System.Windows.Input;
using AudioBand.Commands;
namespace AudioBand.ViewModels
@@ -9,14 +12,6 @@ namespace AudioBand.ViewModels
///
public class AboutDialogViewModel : ViewModelBase
{
- ///
- /// Initializes a new instance of the class.
- ///
- public AboutDialogViewModel()
- {
- OpenLinkCommand = new RelayCommand(OpenLinkCommandOnExecute);
- }
-
///
/// Gets the current audioband version.
///
@@ -40,9 +35,29 @@ public AboutDialogViewModel()
///
/// Gets the command to open the link to the project.
///
- public RelayCommand OpenLinkCommand { get; }
+ public ICommand OpenLinkCommand { get; } = new RelayCommand(OpenLinkCommandOnExecute);
+
+ ///
+ /// Gets the command to open the settings folder.
+ ///
+ public ICommand OpenSettingsFolderCommand { get; } = new RelayCommand(OpenSettingsFolderCommandOnExecute);
+
+ ///
+ /// Gets the command to open the audioband logs.
+ ///
+ public ICommand OpenLog { get; } = new RelayCommand(OpenLogCommandOnExecute);
+
+ private static void OpenLogCommandOnExecute(object obj)
+ {
+ Process.Start(Path.Combine(Path.GetTempPath(), "AudioBand.log"));
+ }
+
+ private static void OpenSettingsFolderCommandOnExecute(object obj)
+ {
+ Process.Start(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AudioBand"));
+ }
- private void OpenLinkCommandOnExecute(string link)
+ private static void OpenLinkCommandOnExecute(string link)
{
Process.Start(link);
}
diff --git a/src/AudioBand/ViewModels/AlbumArtViewModel.cs b/src/AudioBand/ViewModels/AlbumArtViewModel.cs
index 3ad6bdfa..50c9453d 100644
--- a/src/AudioBand/ViewModels/AlbumArtViewModel.cs
+++ b/src/AudioBand/ViewModels/AlbumArtViewModel.cs
@@ -12,7 +12,7 @@ namespace AudioBand.ViewModels
///
/// View model for the album art.
///
- public class AlbumArtViewModel : ViewModelBase
+ public class AlbumArtViewModel : LayoutViewModelBase
{
private readonly IAppSettings _appsettings;
private IAudioSource _audioSource;
@@ -32,56 +32,6 @@ public AlbumArtViewModel(IAppSettings appsettings, IDialogService dialogService)
appsettings.ProfileChanged += AppsettingsOnProfileChanged;
}
- ///
- /// Gets or sets a value indicating whether it is visible.
- ///
- [PropertyChangeBinding(nameof(Models.AlbumArt.IsVisible))]
- public bool IsVisible
- {
- get => Model.IsVisible;
- set => SetProperty(nameof(Model.IsVisible), value);
- }
-
- ///
- /// Gets or sets the width.
- ///
- [PropertyChangeBinding(nameof(Models.AlbumArt.Width))]
- public double Width
- {
- get => Model.Width;
- set => SetProperty(nameof(Model.Width), value);
- }
-
- ///
- /// Gets or sets the height.
- ///
- [PropertyChangeBinding(nameof(Models.AlbumArt.Height))]
- public double Height
- {
- get => Model.Height;
- set => SetProperty(nameof(Model.Height), value);
- }
-
- ///
- /// Gets or sets the x position.
- ///
- [PropertyChangeBinding(nameof(Models.AlbumArt.XPosition))]
- public double XPosition
- {
- get => Model.XPosition;
- set => SetProperty(nameof(Model.XPosition), value);
- }
-
- ///
- /// Gets or sets the y position.
- ///
- [PropertyChangeBinding(nameof(Models.AlbumArt.YPosition))]
- public double YPosition
- {
- get => Model.YPosition;
- set => SetProperty(nameof(Model.YPosition), value);
- }
-
///
/// Gets or sets the placeholder path.
///
diff --git a/src/AudioBand/ViewModels/AudioBandViewModel.cs b/src/AudioBand/ViewModels/AudioBandViewModel.cs
index a127feb4..f31efca6 100644
--- a/src/AudioBand/ViewModels/AudioBandViewModel.cs
+++ b/src/AudioBand/ViewModels/AudioBandViewModel.cs
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
+using System.Windows.Media;
using AudioBand.Settings;
namespace AudioBand.ViewModels
@@ -15,9 +16,11 @@ public class AudioBandViewModel : ViewModelBase
/// Initializes a new instance of the class.
///
/// The app settings.
- public AudioBandViewModel(IAppSettings appsettings)
+ /// The dialog service.
+ public AudioBandViewModel(IAppSettings appsettings, IDialogService dialogService)
: base(appsettings.AudioBand)
{
+ DialogService = dialogService;
_appsettings = appsettings;
appsettings.ProfileChanged += AppsettingsOnProfileChanged;
}
@@ -42,6 +45,21 @@ public double Height
set => SetProperty(nameof(Model.Height), value);
}
+ ///
+ /// Gets or sets the background color.
+ ///
+ [PropertyChangeBinding(nameof(Models.AudioBand.BackgroundColor))]
+ public Color BackgroundColor
+ {
+ get => Model.BackgroundColor;
+ set => SetProperty(nameof(Model.BackgroundColor), value);
+ }
+
+ ///
+ /// Gets the dialog service.
+ ///
+ public IDialogService DialogService { get; }
+
private void AppsettingsOnProfileChanged(object sender, EventArgs e)
{
Debug.Assert(IsEditing == false, "Should not be editing");
diff --git a/src/AudioBand/ViewModels/ButtonViewModelBase.cs b/src/AudioBand/ViewModels/ButtonViewModelBase.cs
index 9d61bc30..69ff8944 100644
--- a/src/AudioBand/ViewModels/ButtonViewModelBase.cs
+++ b/src/AudioBand/ViewModels/ButtonViewModelBase.cs
@@ -10,7 +10,7 @@ namespace AudioBand.ViewModels
/// Base view model for buttons.
///
/// The button model.
- public class ButtonViewModelBase : ViewModelBase
+ public class ButtonViewModelBase : LayoutViewModelBase
where TButton : ButtonModelBase, new()
{
private readonly List _contentViewModels = new List();
@@ -26,56 +26,6 @@ public ButtonViewModelBase(TButton model, IDialogService dialogService)
DialogService = dialogService;
}
- ///
- /// Gets or sets a value indicating whether the button is visible.
- ///
- [PropertyChangeBinding(nameof(ButtonModelBase.IsVisible))]
- public bool IsVisible
- {
- get => Model.IsVisible;
- set => SetProperty(nameof(Model.IsVisible), value);
- }
-
- ///
- /// Gets or sets the width.
- ///
- [PropertyChangeBinding(nameof(ButtonModelBase.Width))]
- public double Width
- {
- get => Model.Width;
- set => SetProperty(nameof(Model.Width), value);
- }
-
- ///
- /// Gets or sets the height.
- ///
- [PropertyChangeBinding(nameof(ButtonModelBase.Height))]
- public double Height
- {
- get => Model.Height;
- set => SetProperty(nameof(Model.Height), value);
- }
-
- ///
- /// Gets or sets the x position.
- ///
- [PropertyChangeBinding(nameof(ButtonModelBase.XPosition))]
- public double XPosition
- {
- get => Model.XPosition;
- set => SetProperty(nameof(Model.XPosition), value);
- }
-
- ///
- /// Gets or sets the y position.
- ///
- [PropertyChangeBinding(nameof(ButtonModelBase.YPosition))]
- public double YPosition
- {
- get => Model.YPosition;
- set => SetProperty(nameof(Model.YPosition), value);
- }
-
///
/// Gets or sets the background color.
///
diff --git a/src/AudioBand/ViewModels/CustomLabelViewModel.cs b/src/AudioBand/ViewModels/CustomLabelViewModel.cs
index ad601917..b759bf80 100644
--- a/src/AudioBand/ViewModels/CustomLabelViewModel.cs
+++ b/src/AudioBand/ViewModels/CustomLabelViewModel.cs
@@ -13,7 +13,7 @@ namespace AudioBand.ViewModels
///
/// The view model for a custom label.
///
- public class CustomLabelViewModel : ViewModelBase
+ public class CustomLabelViewModel : LayoutViewModelBase
{
private readonly FormattedTextParser _parser;
private IAudioSource _audioSource;
@@ -92,56 +92,6 @@ public TextAlignment TextAlignment
set => SetProperty(nameof(Model.Alignment), value);
}
- ///
- /// Gets or sets a value indicating whether the text is visible.
- ///
- [PropertyChangeBinding(nameof(CustomLabel.IsVisible))]
- public bool IsVisible
- {
- get => Model.IsVisible;
- set => SetProperty(nameof(Model.IsVisible), value);
- }
-
- ///
- /// Gets or sets the width.
- ///
- [PropertyChangeBinding(nameof(CustomLabel.Width))]
- public double Width
- {
- get => Model.Width;
- set => SetProperty(nameof(Model.Width), value);
- }
-
- ///
- /// Gets or sets the height.
- ///
- [PropertyChangeBinding(nameof(CustomLabel.Height))]
- public double Height
- {
- get => Model.Height;
- set => SetProperty(nameof(Model.Height), value);
- }
-
- ///
- /// Gets or sets the x position.
- ///
- [PropertyChangeBinding(nameof(CustomLabel.XPosition))]
- public double XPosition
- {
- get => Model.XPosition;
- set => SetProperty(nameof(Model.XPosition), value);
- }
-
- ///
- /// Gets or sets the y position.
- ///
- [PropertyChangeBinding(nameof(CustomLabel.YPosition))]
- public double YPosition
- {
- get => Model.YPosition;
- set => SetProperty(nameof(Model.YPosition), value);
- }
-
///
/// Gets or sets the scroll speed.
///
diff --git a/src/AudioBand/ViewModels/LayoutViewModelBase.cs b/src/AudioBand/ViewModels/LayoutViewModelBase.cs
new file mode 100644
index 00000000..e0bdaec0
--- /dev/null
+++ b/src/AudioBand/ViewModels/LayoutViewModelBase.cs
@@ -0,0 +1,81 @@
+using AudioBand.Models;
+
+namespace AudioBand.ViewModels
+{
+ ///
+ /// Base view model for .
+ ///
+ /// A object.
+ public class LayoutViewModelBase : ViewModelBase
+ where TModel : LayoutModelBase, new()
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The model.
+ public LayoutViewModelBase(TModel model)
+ : base(model)
+ {
+ }
+
+ ///
+ /// Gets or sets a value indicating whether it is visible.
+ ///
+ [PropertyChangeBinding(nameof(LayoutModelBase.IsVisible))]
+ public bool IsVisible
+ {
+ get => Model.IsVisible;
+ set => SetProperty(nameof(Model.IsVisible), value);
+ }
+
+ ///
+ /// Gets or sets the width.
+ ///
+ [PropertyChangeBinding(nameof(LayoutModelBase.Width))]
+ public double Width
+ {
+ get => Model.Width;
+ set => SetProperty(nameof(Model.Width), value);
+ }
+
+ ///
+ /// Gets or sets the height.
+ ///
+ [PropertyChangeBinding(nameof(LayoutModelBase.Height))]
+ public double Height
+ {
+ get => Model.Height;
+ set => SetProperty(nameof(Model.Height), value);
+ }
+
+ ///
+ /// Gets or sets the x position.
+ ///
+ [PropertyChangeBinding(nameof(LayoutModelBase.XPosition))]
+ public double XPosition
+ {
+ get => Model.XPosition;
+ set => SetProperty(nameof(Model.XPosition), value);
+ }
+
+ ///
+ /// Gets or sets the y position.
+ ///
+ [PropertyChangeBinding(nameof(LayoutModelBase.YPosition))]
+ public double YPosition
+ {
+ get => Model.YPosition;
+ set => SetProperty(nameof(Model.YPosition), value);
+ }
+
+ ///
+ /// Gets or sets the relative positioning.
+ ///
+ [PropertyChangeBinding(nameof(LayoutModelBase.Anchor))]
+ public PositionAnchor Anchor
+ {
+ get => Model.Anchor;
+ set => SetProperty(nameof(Model.Anchor), value);
+ }
+ }
+}
diff --git a/src/AudioBand/ViewModels/ProgressBarViewModel.cs b/src/AudioBand/ViewModels/ProgressBarViewModel.cs
index 1adbd736..8a9bae66 100644
--- a/src/AudioBand/ViewModels/ProgressBarViewModel.cs
+++ b/src/AudioBand/ViewModels/ProgressBarViewModel.cs
@@ -1,11 +1,7 @@
using System;
using System.Diagnostics;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Input;
using System.Windows.Media;
using AudioBand.AudioSource;
-using AudioBand.Commands;
using AudioBand.Models;
using AudioBand.Settings;
@@ -14,7 +10,7 @@ namespace AudioBand.ViewModels
///
/// View model for the progress bar.
///
- public class ProgressBarViewModel : ViewModelBase
+ public class ProgressBarViewModel : LayoutViewModelBase
{
private readonly IAppSettings _appsettings;
private IAudioSource _audioSource;
@@ -65,58 +61,6 @@ public Color HoverColor
set => SetProperty(nameof(Model.HoverColor), value);
}
- ///
- /// Gets or sets a value indicating whether the bar is visible.
- ///
- [PropertyChangeBinding(nameof(ProgressBar.IsVisible))]
- public bool IsVisible
- {
- get => Model.IsVisible;
- set => SetProperty(nameof(Model.IsVisible), value);
- }
-
- ///
- /// Gets or sets the width.
- ///
- [PropertyChangeBinding(nameof(ProgressBar.Width))]
- [AlsoNotify(nameof(Size))]
- public double Width
- {
- get => Model.Width;
- set => SetProperty(nameof(Model.Width), value);
- }
-
- ///
- /// Gets or sets the height.
- ///
- [PropertyChangeBinding(nameof(ProgressBar.Height))]
- [AlsoNotify(nameof(Size))]
- public double Height
- {
- get => Model.Height;
- set => SetProperty(nameof(Model.Height), value);
- }
-
- ///
- /// Gets or sets the x position.
- ///
- [PropertyChangeBinding(nameof(ProgressBar.XPosition))]
- public double XPosition
- {
- get => Model.XPosition;
- set => SetProperty(nameof(Model.XPosition), value);
- }
-
- ///
- /// Gets or sets the y position.
- ///
- [PropertyChangeBinding(nameof(ProgressBar.YPosition))]
- public double YPosition
- {
- get => Model.YPosition;
- set => SetProperty(nameof(Model.YPosition), value);
- }
-
///
/// Gets or sets the track progress.
///
diff --git a/src/AudioBand/Views/AudioBandToolbar.xaml b/src/AudioBand/Views/AudioBandToolbar.xaml
index 9266da40..5d658bbb 100644
--- a/src/AudioBand/Views/AudioBandToolbar.xaml
+++ b/src/AudioBand/Views/AudioBandToolbar.xaml
@@ -12,9 +12,10 @@
xmlns:resources="clr-namespace:AudioBand.Resources"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:models="clr-namespace:AudioBand.Models"
+ xmlns:views="clr-namespace:AudioBand.Views"
mc:Ignorable="d"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
- Background="Transparent"
+ Background="{Binding ViewModels.AudioBandViewModel.BackgroundColor, Converter={x:Static converters:Converters.ColorToBrush}}"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance viewModels:AudioBandToolbarViewModel, IsDesignTimeCreatable=False}">
@@ -116,11 +117,13 @@
+ RenderOptions.BitmapScalingMode="Fant"
+ behaviors:CanvasPositioning.Anchor="{Binding Anchor}"
+ behaviors:CanvasPositioning.AnchorXDistance="{Binding XPosition}"
+ behaviors:CanvasPositioning.AnchorYDistance="{Binding YPosition}">
diff --git a/src/AudioBand/Views/AudioBandToolbar.xaml.cs b/src/AudioBand/Views/AudioBandToolbar.xaml.cs
index 681493db..4200872e 100644
--- a/src/AudioBand/Views/AudioBandToolbar.xaml.cs
+++ b/src/AudioBand/Views/AudioBandToolbar.xaml.cs
@@ -33,6 +33,7 @@ private void OnSizeChanged(object sender, SizeChangedEventArgs e)
var deskbandSize = new DeskBandSize((int)Math.Round(ActualWidth * scale), (int)Math.Round(ActualHeight * scale));
_options.MinHorizontalSize = deskbandSize;
_options.HorizontalSize = deskbandSize;
+ _options.MaxHorizontalHeight = deskbandSize.Height;
}
}
}
diff --git a/src/AudioBand/Views/Dialogs/AboutDialog.xaml b/src/AudioBand/Views/Dialogs/AboutDialog.xaml
index 6e3c5efc..0802041b 100644
--- a/src/AudioBand/Views/Dialogs/AboutDialog.xaml
+++ b/src/AudioBand/Views/Dialogs/AboutDialog.xaml
@@ -89,7 +89,16 @@
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/src/AudioBand/Views/Settings/ButtonBaseTemplate.xaml b/src/AudioBand/Views/Settings/ButtonBaseTemplate.xaml
index 7aa9f319..d6911c37 100644
--- a/src/AudioBand/Views/Settings/ButtonBaseTemplate.xaml
+++ b/src/AudioBand/Views/Settings/ButtonBaseTemplate.xaml
@@ -2,10 +2,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:AudioBand.Views.Settings"
xmlns:resources="clr-namespace:AudioBand.Resources"
- xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
- xmlns:behaviors="clr-namespace:AudioBand.Behaviors"
- xmlns:models="clr-namespace:AudioBand.Models"
- xmlns:viewModels="clr-namespace:AudioBand.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
@@ -15,24 +11,12 @@
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/src/AudioBand/Views/Settings/CustomLabelSettingsView.xaml b/src/AudioBand/Views/Settings/CustomLabelSettingsView.xaml
index 6d266e5a..c882d5d0 100644
--- a/src/AudioBand/Views/Settings/CustomLabelSettingsView.xaml
+++ b/src/AudioBand/Views/Settings/CustomLabelSettingsView.xaml
@@ -7,7 +7,8 @@
xmlns:behaviors="clr-namespace:AudioBand.Behaviors"
xmlns:converters="clr-namespace:AudioBand.ValueConverters"
xmlns:models="clr-namespace:AudioBand.Models"
- xmlns:resources="clr-namespace:AudioBand.Resources">
+ xmlns:resources="clr-namespace:AudioBand.Resources"
+ xmlns:theming="clr-namespace:AudioBand.Resources.Theming">
@@ -16,26 +17,15 @@
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -75,8 +65,12 @@
-
-
+
+
+
+
+
Tags
@@ -120,7 +114,7 @@
-
+
diff --git a/src/AudioBand/Views/Settings/GeneralSettingsView.xaml b/src/AudioBand/Views/Settings/GeneralSettingsView.xaml
index 28b055ea..b31a3ad7 100644
--- a/src/AudioBand/Views/Settings/GeneralSettingsView.xaml
+++ b/src/AudioBand/Views/Settings/GeneralSettingsView.xaml
@@ -3,7 +3,8 @@
xmlns:viewmodels="clr-namespace:AudioBand.ViewModels"
xmlns:metro="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:behaviors="clr-namespace:AudioBand.Behaviors"
- xmlns:resources="clr-namespace:AudioBand.Resources">
+ xmlns:resources="clr-namespace:AudioBand.Resources"
+ xmlns:settings="clr-namespace:AudioBand.Views.Settings">
@@ -20,6 +21,7 @@
+
diff --git a/src/AudioBand/Views/Settings/LayoutSettingsTemplate.xaml b/src/AudioBand/Views/Settings/LayoutSettingsTemplate.xaml
new file mode 100644
index 00000000..4808bada
--- /dev/null
+++ b/src/AudioBand/Views/Settings/LayoutSettingsTemplate.xaml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/AudioBand/Views/Settings/ProgressBarSettingsView.xaml b/src/AudioBand/Views/Settings/ProgressBarSettingsView.xaml
index 202c5c6e..4f2bf974 100644
--- a/src/AudioBand/Views/Settings/ProgressBarSettingsView.xaml
+++ b/src/AudioBand/Views/Settings/ProgressBarSettingsView.xaml
@@ -12,23 +12,12 @@
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/src/AudioBand/Views/Settings/SettingsWindow.xaml b/src/AudioBand/Views/Settings/SettingsWindow.xaml
index dae59aa4..a8fe7189 100644
--- a/src/AudioBand/Views/Settings/SettingsWindow.xaml
+++ b/src/AudioBand/Views/Settings/SettingsWindow.xaml
@@ -56,10 +56,23 @@
@@ -132,7 +145,7 @@
-
+
@@ -140,7 +153,7 @@
-
-
-
-
-
-
-
-
diff --git a/src/AudioBand/Views/Settings/SettingsWindow.xaml.cs b/src/AudioBand/Views/Settings/SettingsWindow.xaml.cs
index f945947b..9e6fc268 100644
--- a/src/AudioBand/Views/Settings/SettingsWindow.xaml.cs
+++ b/src/AudioBand/Views/Settings/SettingsWindow.xaml.cs
@@ -2,6 +2,7 @@
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
+using System.Windows.Interop;
using AudioBand.Commands;
using AudioBand.Messages;
using AudioBand.ViewModels;
@@ -105,7 +106,32 @@ private void ViewModelOnPropertyChanged(object sender, PropertyChangedEventArgs
private void OnLoaded(object sender, RoutedEventArgs e)
{
- NativeMethods.FixWindowComposition(this);
+ // Windows 10 1903 acrylic fix
+ var win1903 = new Version(10, 0, 18362);
+ if (Environment.OSVersion.Version < win1903)
+ {
+ return;
+ }
+
+ ((HwndSource)PresentationSource.FromVisual(this)).AddHook(Hook);
+ }
+
+ private IntPtr Hook(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled)
+ {
+ const int WM_ENTERSIZEMOVE = 0x0231;
+ const int WM_EXITSIZEMOVE = 0x0232;
+
+ switch (msg)
+ {
+ case WM_ENTERSIZEMOVE:
+ NativeMethods.DisableAcrylic(this);
+ break;
+ case WM_EXITSIZEMOVE:
+ NativeMethods.EnableAcrylic(this);
+ break;
+ }
+
+ return IntPtr.Zero;
}
}
}
diff --git a/src/AudioBand/audioband.ico b/src/AudioBand/audioband.ico
index cb54c906..50745cdf 100644
Binary files a/src/AudioBand/audioband.ico and b/src/AudioBand/audioband.ico differ
diff --git a/src/AudioBandInstaller/.gitignore b/src/AudioBandInstaller/.gitignore
new file mode 100644
index 00000000..d70e3cce
--- /dev/null
+++ b/src/AudioBandInstaller/.gitignore
@@ -0,0 +1,4 @@
+AudioBandHeatGenerated.wxs
+iTunesHeatGenerated.wxs
+MusicBeeHeatGenerated.wxs
+SpotifyHeatGenerated.wxs
\ No newline at end of file
diff --git a/src/AudioBandInstaller/AudioBandCOM.wxs b/src/AudioBandInstaller/AudioBandCOM.wxs
new file mode 100644
index 00000000..74e00e34
--- /dev/null
+++ b/src/AudioBandInstaller/AudioBandCOM.wxs
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/AudioBandInstaller/AudioBandHeatXsl.xslt b/src/AudioBandInstaller/AudioBandHeatXsl.xslt
new file mode 100644
index 00000000..c92aff44
--- /dev/null
+++ b/src/AudioBandInstaller/AudioBandHeatXsl.xslt
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/AudioBandInstaller/AudioBandInstaller.wixproj b/src/AudioBandInstaller/AudioBandInstaller.wixproj
new file mode 100644
index 00000000..7fcaecd2
--- /dev/null
+++ b/src/AudioBandInstaller/AudioBandInstaller.wixproj
@@ -0,0 +1,128 @@
+
+
+
+ Debug
+ x64
+ 3.10
+ 4e9eee47-23f6-45b7-9ddb-a34731d6ae4a
+ 2.0
+ AudioBand
+ Package
+ x64
+
+
+ bin\$(Configuration)\
+ obj\$(Configuration)\
+ Debug
+
+
+ bin\$(Configuration)\
+ obj\$(Configuration)\
+
+
+
+
+
+
+
+
+
+
+
+
+ $(WixToolPath)WixUIExtension.dll
+ WixUIExtension
+
+
+ $(WixToolPath)WixUtilExtension.dll
+ WixUtilExtension
+
+
+
+
+ AudioBand.AudioSource
+ {30f2bfea-788a-494d-88e7-f2070528ebea}
+ True
+
+
+ Binaries;Content;Satellites
+ INSTALLFOLDER
+
+
+ AudioBand.Logging
+ {d8e1d3e5-d0ab-43c4-8af6-60c14c5c6843}
+ True
+
+
+ Binaries;Content;Satellites
+ INSTALLFOLDER
+
+
+ AudioBand
+ {b69832ad-8373-47ac-a52a-183238903896}
+ True
+
+
+ Binaries;Content;Satellites
+ INSTALLFOLDER
+
+
+ AudioSourceHost
+ {d3f92c3e-e546-4a6b-ada2-facd95e229f7}
+ True
+
+
+ Binaries;Content;Satellites
+ INSTALLFOLDER
+
+
+ iTunesAudioSource
+ {6d881b7b-3f3f-4613-a83f-75e31eea5252}
+ True
+
+
+ Binaries;Content;Satellites
+ AudioSourcesFolder
+
+
+ MusicBeeAudioSource
+ {741db79c-921d-4d91-85f1-cd10c746f46e}
+ True
+
+
+ Binaries;Content;Satellites
+ AudioSourcesFolder
+
+
+ SpotifyAudioSource
+ {43b57d81-7fae-40d0-921e-e29f7e848288}
+ True
+
+
+ Binaries;Content;Satellites
+ AudioSourcesFolder
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AudioBandHarvestPath=..\Audioband\bin\$(Configuration);ITunesHarvestPath=..\iTunesAudioSource\bin\$(Configuration)\iTunes;MusicBeeHarvestPath=..\MusicBeeAudioSource\bin\$(Configuration)\MusicBee;SpotifyHarvestPath=..\SpotifyAudioSource\bin\$(Configuration)\spotify
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/AudioBandInstaller/AudioSourcesXsl.xslt b/src/AudioBandInstaller/AudioSourcesXsl.xslt
new file mode 100644
index 00000000..198ab904
--- /dev/null
+++ b/src/AudioBandInstaller/AudioSourcesXsl.xslt
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/AudioBandInstaller/InstallerUI.wxs b/src/AudioBandInstaller/InstallerUI.wxs
new file mode 100644
index 00000000..f606659c
--- /dev/null
+++ b/src/AudioBandInstaller/InstallerUI.wxs
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+ NOT Installed AND NOT PATCH
+ Installed AND PATCH
+
+ 1
+ 1
+ 1
+ 1
+
+ WixUI_InstallMode = "Change"
+ WixUI_InstallMode = "InstallCustom"
+ 1
+
+ WixUI_InstallMode = "InstallCustom"
+ WixUI_InstallMode = "InstallTypical" OR WixUI_InstallMode = "InstallComplete"
+ WixUI_InstallMode = "Change"
+ WixUI_InstallMode = "Repair" OR WixUI_InstallMode = "Remove"
+ WixUI_InstallMode = "Update"
+
+ 1
+
+ 1
+ 1
+ 1
+ 1
+
+
+
+
+
diff --git a/src/AudioBandInstaller/Product.wxs b/src/AudioBandInstaller/Product.wxs
new file mode 100644
index 00000000..142c14bd
Binary files /dev/null and b/src/AudioBandInstaller/Product.wxs differ
diff --git a/src/AudioBandInstaller/audioband.ico b/src/AudioBandInstaller/audioband.ico
new file mode 100644
index 00000000..50745cdf
Binary files /dev/null and b/src/AudioBandInstaller/audioband.ico differ
diff --git a/src/AudioBandInstaller/installer_background.bmp b/src/AudioBandInstaller/installer_background.bmp
new file mode 100644
index 00000000..491dddf2
Binary files /dev/null and b/src/AudioBandInstaller/installer_background.bmp differ
diff --git a/src/AudioBandInstaller/installer_banner.bmp b/src/AudioBandInstaller/installer_banner.bmp
new file mode 100644
index 00000000..a738eaec
Binary files /dev/null and b/src/AudioBandInstaller/installer_banner.bmp differ
diff --git a/src/AudioSourceHost/AudioSourceHost.csproj b/src/AudioSourceHost/AudioSourceHost.csproj
index b335b537..88d85e7d 100644
--- a/src/AudioSourceHost/AudioSourceHost.csproj
+++ b/src/AudioSourceHost/AudioSourceHost.csproj
@@ -47,6 +47,34 @@
prompt
..\AudioBandRules.ruleset
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE
+ bin\Debug\AudioSourceHost.xml
+ full
+ x64
+ prompt
+ ..\AudioBandRules.ruleset
+
+
+ bin\x64\Release\
+ TRACE
+ true
+ pdbonly
+ x64
+ prompt
+ ..\AudioBandRules.ruleset
+
+
+ true
+ bin\x64\Test\
+ DEBUG;TRACE
+ full
+ x64
+ prompt
+ ..\AudioBandRules.ruleset
+
diff --git a/src/MusicBeeAudioSource/MusicBeeAudioSource.csproj b/src/MusicBeeAudioSource/MusicBeeAudioSource.csproj
index 47799736..44f9cebf 100644
--- a/src/MusicBeeAudioSource/MusicBeeAudioSource.csproj
+++ b/src/MusicBeeAudioSource/MusicBeeAudioSource.csproj
@@ -43,6 +43,34 @@
prompt
..\AudioBandRules.ruleset
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE
+ full
+ x64
+ prompt
+ ..\AudioBandRules.ruleset
+
+
+ bin\x64\Release\
+ TRACE
+ true
+ pdbonly
+ x64
+ prompt
+ ..\AudioBandRules.ruleset
+
+
+ true
+ bin\x64\Test\
+ CODE_ANALYSIS;CODE_ANALYSIS;DEBUG;TRACE
+ full
+ x64
+ true
+ prompt
+ ..\AudioBandRules.ruleset
+
@@ -88,6 +116,10 @@
- (robocopy "$(TargetDir)\" "$(SolutionDir)AudioBand\$(OutDir)AudioSources\MusicBee\\" /xf AudioBand.AudioSource.dll) ^& IF %25ERRORLEVEL%25 LEQ 1 exit 0
+ if NOT "$(Configuration)" == "Release" (
+ (robocopy "$(TargetDir)\" "$(SolutionDir)AudioBand\$(OutDir)AudioSources\MusicBee\\" /xf AudioBand.AudioSource.*) ^& IF %25ERRORLEVEL%25 LEQ 1 exit 0
+) ELSE (
+ (robocopy "$(TargetDir)\" "$(TargetDir)MusicBee\\" /xf AudioBand.AudioSource.*) ^& IF %25ERRORLEVEL%25 LEQ 1 exit 0
+)
\ No newline at end of file
diff --git a/src/SpotifyAudioSource/SpotifyAudioSource.csproj b/src/SpotifyAudioSource/SpotifyAudioSource.csproj
index 0f3306f7..28b8c203 100644
--- a/src/SpotifyAudioSource/SpotifyAudioSource.csproj
+++ b/src/SpotifyAudioSource/SpotifyAudioSource.csproj
@@ -46,6 +46,34 @@
prompt
..\AudioBandRules.ruleset
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE
+ full
+ x64
+ prompt
+ ..\AudioBandRules.ruleset
+
+
+ bin\x64\Release\
+ TRACE
+ true
+ pdbonly
+ x64
+ prompt
+ ..\AudioBandRules.ruleset
+
+
+ true
+ bin\x64\Test\
+ CODE_ANALYSIS;CODE_ANALYSIS;DEBUG;TRACE
+ full
+ x64
+ true
+ prompt
+ ..\AudioBandRules.ruleset
+
@@ -94,6 +122,10 @@
- (robocopy "$(TargetDir)\" "$(SolutionDir)AudioBand\$(OutDir)AudioSources\spotify\\" /xf AudioBand.AudioSource.dll) ^& IF %25ERRORLEVEL%25 LEQ 1 exit 0
+ if NOT "$(Configuration)" == "Release" (
+ (robocopy "$(TargetDir)\" "$(SolutionDir)AudioBand\$(OutDir)AudioSources\spotify\\" /xf AudioBand.AudioSource.*) ^& IF %25ERRORLEVEL%25 LEQ 1 exit 0
+) ELSE (
+ (robocopy "$(TargetDir)\" "$(TargetDir)spotify\\" /xf AudioBand.AudioSource.*) ^& IF %25ERRORLEVEL%25 LEQ 1 exit 0
+)
\ No newline at end of file
diff --git a/src/iTunesAudioSource/iTunesAudioSource.csproj b/src/iTunesAudioSource/iTunesAudioSource.csproj
index ba52933a..05d0b239 100644
--- a/src/iTunesAudioSource/iTunesAudioSource.csproj
+++ b/src/iTunesAudioSource/iTunesAudioSource.csproj
@@ -43,6 +43,34 @@
prompt
..\AudioBandRules.ruleset
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE
+ full
+ x64
+ prompt
+ ..\AudioBandRules.ruleset
+
+
+ bin\x64\Release\
+ TRACE
+ true
+ pdbonly
+ x64
+ prompt
+ ..\AudioBandRules.ruleset
+
+
+ true
+ bin\x64\Test\
+ CODE_ANALYSIS;CODE_ANALYSIS;DEBUG;TRACE
+ full
+ x64
+ true
+ prompt
+ ..\AudioBandRules.ruleset
+
.\Interop.iTunesLib.dll
@@ -83,6 +111,10 @@
- (robocopy "$(TargetDir)\" "$(SolutionDir)AudioBand\$(OutDir)AudioSources\iTunes\\" /xf AudioBand.AudioSource.dll) ^& IF %25ERRORLEVEL%25 LEQ 1 exit 0
+ if NOT "$(Configuration)" == "Release" (
+ (robocopy "$(TargetDir)\" "$(SolutionDir)AudioBand\$(OutDir)AudioSources\iTunes\\" /xf AudioBand.AudioSource.*) ^& IF %25ERRORLEVEL%25 LEQ 1 exit 0
+) ELSE (
+ (robocopy "$(TargetDir)\" "$(TargetDir)iTunes\\" /xf AudioBand.AudioSource.*) ^& IF %25ERRORLEVEL%25 LEQ 1 exit 0
+)
\ No newline at end of file
diff --git a/tools/createicon.ps1 b/tools/createicon.ps1
index c694bd48..cba3aab5 100644
--- a/tools/createicon.ps1
+++ b/tools/createicon.ps1
@@ -1,5 +1,9 @@
+param (
+ [string]$source
+)
+
$sizes = 16, 32, 48, 128, 256
-$image = [System.IO.Path]::GetFullPath($args[0])
+$image = [System.IO.Path]::GetFullPath($source)
if (!$image) {
Write-Error "Missing image argument"
exit
diff --git a/tools/extractversion.ps1 b/tools/extractversion.ps1
new file mode 100644
index 00000000..ec9710de
--- /dev/null
+++ b/tools/extractversion.ps1
@@ -0,0 +1,12 @@
+param(
+ [Parameter(Mandatory = $true)][string]$versionString
+)
+
+$pattern = "^v(?0|[1-9]\d*)\.(?0|[1-9]\d*)\.(?0|[1-9]\d*)(-(?0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))?$"
+$version = [regex]::Match($versionString, $pattern)
+if ($version.Success) {
+ $env:AUDIOBAND_VERSION_MAJOR = $version.Groups["major"]
+ $env:AUDIOBAND_VERSION_MINOR = $version.Groups["minor"]
+ $env:AUDIOBAND_VERSION_PATCH = $version.Groups["patch"]
+ $env:AUDIOBAND_VERSION_PRERELEASE = $version.Groups["prerelease"]
+}
\ No newline at end of file
diff --git a/tools/patchinstaller.ps1 b/tools/patchinstaller.ps1
new file mode 100644
index 00000000..6c855836
--- /dev/null
+++ b/tools/patchinstaller.ps1
@@ -0,0 +1,20 @@
+param(
+ [Parameter(Mandatory = $true)][string]$major,
+ [Parameter(Mandatory = $true)][string]$minor,
+ [Parameter(Mandatory = $true)][string]$patch
+)
+
+$productVersionToken = ''
+$productIdToken = ''
+
+$newVersion = "$major.$minor.$patch"
+Write-Host "Updating version to $newVersion"
+
+$newGuid = [guid]::NewGuid()
+Write-Host "Creating new GUID $newGuid"
+
+$targetFile = $PSScriptRoot + '/../src/AudioBandInstaller/Product.wxs'
+$versionReplace = ""
+$guidReplace = ""
+
+(Get-Content "$targetFile").replace("$productVersionToken", "$versionReplace").replace("$productIdToken", "$guidReplace") | Set-Content -Encoding UTF8 "$targetFile"
\ No newline at end of file