-
-
Notifications
You must be signed in to change notification settings - Fork 307
Add TTS #647
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add TTS #647
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
|
|
||
| namespace Text_Grab.Interfaces; | ||
|
|
||
| public interface ITtsEngine | ||
| { | ||
| Task SpeakAsync(string text, CancellationToken ct); | ||
| } |
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There should be a radio group with the notifications to be After grab always:
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| <Page | ||
| x:Class="Text_Grab.Pages.VoiceOutputSettings" | ||
| xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
| xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
| xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | ||
| xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||
| xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml" | ||
| Title="VoiceOutputSettings" | ||
| d:DesignHeight="700" | ||
| d:DesignWidth="800" | ||
| Loaded="Page_Loaded" | ||
| mc:Ignorable="d"> | ||
|
|
||
| <ScrollViewer VerticalScrollBarVisibility="Visible"> | ||
| <StackPanel Margin="20,12,40,40" Orientation="Vertical"> | ||
| <TextBlock Style="{StaticResource TextHeader}" Text="Voice Output Settings" /> | ||
|
|
||
| <!-- Speak instead of notification --> | ||
| <TextBlock | ||
| Margin="0,16,0,4" | ||
| FontSize="16" | ||
| Style="{StaticResource TextHeader}" | ||
| Text="Notification Behaviour" /> | ||
| <ui:ToggleSwitch | ||
| x:Name="SpeakInsteadOfToastToggle" | ||
| Checked="SpeakInsteadOfToastToggle_Checked" | ||
| Unchecked="SpeakInsteadOfToastToggle_Checked"> | ||
| <TextBlock Style="{StaticResource TextBodyNormal}"> | ||
| Speak text instead of showing notification | ||
| </TextBlock> | ||
| </ui:ToggleSwitch> | ||
| <TextBlock Margin="0,4,0,0" Style="{StaticResource TextBodyNormal}"> | ||
| Speaks the grabbed text aloud rather than showing a notification. | ||
| </TextBlock> | ||
|
Comment on lines
+24
to
+34
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When this is enabled AND the Post grab 'speak' option is enabled the text is spoken twice. |
||
|
|
||
| <!-- Voice selection --> | ||
| <TextBlock | ||
| Margin="0,16,0,4" | ||
| FontSize="16" | ||
| Style="{StaticResource TextHeader}" | ||
| Text="Voice" /> | ||
| <TextBlock Margin="0,0,0,6" Style="{StaticResource TextBodyNormal}"> | ||
| Choose from the voices installed on this device. | ||
| </TextBlock> | ||
| <ComboBox | ||
| x:Name="VoiceComboBox" | ||
| Width="320" | ||
| HorizontalAlignment="Left" | ||
| SelectionChanged="VoiceComboBox_SelectionChanged" /> | ||
|
|
||
| <!-- Word limit --> | ||
| <TextBlock | ||
| Margin="0,16,0,4" | ||
| FontSize="16" | ||
| Style="{StaticResource TextHeader}" | ||
| Text="Word Limit" /> | ||
| <TextBlock Margin="0,0,0,6" Style="{StaticResource TextBodyNormal}"> | ||
| Stop speaking after this many words. Set to 0 for no limit. | ||
| </TextBlock> | ||
| <StackPanel Orientation="Horizontal"> | ||
| <TextBlock | ||
| VerticalAlignment="Center" | ||
| Style="{StaticResource TextBodyNormal}" | ||
| Text="Speak word limit:" /> | ||
| <TextBox | ||
| x:Name="TtsSpeakWordLimitTextBox" | ||
| Width="60" | ||
| Height="26" | ||
| Margin="8,0,0,0" | ||
| HorizontalContentAlignment="Center" | ||
| VerticalContentAlignment="Center" | ||
| Background="White" | ||
| FontWeight="Medium" | ||
| Foreground="Black" | ||
| Style="{StaticResource TextBoxStyle1}" | ||
| TextChanged="TtsSpeakWordLimitTextBox_TextChanged" /> | ||
| <TextBlock | ||
| x:Name="TtsWordLimitError" | ||
| Margin="12,0,0,0" | ||
| VerticalAlignment="Center" | ||
| Style="{StaticResource TextBodyNormal}" | ||
| Text="⚠ Must be a positive number" | ||
| Visibility="Collapsed" /> | ||
| </StackPanel> | ||
|
|
||
| <!-- Preview --> | ||
| <TextBlock | ||
| Margin="0,16,0,4" | ||
| FontSize="16" | ||
| Style="{StaticResource TextHeader}" | ||
| Text="Preview" /> | ||
| <Button | ||
| x:Name="PreviewVoiceButton" | ||
| HorizontalAlignment="Left" | ||
| Click="PreviewVoiceButton_Click" | ||
| Content="Speak sample" /> | ||
|
|
||
| </StackPanel> | ||
| </ScrollViewer> | ||
| </Page> | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems good for an MVP of this feature. The only thing I think might be nice is adding a way to set |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| using System.Linq; | ||
| using System.Windows; | ||
| using System.Windows.Controls; | ||
| using Text_Grab.Properties; | ||
| using Text_Grab.Services; | ||
| using Text_Grab.Utilities; | ||
| using Windows.Media.SpeechSynthesis; | ||
|
|
||
| namespace Text_Grab.Pages; | ||
|
|
||
| public partial class VoiceOutputSettings : Page | ||
| { | ||
| private readonly Settings DefaultSettings = AppUtilities.TextGrabSettings; | ||
| private bool _loaded = false; | ||
|
|
||
| public VoiceOutputSettings() | ||
| { | ||
| InitializeComponent(); | ||
| } | ||
|
|
||
| private void Page_Loaded(object sender, RoutedEventArgs e) | ||
| { | ||
| SpeakInsteadOfToastToggle.IsChecked = DefaultSettings.SpeakInsteadOfToast; | ||
|
|
||
| VoiceComboBox.Items.Clear(); | ||
| foreach (VoiceInformation voice in SpeechSynthesizer.AllVoices.OrderBy(v => v.DisplayName)) | ||
| VoiceComboBox.Items.Add(voice.DisplayName); | ||
|
|
||
| string savedVoice = DefaultSettings.TtsVoiceName; | ||
| if (!string.IsNullOrEmpty(savedVoice) && VoiceComboBox.Items.Contains(savedVoice)) | ||
| VoiceComboBox.SelectedItem = savedVoice; | ||
| else | ||
| VoiceComboBox.SelectedIndex = 0; | ||
|
|
||
| TtsSpeakWordLimitTextBox.Text = DefaultSettings.TtsSpeakWordLimit.ToString(); | ||
|
|
||
| _loaded = true; | ||
| } | ||
|
|
||
| private void SpeakInsteadOfToastToggle_Checked(object sender, RoutedEventArgs e) | ||
| { | ||
| if (!_loaded) | ||
| return; | ||
|
|
||
| DefaultSettings.SpeakInsteadOfToast = SpeakInsteadOfToastToggle.IsChecked is true; | ||
| DefaultSettings.Save(); | ||
| } | ||
|
|
||
| private void VoiceComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) | ||
| { | ||
| if (!_loaded) | ||
| return; | ||
|
|
||
| if (VoiceComboBox.SelectedItem is string voiceName) | ||
| { | ||
| DefaultSettings.TtsVoiceName = voiceName; | ||
| DefaultSettings.Save(); | ||
| } | ||
| } | ||
|
|
||
| private void TtsSpeakWordLimitTextBox_TextChanged(object sender, TextChangedEventArgs e) | ||
| { | ||
| if (!_loaded) | ||
| return; | ||
|
|
||
| if (int.TryParse(TtsSpeakWordLimitTextBox.Text, out int parsedValue) && parsedValue > 0) | ||
| { | ||
| DefaultSettings.TtsSpeakWordLimit = parsedValue; | ||
| DefaultSettings.Save(); | ||
| TtsWordLimitError.Visibility = Visibility.Collapsed; | ||
| } | ||
| else | ||
| { | ||
| TtsWordLimitError.Visibility = Visibility.Visible; | ||
| } | ||
| } | ||
|
|
||
| private void PreviewVoiceButton_Click(object sender, RoutedEventArgs e) | ||
| { | ||
| Singleton<TtsService>.Instance.Speak("Hello, this is a preview of the selected voice."); | ||
| } | ||
| } |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,9 @@ | |
| <Setting Name="ShowToast" Type="System.Boolean" Scope="User"> | ||
| <Value Profile="(Default)">True</Value> | ||
| </Setting> | ||
| <Setting Name="SpeakInsteadOfToast" Type="System.Boolean" Scope="User"> | ||
| <Value Profile="(Default)">True</Value> | ||
| </Setting> | ||
| <Setting Name="DefaultLaunch" Type="System.String" Scope="User"> | ||
| <Value Profile="(Default)">Fullscreen</Value> | ||
| </Setting> | ||
|
|
@@ -57,7 +60,7 @@ | |
| <Value Profile="(Default)">False</Value> | ||
| </Setting> | ||
| <Setting Name="FSGMakeSingleLineToggle" Type="System.Boolean" Scope="User"> | ||
| <Value Profile="(Default)">False</Value> | ||
| <Value Profile="(Default)">True</Value> | ||
|
Comment on lines
-60
to
+63
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. undo this change, keep the default option for Make single line as |
||
| </Setting> | ||
| <Setting Name="GlobalHotkeysEnabled" Type="System.Boolean" Scope="User"> | ||
| <Value Profile="(Default)">True</Value> | ||
|
|
@@ -236,5 +239,11 @@ | |
| <Setting Name="RegisterOpenWith" Type="System.Boolean" Scope="User"> | ||
| <Value Profile="(Default)">False</Value> | ||
| </Setting> | ||
| <Setting Name="TtsSpeakWordLimit" Type="System.Int32" Scope="User"> | ||
| <Value Profile="(Default)">100</Value> | ||
| </Setting> | ||
| <Setting Name="TtsVoiceName" Type="System.String" Scope="User"> | ||
| <Value Profile="(Default)" /> | ||
| </Setting> | ||
| </Settings> | ||
| </SettingsFile> | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine for this implementation but makes me think there needs to be a more central service for handling 'text action' like copy/speak/etc.
We don't need to solve now just a thought