KbMediaPlayerとSkypeを通信させるプログラム

・KbMediaPlayerで演奏している音楽を取得してSkypeのムードメッセージへ転送するプログラムです。
・このサンプル公開は自分の技術的好奇心、バックアップと他者の開発支援を主に目的としています。
・バックアップ目的の為、設定データなどが存在しない場合など、正常に動作しない場合があります。
・その結果起こった事故、損失などについて作者は責任を追わないものとします ・動作保証はありません
・またこの技術を悪用した悪戯プログラムの作成の一切を禁止します。
・ソースのコピーはサンプル上部のエディタ表示から行って下さい。
・以上のことを理解した上で使用してください。



Script : kbskype0.03b.hsp

// コンパイル時に、メインウィンドゥを非表示にしてください。
// コンパイル時に、メインウィンドゥを非表示にしてください。
// コンパイル時に、メインウィンドゥを非表示にしてください。

/*
	KBSkype ver 0.01β


	DDE(Dynamic Data Exchange)
		Windows上でアプリケーションソフト同士がデータやコマンドを行なうための手順の一つ。
		Windows 2.0から実装されているが、OLEなどに取って代わられ、現在ではあまり使われていない。
*/


#module "DDE_client"

	#uselib "user32.dll"
	#func DdeInitialize "DdeInitializeA" int,int,int,int
	#func DdeUninitialize "DdeUninitialize" int
	#cfunc DdeCreateStringHandle "DdeCreateStringHandleA" int,str,int
	#cfunc DdeConnect "DdeConnect" int,int,int,int
	#func DdeFreeStringHandle "DdeFreeStringHandle" int,int
	#func DdeDisconnect "DdeDisconnect" int
	#cfunc DdeClientTransaction "DdeClientTransaction" int,int,int,int,int,int,int,int
	#func DdeGetData "DdeGetData" int,int,int,int
	#func DdeFreeDataHandle "DdeFreeDataHandle" int

	#define CP_WINANSI	  1004
	#define XTYP_REQUEST	$20b0
	#define CF_TEXT		 1
	;------------------------------------------------------------------------
	#deffunc DDE_Init
	if ddeInst : return 0
	; DdeInitialize( &ddeInst, NULL, APPCMD_CLIENTONLY
	;	   | CBF_FAIL_ALLSVRXACTIONS | CBF_SKIP_ALLNOTIFICATIONS, 0 )
	; (本当はコールバック関数はNULLではダメなんだけど…)
	DdeInitialize varptr(ddeInst), 0, $3FF010, 0
	return

	;------------------------------------------------------------------------
	#deffunc DDE_Connect str service, str topic
	hszService = DdeCreateStringHandle( ddeInst, service, CP_WINANSI )
	hszTopic   = DdeCreateStringHandle( ddeInst, topic, CP_WINANSI )
	hConvNew   = DdeConnect( ddeInst, hszService, hszTopic, 0 )
	DdeFreeStringHandle ddeInst, hszService
	DdeFreeStringHandle ddeInst, hszTopic
	return hConvNew

	;------------------------------------------------------------------------
	#deffunc DDE_Disconnect int hConv
	DdeDisconnect hConv
	return (stat == 0)

	;------------------------------------------------------------------------
    #deffunc DDE_Request var retbuf, str item, int hConv, int size, int offset, int _fmt, int _timeout

    if hConv == 0 : return 1
	if ( _fmt == 0 ) : fmt = CF_TEXT : else : fmt = _fmt
	if ( _timeout == 0 ) : timeout = 5000 : else : timeout = _timeout	; デフォルトは5秒

    hszItem = DdeCreateStringHandle( ddeInst, item, CP_WINANSI )
    hDdeData = DdeClientTransaction( 0,0,hConv,hszItem,fmt,XTYP_REQUEST,timeout,0 )
    DdeFreeStringHandle ddeInst, hszItem

    if hDdeData {
        DdeGetData hDdeData, varptr(retbuf), size, offset
        DdeFreeDataHandle hDdeData
        return 0
    }
    return 1



//	#deffunc DDE_Request var retbuf, str item, int hConv, int size, int offset, int _fmt, int _timeout
//
//	sdim retbuf
//	if hConv == 0 : return 1
//	if ( _fmt == 0 ) : fmt = CF_TEXT : else : fmt = _fmt
//	if ( _timeout == 0 ) : timeout = 5000 : else : timeout = _timeout	; デフォルトは5秒
//
//	hszItem = DdeCreateStringHandle( ddeInst, item, CP_WINANSI )
//	hDdeData = DdeClientTransaction( 0,0,hConv,hszItem,fmt,XTYP_REQUEST,timeout,0 )
//	DdeFreeStringHandle ddeInst, hszItem
//
//	if hDdeData {
//		DdeGetData hDdeData, varptr(retbuf), size, offset
//		DdeFreeDataHandle hDdeData
//		return 0
//	}
//	return 1



	;------------------------------------------------------------------------
	#deffunc DDE_Uninit onexit  ; クリーンアップ命令(終了時に自動実行)
	if ddeInst {
		DdeUninitialize ddeInst
		ddeInst = 0
	}
	return

	;------------------------------------------------------------------------
	#global



/*--------------------------------------------------------------------------------------*/


/* trayicon.hsp */
#module "trayicon"
;//   HSP3 で タスクトレイアイコンを作るモジュール 0.02 / 月影とも 2005. 8.12

#define __TRAYICONSAMPLE__  ;// コメントを解除するとサンプルを実行できます

;// 追加命令説明
;//
;// CreateTrayIcon "ツールチップ文字列", アイコン番号, アイコンid
;//   トレイアイコンを作成する。
;//   ツールチップ文字列 = ツールチップに表示する63バイトまでの文字列。
;//   アイコン番号 = SetTrayIconFile で指定したファイルの中に含まれるアイコンのインデックスを指定。
;//   アイコンid   = 作成するiconのidを指定。複数アイコン作成時の識別用。
;//   作ったアイコンを弄られると、*onTrayIconEventというラベルに oncmd gosub でジャンプする。
;//   goto にしてしまうと、ウィンドウに次のメッセージがポストされるまで有効にならないっぽい?
;//
;// PopupBalloonTip "タイトル文字列","バルーンチップ本文", バルーンチップアイコン, アイコンid
;//   CreateTrayIcon済みのアイコンから、バルーンチップをポップアップさせる。
;//   タイトル文字列 = バルーンチップのタイトル部に表示する 63バイトまでの文字列。
;//   バルーンチップ本文 = バルーンチップの本文となる255バイトまでの文字列。
;//   バルーンチップアイコン = 0〜3 が指定できますの。→ 0:ナシ 1:情報(i) 2:警告(!) 3:(エラー)X
;//   アイコンid = バルーンチップを表示させるアイコンのid
;//   Windows Me/2000/XP のみで有効、98SE以前では実行しても何も起こらなそう。
;//
;// DestroyTrayIcon アイコンid
;//   トレイアイコンを削除する。
;//
;// SetTrayIconFile "アイコンファイル.ico"
;//   使用するアイコンファイルを変更する。
;//   アイコンファイル = .ico とか .exe とか。
;//      "" にすると 自分自身のexeファイルアイコンを使う。
;// 

#define WM_TRAYEVENTSTART $900
#define MAXICONS 16 ;// ←アイコン最大数定義

;// 使用するAPIの定義。
#uselib "Kernel32.dll"
#func GetModuleFileName "GetModuleFileNameA" nullptr,prefstr,int ;// 自分自身の名前を得るAPI
#uselib "Shell32.dll"
#func ExtractIconEx "ExtractIconExA" sptr,int,nullptr,var,int ;// ファイルからアイコンを抽出する
#func Shell_NotifyIcon "Shell_NotifyIconA" int,var ;// タスクトレイアイコンを制御する
#uselib "user32.dll"
#func DestroyIcon "DestroyIcon" int ;// 抽出したアイコンを破棄する
#func global SetForegroundWindow "SetForegroundWindow" sptr//はりー追加

#deffunc DestroyTrayIcon int iconid 
    dim NOTIFYICONDATA,88/4                                 ;// NOTIFYICONDATA 構造体を作る。
    NOTIFYICONDATA = 88, hWnd_, iconid
    Shell_NotifyIcon 2, NOTIFYICONDATA                      ;// アイコンを削除する。
    if hIcon.iconid { DestroyIcon hIcon.iconid : hIcon.iconid = 0 } ;// アイコンハンドル破棄
return

#deffunc CreateTrayIcon str tooltip, int nIconIndex, int iconid
    if hIcon.iconid { DestroyTrayIcon iconid }              ;// すでに設定されていたら一度削除する
    ExtractIconEx icofile, nIconIndex, hIcon.iconid, 1      ;// ファイルからアイコンを取り出す。

    dim NOTIFYICONDATA,88/4                                 ;// NOTIFYICONDATA 構造体を作る。
    ;// ↓構造体のサイズ,ウィンドウハンドル,アイコンid,フラグ
    ;//                           メッセージID,アイコンハンドル,ツールチップ
    NOTIFYICONDATA = 88, hWnd_, iconid, 7, WM_TRAYEVENTSTART, hIcon.iconid
    poke NOTIFYICONDATA, 4*6, tooltip

    Shell_NotifyIcon 0, NOTIFYICONDATA                      ;// アイコンを登録する。

    ;// アイコンを弄られたらこのラベルにジャンプするよう指定する。
    oncmd gosub *onTrayIconEvent@, WM_TRAYEVENTSTART
return

#deffunc PopupBalloonTip str balloonInfoTitle, str balloonInfo, int balloonIcon,int iconid
    dim NOTIFYICONDATA,488/4
    NOTIFYICONDATA = 488, hWnd_, iconid, $10
    poke NOTIFYICONDATA, 4*40, balloonInfo
    NOTIFYICONDATA.104 = 1000* 20                           ;// タイムアウト時間: 20secで消える。
    poke NOTIFYICONDATA, 4*105, balloonInfoTitle
    NOTIFYICONDATA.121 = balloonIcon
    
    Shell_NotifyIcon 1, NOTIFYICONDATA                      ;// アイコンを変更する。
return

#deffunc SetTrayIconFile str filename 
    sdim icofile,1024
    if filename = "" { GetModuleFileName 1024 : icofile = refstr }
    else { icofile = filename }
return 

#deffunc _init_trayicon_
    mref bmscr,96: hWnd_ = bmscr.13
    dim hIcon,MAXICONS : SetTrayIconFile "" : return

#deffunc _deinit_trayicon_ onexit  ;// 終了時に全部のアイコンを削除。
    foreach hIcon : if hIcon.cnt { DestroyTrayIcon cnt } loop : return

#global
_init_trayicon_


#uselib "user32.dll" // メニュー用のAPI
	#func CreatePopupMenu "CreatePopupMenu"
	#func TrackPopupMenuEx "TrackPopupMenuEx" int,int,int,int,int,nullptr
	#func AppendMenu "AppendMenuA" int,int,int,sptr
	#func DestroyMenu "DestroyMenu" int

	// PC電源投入してからの経過時間を取得用
	#uselib "kernel32.dll"
	#cfunc GetTickCount "GetTickCount"


	// Skype ムードテキスト書替え用コンポーネント
#module "skype"
	#deffunc skype_moodinit@skype
		newcom oSkype, "Skype4COM.Skype"
		skypeClient = oSkype("Client")
		currentUser = oSkype("CurrentUserProfile")
	return


	#deffunc skype_setmood str p1
		// oSkype("CurrentUserStatus")の返り値
		// -1 : 不明
		//  0 : オフライン
		//  1 : オンライン
		//  2 : 退席中
		//  3 : 使用不可
		//  4 : 取り込み中
		//  5 : ログイン状態を隠す
		//  6 : Skype Me
		if ( skypeClient("IsRunning") != 0 ) {
			if ( tmp == 1 ) : tmp = 0 : wait 100
			status = oSkype("CurrentUserStatus")
			if ( status != -1 ) && ( status != 0 ) && ( status != 3 ) && ( status != 5 ) {
				currentUser("RichMoodText") = p1
			}
		} else {
			tmp = 1
		}
	return
#global
	skype_moodinit@skype


	// デバッグ中かどうかでカレントディレクトリの設定
	#ifdef _debug
		#define DIR "C:\\HSP_WORKS\\KBSkype"
	#else
		#define DIR dir_exe
	#endif


/*-------------------------------------------------------------------------------------------------------------------------------*/

*init
	#define waittime 80

	#define SOFTNAME "KBSkype"
	#define VERINFO  "0.03β"

	#define MENUID_SETMESSAGE 1
	#define MENUID_PAUSE      3
	#define MENUID_END        4

	#define WINX 300
	#define WINY 150


	mode = 1
	zenspace = " "
	code_zenspace = wpeek(zenspace,0)

	// PC電源投入して4分以内なら20秒待たせる
	tick = GetTickCount()
	if ( tick/(1000*60) <= 4 ) && ( tick != 0 ) : wait 2000
	onexit gosub *exit


	// msg.txt読み出し
	sdim msg
	exist DIR+"\\msg.txt"
	if ( strsize != -1 ) {
		notesel msg
		noteload DIR+"\\msg.txt"
	}


	// メニューバーの作成とタスクトレイへ追加
	CreatePopupMenu : hpop = stat
	AppendMenu hpop , 0, MENUID_SETMESSAGE, "メッセージの変更"
	AppendMenu hpop , $800, 2, ""
	AppendMenu hpop , 0, MENUID_PAUSE, "一時停止"
	AppendMenu hpop , $800, 2, ""
	AppendMenu hpop , 0, MENUID_END, "終了"
	CreateTrayIcon SOFTNAME+VERINFO


*checkkb
	DDE_Init
		if ( stat ) : dialog "DDE の初期化に失敗しました。",1 : end

	if ( hConv ) : DDE_Disconnect hConv
	repeat
		skype_setmood msg
		DDE_Connect "KbMedia Player","KbMedia Player"
		hConv = stat
			if ( hConv ) : break
		wait waittime
	loop


*main
	repeat
		if ( mode ) {
			sdim artist,2048 : DDE_Request artist,"artist", hConv, 2048
				if ( stat ) : break

			sdim ttl,1024 : DDE_Request ttl,"title",hConv, 1024
				if ( stat ) : break

			sdim len,1024 : DDE_Request len,"length", hConv, 1024
				if ( stat ) : break

			sdim position,1024 : DDE_Request position,"position",hConv, 1024
				if ( stat ) : break

			position = int(position) / 1000
			len = int(len) / 1000
			nowmin = position / 60
			nowsec = position \ 60
			nowsec = strf("%02d",nowsec)
			min = len / 60
			sec = len \ 60
			sec = strf("%02d",sec)

			sdim format,1024
			sdim prms,1024
			sdim data,1024
			if ( artist != "" ) && ( ttl != "" ) {
				data = artist + " - " + ttl
			} else {
				if ( ttl    != "" ) : data = ttl
				if ( artist != "" ) : data = artist
				if ( strmid(ttl,strlen(ttl)-1,1) == "]" ) {
					sdim fname, 1024 : DDE_Request fname,"filename",hConv, 1024
						if ( stat ) : break
				}
			}
			sdim status,1024 : DDE_Request status,"Status",hConv, 1024
				if ( stat ) : break
			if ( status == "Playing" ) {
				msg = strtrim(msg,0,' ')
				msg = strtrim(msg,0,code_zenspace)
				if ( msg == "" ) : brstr = "" : else : brstr = "\n"
				skype_setmood msg+brstr+"今聴いている曲:♪"+data+" ("+nowmin+":"+nowsec+" / "+min+":"+sec+") tech by はりー総合技術研究所"
				// gsel 0,1
				// title "今聴いている曲:♪"+data+" ("+nowmin+":"+nowsec+" / "+min+":"+sec+")"
			} else {
				skype_setmood msg
			}
		}
		wait waittime
	loop

	// メインループを抜け出して新たにKbが起動するのを監視するループへ移動させる
	//skype_setmood ""
	goto *checkkb
stop


*onTrayIconEvent
	// トレイアイコンのサブルーチン[左クリック:$201][右クリック:$205]
	iconid = wParam
	if (lparam == $201 ) || (lparam == $205 ) : SetForegroundWindow hwnd : gosub *popupmenu
return


*popupmenu
	TrackPopupMenuEx hpop,$182,ginfo_mx,ginfo_my,hWnd : menuid = stat
	switch menuid
		case MENUID_SETMESSAGE
			screen 1,WINX,WINY,SCREEN_FRAME+SCREEN_TOOL,(ginfo_dispx-WINX)/2,(ginfo_dispy-WINY)/2
			title "設定画面 - "+SOFTNAME+" Ver."+VERINFO
			syscolor 15 : boxf
			msg_backup = msg
			pos 080,020
			color 000,000,000
			mes "表示するメッセージ"
			pos 020,050
			mesbox msg,260,50,1
			sendmsg objinfo_hwnd(stat), $B1/*EM_SETSEL*/, 0,-1
			objsize 80,20
			pos 050,115 : button gosub "OK"         , *setmessage : btnid_ok = stat
			pos 170,115 : button gosub "キャンセル" , *setmessage
			return
		case MENUID_PAUSE : 
			if ( mode == 0 ) {
				DestroyMenu hpop
				mode = 1
				CreatePopupMenu : hpop = stat
				AppendMenu hpop , 0, MENUID_SETMESSAGE, "メッセージの変更"
				AppendMenu hpop , $800, 2, ""
				AppendMenu hpop , 0, MENUID_PAUSE, "一時停止"
				AppendMenu hpop , $800, 2, ""
				AppendMenu hpop , 0, MENUID_END, "終了"
				return
			} else {
				DestroyMenu hpop
				mode = 0
				CreatePopupMenu : hpop = stat
				AppendMenu hpop , 0, MENUID_SETMESSAGE, "メッセージの変更"
				AppendMenu hpop , $800, 2, ""
				AppendMenu hpop , 0, MENUID_PAUSE, "動作再開"
				AppendMenu hpop , $800, 2, "----"
				AppendMenu hpop , 0, MENUID_END, "終了"
				skype_setmood ""
				return
			}
			swbreak
		case MENUID_END : goto *exit : swbreak
	swend
	return


*setmessage
	gsel 1,-1
	if ( stat == btnid_ok ) {
		// メッセージ適用させる
		notesel msg
		notesave DIR+"\\msg.txt"
	} else {
		msg = msg_backup
	}
return




*exit
	if ( wparam == 1 ) {
		gsel 1,-1
		return
	}
	DestroyMenu hpop
	skype_setmood ""
	DDE_Uninit
end