371 lines
9.0 KiB
C
371 lines
9.0 KiB
C
/* $Id$ */
|
|
/*
|
|
* Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
#include <winuserm.h>
|
|
#include <aygshell.h>
|
|
#include "..\pjsua_app.h"
|
|
#include "..\pjsua_app_config.h"
|
|
|
|
#define MAINWINDOWCLASS TEXT("PjsuaDlg")
|
|
#define MAINWINDOWTITLE TEXT("PJSUA")
|
|
#define LOGO_PATH TEXT("\\Program Files\\pjsua\\pjsua.bmp")
|
|
|
|
#define WM_APP_INIT WM_USER + 1
|
|
#define WM_APP_DESTROY WM_USER + 2
|
|
#define WM_APP_RESTART WM_USER + 3
|
|
|
|
static HINSTANCE g_hInst;
|
|
static HWND g_hWndMenuBar;
|
|
static HWND g_hWndMain;
|
|
static HWND g_hWndLbl;
|
|
static HWND g_hWndImg;
|
|
static HBITMAP g_hBmp;
|
|
|
|
static int start_argc;
|
|
static char **start_argv;
|
|
|
|
/* Helper funtions to init/destroy the pjsua */
|
|
static void PjsuaInit();
|
|
static void PjsuaDestroy();
|
|
|
|
/* pjsua app callbacks */
|
|
static void PjsuaOnStarted(pj_status_t status, const char* title);
|
|
static void PjsuaOnStopped(pj_bool_t restart, int argc, char** argv);
|
|
static void PjsuaOnConfig(pjsua_app_config *cfg);
|
|
|
|
LRESULT CALLBACK DialogProc(const HWND hWnd,
|
|
const UINT Msg,
|
|
const WPARAM wParam,
|
|
const LPARAM lParam)
|
|
{
|
|
LRESULT res = 0;
|
|
|
|
switch (Msg) {
|
|
case WM_CREATE:
|
|
g_hWndMain = hWnd;
|
|
break;
|
|
|
|
case WM_COMMAND: /* Exit menu */
|
|
case WM_CLOSE:
|
|
PostQuitMessage(0);
|
|
break;
|
|
|
|
case WM_HOTKEY:
|
|
/* Exit app when back is pressed. */
|
|
if (VK_TBACK == HIWORD(lParam) && (0 != (MOD_KEYUP & LOWORD(lParam)))) {
|
|
PostQuitMessage(0);
|
|
} else {
|
|
return DefWindowProc(hWnd, Msg, wParam, lParam);
|
|
}
|
|
break;
|
|
|
|
case WM_CTLCOLORSTATIC:
|
|
/* Set text and background color for static windows */
|
|
SetTextColor((HDC)wParam, RGB(255, 255, 255));
|
|
SetBkColor((HDC)wParam, RGB(0, 0, 0));
|
|
return (LRESULT)GetStockObject(BLACK_BRUSH);
|
|
|
|
case WM_APP_INIT:
|
|
case WM_APP_RESTART:
|
|
PjsuaInit();
|
|
break;
|
|
|
|
case WM_APP_DESTROY:
|
|
PostQuitMessage(0);
|
|
break;
|
|
|
|
default:
|
|
return DefWindowProc(hWnd, Msg, wParam, lParam);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
/* === GUI === */
|
|
|
|
pj_status_t GuiInit()
|
|
{
|
|
WNDCLASS wc;
|
|
HWND hWnd = NULL;
|
|
RECT r;
|
|
DWORD dwStyle;
|
|
enum { LABEL_HEIGHT = 30 };
|
|
enum { MENU_ID_EXIT = 50000 };
|
|
BITMAP bmp;
|
|
HMENU hRootMenu;
|
|
SHMENUBARINFO mbi;
|
|
|
|
pj_status_t status = PJ_SUCCESS;
|
|
|
|
/* Check if app is running. If it's running then focus on the window */
|
|
hWnd = FindWindow(MAINWINDOWCLASS, MAINWINDOWTITLE);
|
|
|
|
if (NULL != hWnd) {
|
|
SetForegroundWindow(hWnd);
|
|
return status;
|
|
}
|
|
|
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
|
wc.lpfnWndProc = (WNDPROC)DialogProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = g_hInst;
|
|
wc.hIcon = 0;
|
|
wc.hCursor = 0;
|
|
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
|
wc.lpszMenuName = 0;
|
|
wc.lpszClassName = MAINWINDOWCLASS;
|
|
|
|
if (!RegisterClass(&wc) != 0) {
|
|
DWORD err = GetLastError();
|
|
return PJ_RETURN_OS_ERROR(err);
|
|
}
|
|
|
|
/* Create the app. window */
|
|
g_hWndMain = CreateWindow(MAINWINDOWCLASS, MAINWINDOWTITLE,
|
|
WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
|
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
|
(HWND)NULL, NULL, g_hInst, (LPSTR)NULL);
|
|
if (g_hWndMain == NULL) {
|
|
DWORD err = GetLastError();
|
|
return PJ_RETURN_OS_ERROR(err);
|
|
}
|
|
|
|
/* Create exit menu */
|
|
hRootMenu = CreateMenu();
|
|
AppendMenu(hRootMenu, MF_STRING, MENU_ID_EXIT, L"Exit");
|
|
|
|
/* Initialize menubar */
|
|
ZeroMemory(&mbi, sizeof(SHMENUBARINFO));
|
|
mbi.cbSize = sizeof(SHMENUBARINFO);
|
|
mbi.hwndParent = g_hWndMain;
|
|
mbi.dwFlags = SHCMBF_HIDESIPBUTTON|SHCMBF_HMENU;
|
|
mbi.nToolBarId = (UINT)hRootMenu;
|
|
mbi.hInstRes = g_hInst;
|
|
|
|
if (FALSE == SHCreateMenuBar(&mbi)) {
|
|
DWORD err = GetLastError();
|
|
return PJ_RETURN_OS_ERROR(err);
|
|
}
|
|
|
|
/* Store menu window handle */
|
|
g_hWndMenuBar = mbi.hwndMB;
|
|
|
|
/* Show the menu */
|
|
DrawMenuBar(g_hWndMain);
|
|
ShowWindow(g_hWndMenuBar, SW_SHOW);
|
|
|
|
/* Override back button */
|
|
SendMessage(g_hWndMenuBar, SHCMBM_OVERRIDEKEY, VK_TBACK,
|
|
MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY,
|
|
SHMBOF_NODEFAULT | SHMBOF_NOTIFY));
|
|
|
|
/* Get main window size */
|
|
GetClientRect(g_hWndMain, &r);
|
|
#if defined(WIN32_PLATFORM_PSPC) && WIN32_PLATFORM_PSPC != 0
|
|
/* Adjust the height for PocketPC platform */
|
|
r.bottom -= GetSystemMetrics(SM_CYMENU);
|
|
#endif
|
|
|
|
/* Create logo */
|
|
g_hBmp = SHLoadDIBitmap(LOGO_PATH); /* for jpeg, uses SHLoadImageFile() */
|
|
if (g_hBmp == NULL) {
|
|
DWORD err = GetLastError();
|
|
return PJ_RETURN_OS_ERROR(err);
|
|
}
|
|
GetObject(g_hBmp, sizeof(bmp), &bmp);
|
|
|
|
dwStyle = SS_CENTERIMAGE | SS_REALSIZEIMAGE | SS_BITMAP |
|
|
WS_CHILD | WS_VISIBLE;
|
|
g_hWndImg = CreateWindow(TEXT("STATIC"), NULL, dwStyle,
|
|
(r.right-r.left-bmp.bmWidth)/2,
|
|
(r.bottom-r.top-bmp.bmHeight)/2,
|
|
bmp.bmWidth, bmp.bmHeight,
|
|
g_hWndMain, (HMENU)0, g_hInst, NULL);
|
|
if (g_hWndImg == NULL) {
|
|
DWORD err = GetLastError();
|
|
return PJ_RETURN_OS_ERROR(err);
|
|
}
|
|
SendMessage(g_hWndImg, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)g_hBmp);
|
|
|
|
/* Create label */
|
|
dwStyle = WS_CHILD | WS_VISIBLE | ES_CENTER;
|
|
g_hWndLbl = CreateWindow(TEXT("STATIC"), NULL, dwStyle,
|
|
0, r.bottom-LABEL_HEIGHT, r.right-r.left, LABEL_HEIGHT,
|
|
g_hWndMain, (HMENU)0, g_hInst, NULL);
|
|
if (g_hWndLbl == NULL) {
|
|
DWORD err = GetLastError();
|
|
return PJ_RETURN_OS_ERROR(err);
|
|
}
|
|
SetWindowText(g_hWndLbl, _T("Please wait.."));
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
pj_status_t GuiStart()
|
|
{
|
|
MSG msg;
|
|
while (GetMessage(&msg, NULL, 0, 0)) {
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
return (msg.wParam);
|
|
}
|
|
|
|
void GuiDestroy(void)
|
|
{
|
|
if (g_hWndMain) {
|
|
DestroyWindow(g_hWndMain);
|
|
g_hWndMain = NULL;
|
|
}
|
|
if (g_hWndMenuBar) {
|
|
DestroyWindow(g_hWndMenuBar);
|
|
g_hWndMenuBar = NULL;
|
|
}
|
|
if (g_hWndLbl) {
|
|
DestroyWindow(g_hWndLbl);
|
|
g_hWndLbl = NULL;
|
|
}
|
|
if (g_hWndImg) {
|
|
DestroyWindow(g_hWndImg);
|
|
g_hWndImg = NULL;
|
|
}
|
|
if (g_hBmp) {
|
|
DeleteObject(g_hBmp);
|
|
g_hBmp = NULL;
|
|
}
|
|
UnregisterClass(MAINWINDOWCLASS, g_hInst);
|
|
}
|
|
|
|
/* === ENGINE === */
|
|
|
|
/* Called when pjsua is started */
|
|
void PjsuaOnStarted(pj_status_t status, const char* title)
|
|
{
|
|
wchar_t wtitle[128];
|
|
char err_msg[128];
|
|
|
|
if (status != PJ_SUCCESS || title == NULL) {
|
|
char err_str[PJ_ERR_MSG_SIZE];
|
|
pj_strerror(status, err_str, sizeof(err_str));
|
|
pj_ansi_snprintf(err_msg, sizeof(err_msg), "%s: %s",
|
|
(title?title:"App start error"), err_str);
|
|
title = err_msg;
|
|
}
|
|
|
|
pj_ansi_to_unicode(title, strlen(title), wtitle, PJ_ARRAY_SIZE(wtitle));
|
|
SetWindowText(g_hWndLbl, wtitle);
|
|
}
|
|
|
|
/* Called when pjsua is stopped */
|
|
void PjsuaOnStopped(pj_bool_t restart, int argc, char** argv)
|
|
{
|
|
if (restart) {
|
|
start_argc = argc;
|
|
start_argv = argv;
|
|
|
|
// Schedule Lib Restart
|
|
PostMessage(g_hWndMain, WM_APP_RESTART, 0, 0);
|
|
} else {
|
|
/* Destroy & quit GUI, e.g: clean up window, resources */
|
|
PostMessage(g_hWndMain, WM_APP_DESTROY, 0, 0);
|
|
}
|
|
}
|
|
|
|
/* Called before pjsua initializing config. */
|
|
void PjsuaOnConfig(pjsua_app_config *cfg)
|
|
{
|
|
PJ_UNUSED_ARG(cfg);
|
|
}
|
|
|
|
void PjsuaInit()
|
|
{
|
|
pjsua_app_cfg_t app_cfg;
|
|
pj_status_t status;
|
|
|
|
/* Destroy pjsua app first */
|
|
pjsua_app_destroy();
|
|
|
|
/* Init pjsua app */
|
|
pj_bzero(&app_cfg, sizeof(app_cfg));
|
|
app_cfg.argc = start_argc;
|
|
app_cfg.argv = start_argv;
|
|
app_cfg.on_started = &PjsuaOnStarted;
|
|
app_cfg.on_stopped = &PjsuaOnStopped;
|
|
app_cfg.on_config_init = &PjsuaOnConfig;
|
|
|
|
SetWindowText(g_hWndLbl, _T("Initializing.."));
|
|
status = pjsua_app_init(&app_cfg);
|
|
if (status != PJ_SUCCESS)
|
|
goto on_return;
|
|
|
|
SetWindowText(g_hWndLbl, _T("Starting.."));
|
|
status = pjsua_app_run(PJ_FALSE);
|
|
if (status != PJ_SUCCESS)
|
|
goto on_return;
|
|
|
|
on_return:
|
|
if (status != PJ_SUCCESS)
|
|
SetWindowText(g_hWndLbl, _T("Initialization failed"));
|
|
}
|
|
|
|
void PjsuaDestroy()
|
|
{
|
|
pjsua_app_destroy();
|
|
}
|
|
|
|
/* === MAIN === */
|
|
|
|
int WINAPI WinMain(
|
|
HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPWSTR lpCmdLine,
|
|
int nShowCmd
|
|
)
|
|
{
|
|
int status;
|
|
|
|
PJ_UNUSED_ARG(hPrevInstance);
|
|
PJ_UNUSED_ARG(lpCmdLine);
|
|
PJ_UNUSED_ARG(nShowCmd);
|
|
|
|
// store the hInstance in global
|
|
g_hInst = hInstance;
|
|
|
|
// Start GUI
|
|
status = GuiInit();
|
|
if (status != 0)
|
|
goto on_return;
|
|
|
|
// Setup args and start pjsua
|
|
start_argc = pjsua_app_def_argc;
|
|
start_argv = (char**)pjsua_app_def_argv;
|
|
PostMessage(g_hWndMain, WM_APP_INIT, 0, 0);
|
|
|
|
status = GuiStart();
|
|
|
|
on_return:
|
|
PjsuaDestroy();
|
|
GuiDestroy();
|
|
|
|
return status;
|
|
}
|