イベントハンドリング
http://d.hatena.ne.jp/yach/20070905 の続き。
チャットメッセージの受信とかは、イベントで処理する。イベントは、_ISkypeEvents (https://developer.skype.com/Docs/Skype4COMLib/ISkypeEvents) で定義されている。
win32com でCOMイベントを扱うには、以下のように書く。2パターンあり。
方法1 (DispatchWithEvents)
import sys import win32com.client from time import sleep class SkypeEvents: def OnMessageStatus(self, msg, stat): msg = win32com.client.Dispatch(msg) print "[%s(%s)] %s: %s"%( conversion.ChatMessageStatusToText(stat), str(stat), msg.FromDisplayName, msg.Body) sys.stdout.flush() skype = win32com.client.DispatchWithEvents('Skype4COM.Skype', SkypeEvents) conversion = skype.Convert skype.Attach() while True: skype.CurrentUser sleep(1)
方法2 (getevents)
import sys import win32com.client from time import sleep class SkypeEvents(win32com.client.getevents('Skype4COM.Skype')): def OnMessageStatus(self, msg, stat): msg = win32com.client.Dispatch(msg) print "[%s(%s)] %s: %s"%( conversion.ChatMessageStatusToText(stat), str(stat), msg.FromDisplayName, msg.Body) sys.stdout.flush() skype = win32com.client.Dispatch('Skype4COM.Skype') conversion = skype.Convert handler = SkypeEvents(skype) skype.Attach() while True: skype.CurrentUser sleep(1)
1番目の方法はシンプル。DispatchWithEvent()で得られるオブジェクトは、SkypeオブジェクトとSkypeEventsオブジェクトの両方のメソッドを併せ持つようになる(ただしSkypeEventsのオブジェクトではないので注意)。
2番目の方法は、ちょっと面倒だが、後からハンドラを自由に定義できる。また、 handler は SkypeEvents のオブジェクトなので、取り扱いが便利かもしれない。
ポイント:
- イベントに対するイベントハンドラは「On〜」
- パラメータのうち、[in]はイベントハンドラのパラメータに、[out]は戻り値になる。
- イベントは非同期に発生するのだが(当然)、イベントハンドラが呼び出されるためには、「skype.CurrentUser」の行が必要。おそらくメッセージループを回すのに必要なのではないか。
- パラメータで受け取ったオブジェクトは、IPyDispatch。これは、win32com.client.Dispatch()に渡してやらないと、オブジェクトとして呼び出せない。
- たぶんシングルスレッドモデルで動作する。マルチスレッド化するには?
- statusの類を文字列化するには、Skype.Convertを使う。
2番目の方法でイベントハンドラを追加するには:
class SkypeEvents(win32com.client.getevents('Skype4COM.Skype')): def OnMessageStatus(self, msg, stat): msg = win32com.client.Dispatch(msg) print "[%s(%s)] %s: %s"%( conversion.ChatMessageStatusToText(stat), str(stat), msg.FromDisplayName, msg.Body) sys.stdout.flush() skype = win32com.client.Dispatch('Skype4COM.Skype') handler = SkypeEvents(skype) class SkypeEvents2(win32com.client.getevents('Skype4COM.Skype')): def OnUserStatus(self,name): print "Event: UserStatus:" + str(name) sys.stdout.flush() handler2 = SkypeEvents2(skype)