#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include <windows.h>
#include <stdlib.h>
HWND g_hWndSkype; // window handle received in SkypeControlAPIAttach message
HWND g_hWndClient; // our window handle
int g_nAvailable = 0; // set by not-available msg from skype
bool is_quit = FALSE;
UINT SkypeControlAPIDiscover;
UINT SkypeControlAPIAttach;
enum {
SKYPECONTROLAPI_ATTACH_SUCCESS=0,
SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION,
SKYPECONTROLAPI_ATTACH_REFUSED,
SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE,
SKYPECONTROLAPI_ATTACH_API_AVAILABLE= 0x8001,
};
static SV* callback_copydata;
void HandleSkypeMessage(HWND hWndSkype, COPYDATASTRUCT* cds)
{
printf("[msg]%s\n", (char*)cds->lpData);
if (callback_copydata != NULL){
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpv((char*)cds->lpData, 0)));
//XPUSHs(sv_2mortal(newSViv(hWndSkype)));
PUTBACK;
call_sv(callback_copydata, G_DISCARD);
FREETMPS;
LEAVE;
}
}
BOOL SkypeRegisterMessages()
{
SkypeControlAPIDiscover =RegisterWindowMessage("SkypeControlAPIDiscover");
if (SkypeControlAPIDiscover==0) {
printf("[win]RegisterWindowMessage error\n");
return FALSE;
}
printf("[win]SkypeControlAPIDiscover=%04x\n", SkypeControlAPIDiscover);
SkypeControlAPIAttach =RegisterWindowMessage("SkypeControlAPIAttach");
if (SkypeControlAPIAttach==0) {
printf("[win]RegisterWindowMessage error\n");
return FALSE;
}
printf("[win]SkypeControlAPIAttach=%04x\n", SkypeControlAPIAttach);
return TRUE;
}
// initiate connnection with skype.
BOOL SkypeDiscover(HWND hWnd)
{
LRESULT res;
if (g_nAvailable == -1)
return FALSE;
g_hWndSkype= NULL;
res= SendMessage(HWND_BROADCAST, SkypeControlAPIDiscover, (WPARAM)hWnd, 0);
printf("[win]discover result=%08lx\n", res);
return TRUE;
}
void HandleSkypeAttach(LPARAM lParam, WPARAM wParam)
{
switch(lParam) {
case SKYPECONTROLAPI_ATTACH_SUCCESS:
g_hWndSkype= (HWND)wParam;
printf("[win]success: skypewnd= %08lx\n", g_hWndSkype);
g_nAvailable= 1;
break;
case SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION:
printf("[win]pending authorization\n");
break;
case SKYPECONTROLAPI_ATTACH_REFUSED:
printf("[win]attach refused\n");
g_hWndSkype= NULL;
g_nAvailable= -1;
break;
case SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE:
printf("[win]skype api not available\n");
g_nAvailable= -1;
break;
case SKYPECONTROLAPI_ATTACH_API_AVAILABLE:
printf("[win]skype api available\n");
g_nAvailable= 1;
SkypeDiscover(g_hWndClient);
break;
default:
printf("[win]UNKNOWN SKYPEMSG %08lx: %08lx\n", lParam, wParam);
}
}
LRESULT CALLBACK MySkypeWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg==WM_CREATE) {
if (!SkypeRegisterMessages()) {
return -1;
}
if (!SkypeDiscover(hWnd)) {
return -1;
}
return 0;
}
else if (uMsg==WM_DESTROY) {
return 0;
}
else if (uMsg==SkypeControlAPIAttach) {
HandleSkypeAttach(lParam, wParam);
return 0;
}
else if (uMsg==SkypeControlAPIDiscover) {
HWND hWndOther= (HWND)wParam;
if (hWndOther!=hWnd)
printf( "[win]detected other skype api client: %08lx\n", hWndOther);
return 0;
}
else if (uMsg==WM_COPYDATA && (HWND)wParam == g_hWndSkype) {
HandleSkypeMessage((HWND)wParam, (COPYDATASTRUCT*)lParam);
return TRUE;
}
else {
printf( "[win]wnd %08lx msg %08lx %08lx %08lx\n", hWnd, uMsg ,wParam, lParam);
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
HWND MakeWindow() {
WNDCLASS wndcls;
HWND hWnd;
ATOM a;
memset(&wndcls, 0, sizeof(WNDCLASS)); // start with NULL
wndcls.style = 0;
wndcls.lpfnWndProc = MySkypeWindowProc;
wndcls.hInstance = GetModuleHandle(NULL);
wndcls.lpszClassName = "perl skype window";
a = RegisterClass(&wndcls);
if (a==0) {
printf("[win]register class failed\n");
return 0;
}
hWnd= CreateWindowEx(WS_EX_CLIENTEDGE, wndcls.lpszClassName, "perl skype window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, (HWND)NULL, (HMENU)NULL, (HINSTANCE)GetModuleHandle(NULL), NULL);
if (hWnd==NULL) {
printf("[win]create windowfailed\n");
return 0;
}
return hWnd;
}
void UnmakeWindow(HWND hWnd)
{
if (!DestroyWindow(hWnd))
printf("DestroyWindow\n");
if (!UnregisterClass("perl skype window", NULL))
printf("UnregisterClass\n");
}
// sends skype api message to skype
bool SkypeSendMessage(char *msg)
{
COPYDATASTRUCT cds;
cds.dwData= 0;
cds.lpData= msg;
cds.cbData= strlen(msg)+1;
if (!SendMessage(g_hWndSkype, WM_COPYDATA, (WPARAM)g_hWndClient, (LPARAM)&cds)) {
printf("[send]skypesendmessage failed\n");
SkypeDiscover(g_hWndClient);
return FALSE;
}
return TRUE;
}
void attach_skype() {
BOOL bRet;
MSG msg;
g_hWndClient= MakeWindow();
do
{
if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
if (is_quit) {
break;
}
Sleep(1000);
} while (msg.message != WM_QUIT);
UnmakeWindow(g_hWndClient);
}
MODULE = SkypeAPI::Win PACKAGE = SkypeAPI::Win
void
attach(SV* self, SV* option)
INIT:
HV* hvoption;
if (!SvROK(option) || SvTYPE(SvRV(option)) != SVt_PVHV) {
printf("[win]option must be a hashref\n");
XSRETURN_UNDEF;
}
hvoption = (HV *)SvRV(option);
CODE:
if (hv_exists(hvoption, "copy_data", 9)) {
SV** refval = hv_fetch(hvoption, "copy_data",9, NULL);
if (refval != NULL) {
callback_copydata = (SV*)SvRV((*refval));
}
}
attach_skype();
int
is_available(SV* self)
CODE:
RETVAL=g_nAvailable;
OUTPUT:
RETVAL
bool
send_message(SV* self, char* msg)
CODE:
bool result = SkypeSendMessage(msg);
RETVAL= result;
OUTPUT:
RETVAL
void
quit(SV* self)
CODE:
is_quit = TRUE;
printf("[api]some one call me quit\n");
SendMessage(g_hWndClient, WM_QUIT, 0, 0);