ぴこぴこすぴーち!!

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" ] ) #print( text ) 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":"こんにちは"})