Skip to content

Instantly share code, notes, and snippets.

@karno
Created April 1, 2011 10:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save karno/897975 to your computer and use it in GitHub Desktop.
Save karno/897975 to your computer and use it in GitHub Desktop.
Phonetics resolver
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Microsoft.VisualBasic;
using Std.Tweak;
namespace Athenaeum.Injection
{
public static class Kana
{
private static IMEPhoneticHelper phonetic = null;
// private static ImeLanguage phoneticService = null;
/// <summary>
/// Call from STA Thread!
/// </summary>
public static void Initialize()
{
phonetic = new IMEPhoneticHelper();
phonetic.ReadyPhoneticService();
Application.Current.Exit += (o, e) => phonetic.EndPhoneticService();
// phoneticService = new ImeLanguage();
// Application.Current.Exit += (o, e) => phoneticService.Dispose();
phonetic.EnqueueConvPhonetic("柏崎刈羽原発", s => System.Diagnostics.Debug.WriteLine(s));
}
public static void TranslateTweetToKana(TwitterStatusBase status, Action<TwitterStatusBase> callback)
{
// ツイートの正規化
var newtext = Strings.StrConv(status.Text, VbStrConv.Wide);
newtext = Strings.StrConv(status.Text, VbStrConv.Katakana);
// 読みを取得する
// newtext = phoneticService.GetYomi(newtext);
phonetic.EnqueueConvPhonetic(newtext, n =>
{
var convd = n;
// リプレーステーブルを再度通す
foreach (var rt in replaceTable)
convd = convd.Replace(rt.Item1, rt.Item2);
convd = Strings.StrConv(convd, VbStrConv.Katakana);
System.Diagnostics.Debug.WriteLine("CONVD:" + convd);
status.Text = convd;
callback(status);
});
}
public static Tuple<string, string>[] replaceTable = new Tuple<string, string>[]{
new Tuple<string, string>("GJ", "グッジョブ"),
new Tuple<string, string>("ktkr", "キタコレ"),
new Tuple<string, string>("wktk", "ワクテカ"),
new Tuple<string, string>("ry", "いかりゃく"),
new Tuple<string, string>("kwsk", "くわしく"),
new Tuple<string, string>("Twitter", "ついったー"),
new Tuple<string, string>("Wassr", "わっさー"),
new Tuple<string, string>("Krile", "くるる"),
new Tuple<string, string>("A", "えー"),
new Tuple<string, string>("B", "びー"),
new Tuple<string, string>("C", "しー"),
new Tuple<string, string>("D", "でぃー"),
new Tuple<string, string>("E", "いー"),
new Tuple<string, string>("F", "えふ"),
new Tuple<string, string>("G", "じー"),
new Tuple<string, string>("H", "えいち"),
new Tuple<string, string>("I", "あい"),
new Tuple<string, string>("J", "じぇい"),
new Tuple<string, string>("K", "けー"),
new Tuple<string, string>("L", "える"),
new Tuple<string, string>("M", "えむ"),
new Tuple<string, string>("N", "えぬ"),
new Tuple<string, string>("O", "おー"),
new Tuple<string, string>("P", "ぴー"),
new Tuple<string, string>("Q", "きゅー"),
new Tuple<string, string>("R", "あーる"),
new Tuple<string, string>("S", "えす"),
new Tuple<string, string>("T", "てぃー"),
new Tuple<string, string>("U", "ゆー"),
new Tuple<string, string>("V", "ぶい"),
new Tuple<string, string>("W", "だぶりゅ"),
new Tuple<string, string>("X", "えっくす"),
new Tuple<string, string>("Y", "わい"),
new Tuple<string, string>("Z", "ぜっと"),
new Tuple<string, string>("a", "えー"),
new Tuple<string, string>("b", "びー"),
new Tuple<string, string>("c", "しー"),
new Tuple<string, string>("d", "でぃー"),
new Tuple<string, string>("e", "いー"),
new Tuple<string, string>("f", "えふ"),
new Tuple<string, string>("g", "じー"),
new Tuple<string, string>("h", "えいち"),
new Tuple<string, string>("i", "あい"),
new Tuple<string, string>("j", "じぇい"),
new Tuple<string, string>("k", "けー"),
new Tuple<string, string>("l", "える"),
new Tuple<string, string>("m", "えむ"),
new Tuple<string, string>("n", "えぬ"),
new Tuple<string, string>("o", "おー"),
new Tuple<string, string>("p", "ぴー"),
new Tuple<string, string>("q", "きゅー"),
new Tuple<string, string>("r", "あーる"),
new Tuple<string, string>("s", "えす"),
new Tuple<string, string>("t", "てぃー"),
new Tuple<string, string>("u", "ゆー"),
new Tuple<string, string>("v", "ぶい"),
new Tuple<string, string>("w", "だぶりゅ"),
new Tuple<string, string>("x", "えっくす"),
new Tuple<string, string>("y", "わい"),
new Tuple<string, string>("z", "ぜっと"),
new Tuple<string, string>("@", "あっと"),
new Tuple<string, string>("#", "しゃーぷ"),
new Tuple<string, string>("+", "ぷらす"),
new Tuple<string, string>("-", "まいなす"),
new Tuple<string, string>("<", "だいなり"),
new Tuple<string, string>(">", "しょうなり"),
new Tuple<string, string>("!", "ー"),
new Tuple<string, string>(" ", "、"),
new Tuple<string, string>("ァ", "あー"),
new Tuple<string, string>("ィ", "いー"),
new Tuple<string, string>("ゥ", "うー"),
new Tuple<string, string>("ェ", "えー"),
new Tuple<string, string>("ォ", "おー"),
new Tuple<string, string>("ヮ", "わあ"),
new Tuple<string, string>("ヂ", "ジ"),
new Tuple<string, string>("ヅ", "ズ"),
new Tuple<string, string>("(", "、"),
new Tuple<string, string>(")", "、"),
new Tuple<string, string>("・", "、"),
new Tuple<string, string>("~", "ー"),
new Tuple<string, string>("/", "スラッシュ"),
new Tuple<string, string>("「", "、"),
new Tuple<string, string>("」", "、"),
new Tuple<string, string>("(", "、"),
new Tuple<string, string>(")", "、"),
new Tuple<string, string>("<", "、"),
new Tuple<string, string>(">", "、"),
new Tuple<string, string>("ヰ", "イ"),
};
}
public class IMEPhoneticHelper
{
private const int S_OK = 0;
private const int CLSCTX_LOCAL_SERVER = 4;
private const int CLSCTX_INPROC_SERVER = 1;
private const int CLSCTX_INPROC_HANDLER = 2;
private const int CLSCTX_SERVER = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER;
private const int FELANG_REQ_REV = 0x00030000;
private const int FELANG_CMODE_PINYIN = 0x00000100;
private const int FELANG_CMODE_NOINVISIBLECHAR = 0x40000000;
[DllImport("ole32.dll")]
private static extern int CLSIDFromString([MarshalAs(UnmanagedType.LPWStr)] string lpsz, out Guid pclsid);
[DllImport("ole32.dll")]
private static extern int CoCreateInstance([MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,
IntPtr pUnkOuter, uint dwClsContext, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr rpv);
public void ReadyPhoneticService()
{
phoneticServiceThread = new Thread(PhoneticEngine);
phoneticServiceThread.SetApartmentState(ApartmentState.STA);
phoneticServiceThread.Start();
}
public void EndPhoneticService()
{
enableEngine = false;
phoneticServiceThread.Abort();
queueWait.Set();
}
private Thread phoneticServiceThread = null;
private bool enableEngine = false;
private Queue<Tuple<string, Action<string>>> waitQueue = new Queue<Tuple<string, Action<string>>>();
IFELanguage ifeLang = null;
ManualResetEvent queueWait = new ManualResetEvent(false);
private void PhoneticEngine()
{
try
{
enableEngine = true;
int res;
Guid pclsid;
IntPtr ppv;
// 文字列の CLSID から CLSID へのポインタを取得する
res = CLSIDFromString("MSIME.Japan", out pclsid);
if (res != S_OK)
throw new Exception("CLSID pointer translation failed.");
Guid riid = new Guid("019F7152-E6DB-11D0-83C3-00C04FDDB82E");
res = CoCreateInstance(pclsid, IntPtr.Zero, CLSCTX_SERVER, riid, out ppv);
if (res != S_OK)
throw new Exception("Instance create failed. :" + res.ToString("X"));
ifeLang = Marshal.GetTypedObjectForIUnknown(ppv, typeof(IFELanguage)) as IFELanguage;
res = ifeLang.Open();
if (res != S_OK)
throw new Exception("Language interface open failed.");
while (enableEngine)
{
queueWait.Reset();
while (waitQueue.Count > 0)
{
queueWait.Reset();
IntPtr result;
int cres;
var cq = waitQueue.Dequeue();
cres = ifeLang.GetJMorphResult(FELANG_REQ_REV, FELANG_CMODE_PINYIN | FELANG_CMODE_NOINVISIBLECHAR,
cq.Item1.Length, cq.Item1, IntPtr.Zero, out result);
if (cres != S_OK)
throw new Exception("Convert error.");
var convd = Marshal.PtrToStringUni(Marshal.ReadIntPtr(result, 4), Marshal.ReadInt16(result, 8));
Task.Factory.StartNew(() => cq.Item2(convd), TaskCreationOptions.LongRunning);
}
queueWait.WaitOne();
}
if (ifeLang == null) return;
}
finally
{
if (ifeLang != null)
{
ifeLang.Close();
ifeLang = null;
}
}
}
public void EnqueueConvPhonetic(string str, Action<string> callback)
{
waitQueue.Enqueue(new Tuple<string, Action<string>>(str, callback));
queueWait.Set();
}
}
//**************************************************************************************
// IFELanguage Interface(メソッドの実装はランタイムの中にあるので、実装は不要)
//**************************************************************************************
[ComImport, Guid("019F7152-E6DB-11D0-83C3-00C04FDDB82E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IFELanguage
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
int Open();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
int Close();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
int GetJMorphResult(uint dwRequest, uint dwCMode, int cwchInput,
[MarshalAs(UnmanagedType.LPWStr)] string pwchInput, IntPtr pfCInfo, out IntPtr ppResult);
} // end of IFELanguage Interface}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment