Created
April 1, 2011 10:18
-
-
Save karno/897975 to your computer and use it in GitHub Desktop.
Phonetics resolver
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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