📄 pjsua_wince.cpp
字号:
// pjsua_wince.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "pjsua_wince.h"
#include <commctrl.h>
#include <pjsua-lib/pjsua.h>
#define MAX_LOADSTRING 100
// Global Variables:
static HINSTANCE hInst;
static HWND hMainWnd;
static HWND hwndCB;
static HWND hwndGlobalStatus, hwndURI, hwndCallStatus;
static HWND hwndActionButton, hwndExitButton;
static pj_pool_t *g_pool;
static pj_str_t g_local_uri;
static int g_current_acc;
static int g_current_call = PJSUA_INVALID_ID;
static int g_current_action;
enum
{
ID_GLOBAL_STATUS = 21,
ID_URI,
ID_CALL_STATUS,
ID_POLL_TIMER,
};
enum
{
ID_MENU_NONE = 64,
ID_MENU_CALL,
ID_MENU_ANSWER,
ID_MENU_DISCONNECT,
ID_BTN_ACTION,
};
#define DEFAULT_URI "sip:192.168.0.7"
// Forward declarations of functions included in this code module:
static ATOM MyRegisterClass (HINSTANCE, LPTSTR);
BOOL InitInstance (HINSTANCE, int);
static void OnCreate (HWND hWnd);
static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
/////////////////////////////////////////////////////////////////////////////
static void OnError(const wchar_t *title, pj_status_t status)
{
char errmsg[PJ_ERR_MSG_SIZE];
PJ_DECL_UNICODE_TEMP_BUF(werrmsg, PJ_ERR_MSG_SIZE);
pj_strerror(status, errmsg, sizeof(errmsg));
MessageBox(NULL, PJ_STRING_TO_NATIVE(errmsg, werrmsg, PJ_ERR_MSG_SIZE),
title, MB_OK);
}
static void SetLocalURI(const char *uri, int len, bool enabled=true)
{
wchar_t tmp[128];
if (len==-1) len=pj_ansi_strlen(uri);
pj_ansi_to_unicode(uri, len, tmp, PJ_ARRAY_SIZE(tmp));
SetDlgItemText(hMainWnd, ID_GLOBAL_STATUS, tmp);
EnableWindow(hwndGlobalStatus, enabled?TRUE:FALSE);
}
static void SetURI(const char *uri, int len, bool enabled=true)
{
wchar_t tmp[128];
if (len==-1) len=pj_ansi_strlen(uri);
pj_ansi_to_unicode(uri, len, tmp, PJ_ARRAY_SIZE(tmp));
SetDlgItemText(hMainWnd, ID_URI, tmp);
EnableWindow(hwndURI, enabled?TRUE:FALSE);
}
static void SetCallStatus(const char *state, int len)
{
wchar_t tmp[128];
if (len==-1) len=pj_ansi_strlen(state);
pj_ansi_to_unicode(state, len, tmp, PJ_ARRAY_SIZE(tmp));
SetDlgItemText(hMainWnd, ID_CALL_STATUS, tmp);
}
static void SetAction(int action, bool enable=true)
{
HMENU hMenu;
hMenu = CommandBar_GetMenu(hwndCB, 0);
RemoveMenu(hMenu, ID_MENU_NONE, MF_BYCOMMAND);
RemoveMenu(hMenu, ID_MENU_CALL, MF_BYCOMMAND);
RemoveMenu(hMenu, ID_MENU_ANSWER, MF_BYCOMMAND);
RemoveMenu(hMenu, ID_MENU_DISCONNECT, MF_BYCOMMAND);
switch (action) {
case ID_MENU_NONE:
InsertMenu(hMenu, ID_EXIT, MF_BYCOMMAND, action, TEXT("None"));
SetWindowText(hwndActionButton, TEXT("-"));
break;
case ID_MENU_CALL:
InsertMenu(hMenu, ID_EXIT, MF_BYCOMMAND, action, TEXT("Call"));
SetWindowText(hwndActionButton, TEXT("&Call"));
break;
case ID_MENU_ANSWER:
InsertMenu(hMenu, ID_EXIT, MF_BYCOMMAND, action, TEXT("Answer"));
SetWindowText(hwndActionButton, TEXT("&Answer"));
break;
case ID_MENU_DISCONNECT:
InsertMenu(hMenu, ID_EXIT, MF_BYCOMMAND, action, TEXT("Hangup"));
SetWindowText(hwndActionButton, TEXT("&Hangup"));
break;
}
EnableMenuItem(hMenu, action, MF_BYCOMMAND | (enable?MF_ENABLED:MF_GRAYED));
DrawMenuBar(hMainWnd);
g_current_action = action;
}
/*
* Handler when invite state has changed.
*/
static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
{
pjsua_call_info call_info;
PJ_UNUSED_ARG(e);
pjsua_call_get_info(call_id, &call_info);
if (call_info.state == PJSIP_INV_STATE_DISCONNECTED) {
g_current_call = PJSUA_INVALID_ID;
SetURI(DEFAULT_URI, -1);
SetAction(ID_MENU_CALL);
//SetCallStatus(call_info.state_text.ptr, call_info.state_text.slen);
SetCallStatus(call_info.last_status_text.ptr, call_info.last_status_text.slen);
} else {
//if (g_current_call == PJSUA_INVALID_ID)
// g_current_call = call_id;
if (call_info.remote_contact.slen)
SetURI(call_info.remote_contact.ptr, call_info.remote_contact.slen, false);
else
SetURI(call_info.remote_info.ptr, call_info.remote_info.slen, false);
if (call_info.state == PJSIP_INV_STATE_CONFIRMED)
SetAction(ID_MENU_DISCONNECT);
SetCallStatus(call_info.state_text.ptr, call_info.state_text.slen);
}
}
/*
* Callback on media state changed event.
* The action may connect the call to sound device, to file, or
* to loop the call.
*/
static void on_call_media_state(pjsua_call_id call_id)
{
pjsua_call_info call_info;
pjsua_call_get_info(call_id, &call_info);
if (call_info.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
pjsua_conf_connect(call_info.conf_slot, 0);
pjsua_conf_connect(0, call_info.conf_slot);
}
}
/**
* Handler when there is incoming call.
*/
static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
pjsip_rx_data *rdata)
{
pjsua_call_info call_info;
PJ_UNUSED_ARG(acc_id);
PJ_UNUSED_ARG(rdata);
if (g_current_call != PJSUA_INVALID_ID) {
pj_str_t reason;
reason = pj_str("Another call is in progress");
pjsua_call_answer(call_id, PJSIP_SC_BUSY_HERE, &reason, NULL);
return;
}
g_current_call = call_id;
pjsua_call_get_info(call_id, &call_info);
SetAction(ID_MENU_ANSWER);
SetURI(call_info.remote_info.ptr, call_info.remote_info.slen, false);
pjsua_call_answer(call_id, 200, NULL, NULL);
}
/*
* Handler registration status has changed.
*/
static void on_reg_state(pjsua_acc_id acc_id)
{
PJ_UNUSED_ARG(acc_id);
// Log already written.
}
/*
* Handler on buddy state changed.
*/
static void on_buddy_state(pjsua_buddy_id buddy_id)
{
}
/**
* Incoming IM message (i.e. MESSAGE request)!
*/
static void on_pager(pjsua_call_id call_id, const pj_str_t *from,
const pj_str_t *to, const pj_str_t *contact,
const pj_str_t *mime_type, const pj_str_t *text)
{
}
/**
* Received typing indication
*/
static void on_typing(pjsua_call_id call_id, const pj_str_t *from,
const pj_str_t *to, const pj_str_t *contact,
pj_bool_t is_typing)
{
}
static BOOL OnInitStack(void)
{
pjsua_config cfg;
pjsua_logging_config log_cfg;
pjsua_media_config media_cfg;
pjsua_transport_config udp_cfg;
pjsua_transport_config rtp_cfg;
pjsua_transport_id transport_id;
pjsua_transport_info transport_info;
pj_str_t tmp;
pj_status_t status;
/* Create pjsua */
status = pjsua_create();
if (status != PJ_SUCCESS) {
OnError(TEXT("Error creating pjsua"), status);
return FALSE;
}
/* Create global pool for application */
g_pool = pjsua_pool_create("pjsua", 4000, 4000);
/* Init configs */
pjsua_config_default(&cfg);
pjsua_media_config_default(&media_cfg);
pjsua_transport_config_default(&udp_cfg);
udp_cfg.port = 50060;
pjsua_transport_config_default(&rtp_cfg);
rtp_cfg.port = 40000;
pjsua_logging_config_default(&log_cfg);
log_cfg.level = 5;
log_cfg.log_filename = pj_str("\\pjsua.txt");
log_cfg.msg_logging = 1;
log_cfg.decor = pj_log_get_decor() | PJ_LOG_HAS_CR;
/* Setup media */
media_cfg.clock_rate = 8000;
media_cfg.ec_options = PJMEDIA_ECHO_SIMPLE;
media_cfg.ec_tail_len = 256;
media_cfg.quality = 1;
media_cfg.ptime = 20;
/* Initialize application callbacks */
cfg.cb.on_call_state = &on_call_state;
cfg.cb.on_call_media_state = &on_call_media_state;
cfg.cb.on_incoming_call = &on_incoming_call;
cfg.cb.on_reg_state = &on_reg_state;
cfg.cb.on_buddy_state = &on_buddy_state;
cfg.cb.on_pager = &on_pager;
cfg.cb.on_typing = &on_typing;
/* Initialize pjsua */
status = pjsua_init(&cfg, &log_cfg, &media_cfg);
if (status != PJ_SUCCESS) {
OnError(TEXT("Initialization error"), status);
return FALSE;
}
/* Set codec priority */
pjsua_codec_set_priority(pj_cstr(&tmp, "pcmu"), 240);
pjsua_codec_set_priority(pj_cstr(&tmp, "pcma"), 230);
pjsua_codec_set_priority(pj_cstr(&tmp, "speex/8000"), 190);
pjsua_codec_set_priority(pj_cstr(&tmp, "ilbc"), 189);
pjsua_codec_set_priority(pj_cstr(&tmp, "speex/16000"), 180);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -