⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pjsua_wince.cpp

📁 一个开源SIP协议栈
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -