Skip to content

Commit

Permalink
Add Play Sound instruction and trigger
Browse files Browse the repository at this point in the history
  • Loading branch information
daleghent committed Mar 26, 2023
1 parent fc97fad commit 0708895
Show file tree
Hide file tree
Showing 13 changed files with 679 additions and 3 deletions.
6 changes: 6 additions & 0 deletions App.config
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ Reasons: $$ERROR_LIST$$
<setting name="PushoverEmergExpireAfter" serializeAs="String">
<value>600</value>
</setting>
<setting name="PlaySoundDefaultFile" serializeAs="String">
<value />
</setting>
<setting name="PlaySoundDefaultFailureFile" serializeAs="String">
<value />
</setting>
</DaleGhent.NINA.GroundStation.Properties.Settings>
</userSettings>
</configuration>
5 changes: 3 additions & 2 deletions Ground Station.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="MailKit">
<Version>3.4.2</Version>
<Version>3.6.0</Version>
<IncludeAssets></IncludeAssets>
</PackageReference>
<PackageReference Include="MQTTnet">
<Version>3.1.2</Version>
</PackageReference>
<PackageReference Include="NetCoreAudio" Version="1.7.0" />
<PackageReference Include="NINA.Plugin" Version="3.0.0.1001-nightly" />
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
<PackageReference Include="System.Speech" Version="7.0.0" />
Expand Down Expand Up @@ -54,6 +55,6 @@
</None>
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="if not exist &quot;%25localappdata%25\NINA\Plugin\$(TargetName)&quot; (&#xD;&#xA; echo &quot;Creating $(PlatformName) Plugins $(TargetName) folder&quot;&#xD;&#xA; mkdir &quot;%25localappdata%25\NINA\Plugins\$(TargetName)&quot;&#xD;&#xA;)&#xD;&#xA;&#xD;&#xA;echo &quot;Copying artifacts&quot;&#xD;&#xA;xcopy &quot;$(TargetPath)&quot; &quot;%25localappdata%25\NINA\Plugins\$(TargetName)&quot; /h/i/c/k/e/r/y&#xD;&#xA;xcopy &quot;$(TargetDir)$(TargetName).pdb&quot; &quot;%25localappdata%25\NINA\Plugins\$(TargetName)&quot; /h/i/c/k/e/r/y&#xD;&#xA;xcopy &quot;$(TargetDir)runtimes\win\lib\net7.0\System.Speech.dll&quot; &quot;%25localappdata%25\NINA\Plugins\$(TargetName)&quot; /h/i/c/k/e/r/y&#xD;&#xA;xcopy &quot;$(TargetDir)MailKit.dll&quot; &quot;%25localappdata%25\NINA\Plugins\$(TargetName)&quot; /h/i/c/k/e/r/y&#xD;&#xA;xcopy &quot;$(TargetDir)MimeKit.dll&quot; &quot;%25localappdata%25\NINA\Plugins\$(TargetName)&quot; /h/i/c/k/e/r/y&#xD;&#xA;xcopy &quot;$(TargetDir)BouncyCastle.Crypto.dll&quot; &quot;%25localappdata%25\NINA\Plugins\$(TargetName)&quot; /h/i/c/k/e/r/y&#xD;&#xA;xcopy &quot;$(TargetDir)Telegram.Bot.dll&quot; &quot;%25localappdata%25\NINA\Plugins\$(TargetName)&quot; /h/i/c/k/e/r/y&#xD;&#xA;xcopy &quot;$(TargetDir)MQTTnet.dll&quot; &quot;%25localappdata%25\NINA\Plugins\$(TargetName)&quot; /h/i/c/k/e/r/y" />
<Exec Command="if not exist &quot;%25localappdata%25\NINA\Plugin\$(TargetName)&quot; (&#xD;&#xA; echo &quot;Creating $(PlatformName) Plugins $(TargetName) folder&quot;&#xD;&#xA; mkdir &quot;%25localappdata%25\NINA\Plugins\$(TargetName)&quot;&#xD;&#xA;)&#xD;&#xA;&#xD;&#xA;echo &quot;Copying artifacts&quot;&#xD;&#xA;xcopy &quot;$(TargetPath)&quot; &quot;%25localappdata%25\NINA\Plugins\$(TargetName)&quot; /h/i/c/k/e/r/y&#xD;&#xA;xcopy &quot;$(TargetDir)$(TargetName).pdb&quot; &quot;%25localappdata%25\NINA\Plugins\$(TargetName)&quot; /h/i/c/k/e/r/y&#xD;&#xA;xcopy &quot;$(TargetDir)runtimes\win\lib\net7.0\System.Speech.dll&quot; &quot;%25localappdata%25\NINA\Plugins\$(TargetName)&quot; /h/i/c/k/e/r/y&#xD;&#xA;xcopy &quot;$(TargetDir)MailKit.dll&quot; &quot;%25localappdata%25\NINA\Plugins\$(TargetName)&quot; /h/i/c/k/e/r/y&#xD;&#xA;xcopy &quot;$(TargetDir)MimeKit.dll&quot; &quot;%25localappdata%25\NINA\Plugins\$(TargetName)&quot; /h/i/c/k/e/r/y&#xD;&#xA;xcopy &quot;$(TargetDir)BouncyCastle.Crypto.dll&quot; &quot;%25localappdata%25\NINA\Plugins\$(TargetName)&quot; /h/i/c/k/e/r/y&#xD;&#xA;xcopy &quot;$(TargetDir)Telegram.Bot.dll&quot; &quot;%25localappdata%25\NINA\Plugins\$(TargetName)&quot; /h/i/c/k/e/r/y&#xD;&#xA;xcopy &quot;$(TargetDir)MQTTnet.dll&quot; &quot;%25localappdata%25\NINA\Plugins\$(TargetName)&quot; /h/i/c/k/e/r/y&#xD;&#xA;xcopy &quot;$(TargetDir)NetCoreAudio.dll&quot; &quot;%25localappdata%25\NINA\Plugins\$(TargetName)&quot; /h/i/c/k/e/r/y" />
</Target>
</Project>
47 changes: 47 additions & 0 deletions GroundStation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ This Source Code Form is subject to the terms of the Mozilla Public
using System.Security;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;

namespace DaleGhent.NINA.GroundStation {

Expand All @@ -51,6 +52,9 @@ public GroundStation() {
MQTTTestCommand = new AsyncCommand<bool>(MQTTTest);
IFTTTTestCommand = new AsyncCommand<bool>(IFTTTTest);
TtsTestCommand = new AsyncCommand<bool>(TtsTest);

SelectDefaultSoundFileCommand = new RelayCommand(OpenSelectDefaultSoundFileDialog);
SelectDefaultFailureSoundFileCommand = new RelayCommand(OpenSelectDefaultFailureSoundFileDialog);
}

public override Task Initialize() {
Expand Down Expand Up @@ -618,6 +622,24 @@ public string TTSFailureMessage {
}
}

public string PlaySoundDefaultFile {
get => Properties.Settings.Default.PlaySoundDefaultFile;
set {
Properties.Settings.Default.PlaySoundDefaultFile = value;
CoreUtil.SaveSettings(Properties.Settings.Default);
RaisePropertyChanged();
}
}

public string PlaySoundDefaultFailureFile {
get => Properties.Settings.Default.PlaySoundDefaultFailureFile;
set {
Properties.Settings.Default.PlaySoundDefaultFailureFile = value;
CoreUtil.SaveSettings(Properties.Settings.Default);
RaisePropertyChanged();
}
}

public IList<string> QoSLevels => MqttCommon.QoSLevels;

public string TokenDate => DateTime.Now.ToString("d");
Expand Down Expand Up @@ -657,5 +679,30 @@ public static string GetVersion() {
protected void RaisePropertyChanged([CallerMemberName] string propertyName = null) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

internal void OpenSelectDefaultSoundFileDialog(object obj) {
Microsoft.Win32.OpenFileDialog dialog = new() {
FileName = string.Empty,
Filter = PlaySound.PlaySoundCommon.FileTypeFilter,
};

if (dialog.ShowDialog() == true) {
PlaySoundDefaultFile = dialog.FileName;
}
}

internal void OpenSelectDefaultFailureSoundFileDialog(object obj) {
Microsoft.Win32.OpenFileDialog dialog = new() {
FileName = string.Empty,
Filter = PlaySound.PlaySoundCommon.FileTypeFilter,
};

if (dialog.ShowDialog() == true) {
PlaySoundDefaultFailureFile = dialog.FileName;
}
}

public ICommand SelectDefaultSoundFileCommand { get; private set; }
public ICommand SelectDefaultFailureSoundFileCommand { get; private set; }
}
}
64 changes: 64 additions & 0 deletions Options.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,70 @@
</StackPanel>
</TabItem>

<TabItem Name="PlaySound" Header="Sounds">
<StackPanel Margin="0,10,0,0" Orientation="Vertical">
<StackPanel Margin="0,10,0,5" Orientation="Horizontal">
<TextBlock
Width="110"
HorizontalAlignment="Right"
VerticalAlignment="Center">
<TextBlock.Text>Default sound</TextBlock.Text>
</TextBlock>
<TextBox
MinWidth="300"
MaxWidth="500"
MaxHeight="150"
Margin="5,3,0,3"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"
TextAlignment="Left"
TextWrapping="Wrap"
Text="{Binding PlaySoundDefaultFile}" />

<Button
Width="25"
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Command="{Binding SelectDefaultSoundFileCommand}">
<Button.Content>
<TextBlock Foreground="{StaticResource ButtonForegroundBrush}" Text="..." />
</Button.Content>
</Button>
</StackPanel>

<StackPanel Margin="0,10,0,5" Orientation="Horizontal">
<TextBlock
Width="110"
HorizontalAlignment="Right"
VerticalAlignment="Center">
<TextBlock.Text>Default failure sound</TextBlock.Text>
</TextBlock>
<TextBox
MinWidth="300"
MaxWidth="500"
MaxHeight="150"
Margin="5,3,0,3"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"
TextAlignment="Left"
TextWrapping="Wrap"
Text="{Binding PlaySoundDefaultFailureFile}" />

<Button
Width="25"
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Command="{Binding SelectDefaultFailureSoundFileCommand}">
<Button.Content>
<TextBlock Foreground="{StaticResource ButtonForegroundBrush}" Text="..." />
</Button.Content>
</Button>
</StackPanel>
</StackPanel>
</TabItem>

<TabItem Name="Token_Help" Header="Message Token Help">
<StackPanel Margin="0,10,0,0" Orientation="Vertical">
<TextBlock
Expand Down
134 changes: 134 additions & 0 deletions PlaySound/PlaySound.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#region "copyright"

/*
Copyright Dale Ghent <[email protected]> and contributors
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/
*/

#endregion "copyright"

using NetCoreAudio;
using Newtonsoft.Json;
using NINA.Core.Model;
using NINA.Core.Utility;
using NINA.Sequencer.SequenceItem;
using NINA.Sequencer.Validations;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;

namespace DaleGhent.NINA.GroundStation.PlaySound {

[ExportMetadata("Name", "Play Sound")]
[ExportMetadata("Description", "Plays the specified audio file")]
[ExportMetadata("Icon", "PlaySoundSVG")]
[ExportMetadata("Category", "Ground Station")]
[Export(typeof(ISequenceItem))]
[JsonObject(MemberSerialization.OptIn)]
public class PlaySound : SequenceItem, IValidatable {
private string soundFile = string.Empty;
private bool waitUntilFinished = true;

[ImportingConstructor]
public PlaySound() {
SoundFile = Properties.Settings.Default.PlaySoundDefaultFile;
SelectSoundFileCommand = new RelayCommand(OpenSelectSoundFileDialog);

Validate();
}

public PlaySound(PlaySound copyMe) : this() {
CopyMetaData(copyMe);
}

public override object Clone() {
return new PlaySound(this) {
SoundFile = SoundFile,
WaitUntilFinished = WaitUntilFinished,
};
}

[JsonProperty]
public string SoundFile {
get => soundFile;
set {
soundFile = value;
Validate();
RaisePropertyChanged();
RaisePropertyChanged(nameof(SoundFileShort));
}
}

[JsonProperty]
public bool WaitUntilFinished {
get => waitUntilFinished;
set {
waitUntilFinished = value;
RaisePropertyChanged();
}
}

public string SoundFileShort => Path.GetFileName(soundFile);

public override async Task Execute(IProgress<ApplicationStatus> progress, CancellationToken ct) {
var player = new Player();

if (waitUntilFinished) {
await player.Play(soundFile);

do {
await Task.Delay(250, ct);
} while (player.Playing);
} else {
await player.Play(soundFile);
}

return;
}

public IList<string> Issues { get; set; } = new List<string>();

public bool Validate() {
var i = new List<string>();

if (string.IsNullOrEmpty(soundFile) || string.IsNullOrWhiteSpace(soundFile)) {
i.Add("Sound file has not been specified");
} else {
if (!File.Exists(soundFile)) {
i.Add("Sound file does not exist");
}
}

if (i != Issues) {
Issues = i;
RaisePropertyChanged(nameof(Issues));
}

return i.Count == 0;
}

public override string ToString() {
return $"Category: {Category}, Item: {nameof(PlaySound)}, SoundFile: {soundFile}, WaitUntilFinished: {WaitUntilFinished}";
}

internal void OpenSelectSoundFileDialog(object obj) {
Microsoft.Win32.OpenFileDialog dialog = new() {
FileName = string.Empty,
Filter = PlaySoundCommon.FileTypeFilter,
};

if (dialog.ShowDialog() == true) {
SoundFile = dialog.FileName;
}
}

public ICommand SelectSoundFileCommand { get; private set; }
}
}
25 changes: 25 additions & 0 deletions PlaySound/PlaySoundCommon.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#region "copyright"

/*
Copyright Dale Ghent <[email protected]>
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/
*/

#endregion "copyright"

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DaleGhent.NINA.GroundStation.PlaySound
{
public class PlaySoundCommon {

public static string FileTypeFilter = "Audio files|*.wav;*.aiff;*.aif;*.mp3|All files|*.*";
}
}
Loading

0 comments on commit 0708895

Please sign in to comment.