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)