Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions TSOClient/FSO.Windows/FSO.Windows.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="MacTTSContext.cs" />
<Compile Include="UITTSContext.cs" />
<Compile Include="WinFormsClipboard.cs" />
<EmbeddedResource Include="Properties\Resources.resx">
Expand Down
69 changes: 69 additions & 0 deletions TSOClient/FSO.Windows/MacTTSContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using FSO.Client.UI.Panels;
using FSO.Common.Utils;
using Microsoft.Xna.Framework.Audio;
using System;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace FSO.Windows
{
public class MacTTSContext : ITTSContext
{
public static MacTTSContext PlatformProvider()
{
return new MacTTSContext();
}

public MacTTSContext()
{
}

public override void Dispose()
{
}

public override void Speak(string text, bool gender, int ipitch)
{
Task.Run(() =>
{
if (string.IsNullOrEmpty(text)) return;

// Remove double-quotes from text.
text = text.Replace("\"", string.Empty);
// Remove any 'say' command control sequences.
text = Regex.Replace(text, @"\[\[.*?\]\]", string.Empty);

// Determine the voice to use based on the gender.
// Samantha and Alex are available on most systems.
// If not available, it falls back to the default voice.
string voice = gender ? "Samantha" : "Alex";

// Convert pitch from 0-100 scale to 0-127 scale used by 'pbas' command.
// Note: negative values are clamped to 0 on macOS, it doesn't allow lower pitch than 0 (the default pitch).
int pbas = (int)(ipitch * 1.27);

// Construct the command to send to 'say'.
string command = $"[[pbas {pbas}]] {text}";

// Create a ProcessStartInfo to specify the 'say' command and arguments.
var psi = new ProcessStartInfo("say", $"-v {voice} \"{command}\"")
{
UseShellExecute = false,
CreateNoWindow = true
};

try
{
// Run the 'say' command.
Process.Start(psi);
}
catch (Exception ex)
{
// Handle exception silently to not disrupt the game if anything happens.
Console.WriteLine("Error running 'say' command: " + ex.Message);
}
});
}
}
}
36 changes: 34 additions & 2 deletions TSOClient/FSO.Windows/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using FSO.Client.UI.Panels;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Diagnostics;

namespace FSO.Windows
{
Expand Down Expand Up @@ -46,14 +47,45 @@ public static void InitWindows()

OperatingSystem os = Environment.OSVersion;
PlatformID pid = os.Platform;
bool linux = pid == PlatformID.MacOSX || pid == PlatformID.Unix;
if (!linux) ITTSContext.Provider = UITTSContext.PlatformProvider;

if (IsRunningOnMac())
{
ITTSContext.Provider = MacTTSContext.PlatformProvider;
}
else if (pid != PlatformID.Unix)
{
ITTSContext.Provider = UITTSContext.PlatformProvider;
}

AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
FSOProgram.ShowDialog = ShowDialog;

}

private static bool IsRunningOnMac()
{
// Check for Unix first because Mac is also Unix and would pass both checks
if (Environment.OSVersion.Platform != PlatformID.Unix) return false;

// Distinguish Linux from MacOS
return GetKernelName().ToLower() == "darwin";
}


private static string GetKernelName()
{
var startInfo = new ProcessStartInfo("uname", "-s")
{
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
};
using (var process = Process.Start(startInfo))
{
return process.StandardOutput.ReadLine().Trim();
}
}

public static void ShowDialog(string text)
{
OperatingSystem os = Environment.OSVersion;
Expand Down