ぴこぴこすぴーち!!
Python3でUIAutomationをつかってVoiceroid2を制御する
VoiceroidEditor
import os
import sys
import time
import traceback
import comtypes
import comtypes.client
if not hasattr( sys, "_MEIPASS" ):
comtypes.client.GetModule( 'UIAutomationCore.dll' )
import comtypes.gen.UIAutomationClient as UIA
class UIACtl:
def __init__( self ):
comtypes.CoInitialize()
self.uia = comtypes.CoCreateInstance( UIA.CUIAutomation._reg_clsid_,
interface = UIA.IUIAutomation,
clsctx = comtypes.CLSCTX_INPROC_SERVER )
self.root = self.uia.GetRootElement()
def getWindowElement( self, title ):
return self.root.FindFirst( UIA.TreeScope_Children,
self.uia.CreatePropertyCondition( UIA.UIA_NamePropertyId, title ) )
def findControl( self, element, ctl_type ):
cond = self.uia.CreatePropertyCondition( UIA.UIA_ControlTypePropertyId, ctl_type )
ctl_elements = element.FindAll( UIA.TreeScope_Subtree, cond )
return [ ctl_elements.GetElement( i ) for i in range( ctl_elements.Length ) ]
def action( self, element ):
ptn = element.GetCurrentPattern( UIA.UIA_LegacyIAccessiblePatternId )
ptn.QueryInterface( UIA.IUIAutomationLegacyIAccessiblePattern ).DoDefaultAction()
def setValue( self, element, value ):
ptn = element.GetCurrentPattern( UIA.UIA_LegacyIAccessiblePatternId )
ptn.QueryInterface( UIA.IUIAutomationLegacyIAccessiblePattern ).setValue( value )
def state( self, element ):
ptn = element.GetCurrentPattern( UIA.UIA_LegacyIAccessiblePatternId )
return ptn.QueryInterface( UIA.IUIAutomationLegacyIAccessiblePattern ).CurrentState
class VoiceroidEditor:
def __init__( self ):
self.uia = None
self.win = None
self.btn_play = None
self.btn_stop = None
self.btn_save = None
self.edit_main = None
def open( self ):
try:
if self.uia == None:
self.uia = UIACtl()
self.win = self.uia.getWindowElement( 'VOICEROID2' )
if not self.win:
self.win = self.uia.getWindowElement( 'VOICEROID2*' )
except:
pass
if not self.win:
print( "Voiceroid2 open failed!!" )
self.win = None
return False
btns = self.uia.findControl( self.win, UIA.UIA_ButtonControlTypeId )
for b in btns:
texts = self.uia.findControl( b, UIA.UIA_TextControlTypeId )
for t in texts:
if t.CurrentName == "再生":
self.btn_play = b
if t.CurrentName == "停止":
self.btn_stop = b
if t.CurrentName == "音声保存":
self.btn_save = b
edits = self.uia.findControl( self.win, UIA.UIA_EditControlTypeId )
self.edit_main = edits[ 0 ]
self.images = self.uia.findControl( self.btn_play, UIA.UIA_ImageControlTypeId )
return True
def close( self ):
pass
def send( self, msg ):
if self.win == None:
if not self.open():
time.sleep( 1.0/6.0 * len( msg[ "msg" ] ) )
return
try:
text = '%s>%s' % ( msg[ "title" ], msg[ "msg" ] )
time.sleep( 0.1 )
while True:
if self.uia.state( self.images[ 0 ] ) == 0:
time.sleep( 0.1 )
if ( self.uia.state( self.edit_main ) & 0x40 ) != 0:
self.uia.action( self.btn_play )
time.sleep( 0.1 )
self.uia.action( self.btn_stop )
break
time.sleep( 0.1 )
time.sleep( 0.1 )
self.uia.setValue( self.edit_main, text )
self.uia.action( self.btn_play )
while True:
time.sleep( 0.1 )
if self.uia.state( self.images[ 0 ] ) == 0:
break
except Exception as e:
print( traceback.format_exc() )
self.win = None
if __name__ == "__main__":
v = VoiceroidEditor()
v.open()
v.send({"title":"病ンデる琴葉茜","msg":"こんにちは"})