Skip to content

Commit

Permalink
TcpServer を実装した
Browse files Browse the repository at this point in the history
  • Loading branch information
anoyetta committed Apr 28, 2021
1 parent 30f178e commit 7e4d376
Show file tree
Hide file tree
Showing 6 changed files with 225 additions and 3 deletions.
31 changes: 30 additions & 1 deletion source/CeVIOAIProxy/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Threading;
using CeVIOAIProxy.Servers;

namespace CeVIOAIProxy
{
Expand All @@ -13,6 +15,8 @@ namespace CeVIOAIProxy
/// </summary>
public partial class App : Application
{
private CAPTcpServer server;

public App()
{
this.ShutdownMode = ShutdownMode.OnMainWindowClose;
Expand All @@ -23,16 +27,37 @@ public App()
this.DispatcherUnhandledException += this.App_DispatcherUnhandledException;
}

private void App_Startup(object sender, StartupEventArgs e)
private async void App_Startup(object sender, StartupEventArgs e)
{
var c = Config.Instance;
c.SetStartup(c.IsStartupWithWindows);

await Task.Run(() =>
{
this.server = new CAPTcpServer();
this.server.Open(c.TcpServerPort);
});
}

private void App_Exit(object sender, ExitEventArgs e)
{
this.CloseServer();

CeVIOAIProxy.MainWindow.Instance?.HideNotifyIcon();
Config.Instance.Save();

GC.SuppressFinalize(this);
}

private async void CloseServer()
{
if (this.server != null)
{
this.server.Close();
this.server.Dispose();
await Task.Delay(TimeSpan.FromMilliseconds(100));
this.server = null;
}
}

private async void App_DispatcherUnhandledException(
Expand All @@ -54,9 +79,13 @@ await Task.Run(() =>
MessageBoxButton.OK,
MessageBoxImage.Error);

this.CloseServer();

CeVIOAIProxy.MainWindow.Instance?.HideNotifyIcon();
Config.Instance.Save();

GC.SuppressFinalize(this);

this.Shutdown(1);
}
}
Expand Down
2 changes: 2 additions & 0 deletions source/CeVIOAIProxy/CeVIOAIProxy.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
<PackageReference Include="Hardcodet.Wpf.TaskbarNotification" Version="1.0.5" />
<PackageReference Include="Hjson" Version="3.0.0" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.31" />
<PackageReference Include="Nancy" Version="2.0.0" />
<PackageReference Include="Nancy.Hosting.Self" Version="2.0.0" />
<PackageReference Include="NETStandard.Library" Version="2.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Prism.Core" Version="8.0.0.1909" />
Expand Down
2 changes: 2 additions & 0 deletions source/CeVIOAIProxy/Config.DefaultValues.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ namespace CeVIOAIProxy
public partial class Config : JsonConfigBase
{
public static readonly uint CeVIOBasicParameterDefaultValue = 50;
public static readonly int TcpServerPortDefaultValue = 50001;

public override Dictionary<string, object> DefaultValues => new Dictionary<string, object>()
{
{ nameof(IsStartupWithWindows), false },
{ nameof(IsMinimizeStartup), false },
{ nameof(TcpServerPort), TcpServerPortDefaultValue },

{ nameof(Volume), CeVIOBasicParameterDefaultValue },
{ nameof(Speed), CeVIOBasicParameterDefaultValue },
Expand Down
9 changes: 9 additions & 0 deletions source/CeVIOAIProxy/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ public bool IsMinimizeStartup
set => this.SetProperty(ref this.isMinimizeStartup, value);
}

private int tcpServerPort = TcpServerPortDefaultValue;

[JsonProperty(PropertyName = "tcp_server_port")]
public int TcpServerPort
{
get => this.tcpServerPort;
set => this.SetProperty(ref this.tcpServerPort, value);
}

private string cast;

[JsonProperty(PropertyName = "cast")]
Expand Down
6 changes: 4 additions & 2 deletions source/CeVIOAIProxy/FodyWeavers.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<Weavers
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<Costura />
</Weavers>
</Weavers>
178 changes: 178 additions & 0 deletions source/CeVIOAIProxy/Servers/CAPTcpServer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace CeVIOAIProxy.Servers
{
public class CAPTcpServer : IDisposable
{
public CAPTcpServer()
{
}

private TcpListener listener;

public void Dispose()
{
GC.SuppressFinalize(this);
this.Dispose(disposing: true);
}

protected virtual void Dispose(bool disposing) => this.Close();

~CAPTcpServer() => this.Dispose(disposing: false);

public void Open(
int port)
{
this.isClosing = false;

this.listener = new TcpListener(IPAddress.Any, port);

/*
this.listener.Server.SetSocketOption(
SocketOptionLevel.Socket,
SocketOptionName.ReuseAddress,
true);
*/

this.listener.Start();
this.listener.BeginAcceptTcpClient(AcceptTcpClientCallback, null);
}

public void Close()
{
if (this.listener != null)
{
this.isClosing = true;
this.listener.Server.Close();
this.listener.Stop();
this.listener = null;
}
}

private volatile bool isClosing;

private void AcceptTcpClientCallback(IAsyncResult ar)
{
if (this.listener == null || this.isClosing)
{
return;
}

try
{
using (var tcpClient = this.listener.EndAcceptTcpClient(ar))
using (var s = tcpClient.GetStream())
using (var br = new BinaryReader(s))
{
this.ProcessStream(s, br);
}
}
finally
{
this.listener.BeginAcceptTcpClient(AcceptTcpClientCallback, null);
}
}

private async void ProcessStream(
NetworkStream stream,
BinaryReader br)
{
var opcode = br.ReadInt16();

var speed = default(short);
var tone = default(short);
var volume = default(short);
var type = default(short);
var encode = default(byte);
var count = default(int);
var chars = default(byte[]);
var text = string.Empty;

switch (opcode)
{
case 0:
speed = br.ReadInt16();
volume = br.ReadInt16();
type = br.ReadInt16();
encode = br.ReadByte();
count = br.ReadInt32();
chars = br.ReadBytes(count);

text = encode switch
{
0 => Encoding.UTF8.GetString(chars),
1 => Encoding.Unicode.GetString(chars),
2 => Encoding.GetEncoding("Shift_JIS").GetString(chars),
_ => Encoding.UTF8.GetString(chars),
};

await CeVIO.SpeakAsync(text);
break;

case 1:
speed = br.ReadInt16();
tone = br.ReadInt16();
volume = br.ReadInt16();
type = br.ReadInt16();
encode = br.ReadByte();
count = br.ReadInt32();
chars = br.ReadBytes(count);

text = encode switch
{
0 => Encoding.UTF8.GetString(chars),
1 => Encoding.Unicode.GetString(chars),
2 => Encoding.GetEncoding("Shift_JIS").GetString(chars),
_ => Encoding.UTF8.GetString(chars),
};

await CeVIO.SpeakAsync(text);
break;

case 16:
// ポーズ
// 未実装
break;

case 32:
// ポーズ解除
// 未実装
break;

case 48:
// 次のキューへ
// 未実装
break;

case 64:
// キューをクリアする
// 未実装
break;

case 272:
// ポーズ中か返す
// 未実装
break;

case 288:
// 再生中か返す
// 未実装
break;

case 304:
// 現在のキュー数を返す
// 未実装
break;

case 12078:
// コマンドを実行する
// 未実装
break;
}
}
}
}

0 comments on commit 7e4d376

Please sign in to comment.