blob: 311ca77dbc90b05c9979c204a21ceae2c214c662 [file] [log] [blame]
Nanang Izzuddinae5394d2013-04-19 10:36:11 +00001/* $Id$ */
2/*
3 * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
Nanang Izzuddinae5394d2013-04-19 10:36:11 +000019#include <winuserm.h>
20#include <aygshell.h>
21#include "..\pjsua_app.h"
Nanang Izzuddincd9e8912013-04-23 10:59:52 +000022#include "..\pjsua_app_config.h"
Nanang Izzuddinae5394d2013-04-19 10:36:11 +000023
24#define MAINWINDOWCLASS TEXT("PjsuaDlg")
25#define MAINWINDOWTITLE TEXT("PJSUA")
26#define LOGO_PATH TEXT("\\Program Files\\pjsua\\pjsua.bmp")
27
28#define WM_APP_INIT WM_USER + 1
29#define WM_APP_DESTROY WM_USER + 2
30#define WM_APP_RESTART WM_USER + 3
31
32static HINSTANCE g_hInst;
33static HWND g_hWndMenuBar;
34static HWND g_hWndMain;
35static HWND g_hWndLbl;
36static HWND g_hWndImg;
37static HBITMAP g_hBmp;
38
Nanang Izzuddincd9e8912013-04-23 10:59:52 +000039static int start_argc;
40static char **start_argv;
Nanang Izzuddinae5394d2013-04-19 10:36:11 +000041
Nanang Izzuddincd9e8912013-04-23 10:59:52 +000042/* Helper funtions to init/destroy the pjsua */
43static void PjsuaInit();
44static void PjsuaDestroy();
Nanang Izzuddinae5394d2013-04-19 10:36:11 +000045
46/* pjsua app callbacks */
Nanang Izzuddincd9e8912013-04-23 10:59:52 +000047static void PjsuaOnStarted(pj_status_t status, const char* title);
48static void PjsuaOnStopped(pj_bool_t restart, int argc, char** argv);
49static void PjsuaOnConfig(pjsua_app_config *cfg);
Nanang Izzuddinae5394d2013-04-19 10:36:11 +000050
51LRESULT CALLBACK DialogProc(const HWND hWnd,
52 const UINT Msg,
53 const WPARAM wParam,
54 const LPARAM lParam)
55{
56 LRESULT res = 0;
57
58 switch (Msg) {
59 case WM_CREATE:
60 g_hWndMain = hWnd;
61 break;
62
63 case WM_COMMAND: /* Exit menu */
64 case WM_CLOSE:
65 PostQuitMessage(0);
66 break;
67
68 case WM_HOTKEY:
69 /* Exit app when back is pressed. */
70 if (VK_TBACK == HIWORD(lParam) && (0 != (MOD_KEYUP & LOWORD(lParam)))) {
71 PostQuitMessage(0);
72 } else {
73 return DefWindowProc(hWnd, Msg, wParam, lParam);
74 }
75 break;
76
77 case WM_CTLCOLORSTATIC:
78 /* Set text and background color for static windows */
79 SetTextColor((HDC)wParam, RGB(255, 255, 255));
80 SetBkColor((HDC)wParam, RGB(0, 0, 0));
81 return (LRESULT)GetStockObject(BLACK_BRUSH);
82
83 case WM_APP_INIT:
Nanang Izzuddincd9e8912013-04-23 10:59:52 +000084 case WM_APP_RESTART:
85 PjsuaInit();
Nanang Izzuddinae5394d2013-04-19 10:36:11 +000086 break;
87
88 case WM_APP_DESTROY:
Nanang Izzuddinae5394d2013-04-19 10:36:11 +000089 PostQuitMessage(0);
90 break;
91
Nanang Izzuddinae5394d2013-04-19 10:36:11 +000092 default:
93 return DefWindowProc(hWnd, Msg, wParam, lParam);
94 }
95
96 return res;
97}
98
99
100/* === GUI === */
101
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000102pj_status_t GuiInit()
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000103{
104 WNDCLASS wc;
105 HWND hWnd = NULL;
106 RECT r;
107 DWORD dwStyle;
108 enum { LABEL_HEIGHT = 30 };
109 enum { MENU_ID_EXIT = 50000 };
110 BITMAP bmp;
111 HMENU hRootMenu;
112 SHMENUBARINFO mbi;
113
114 pj_status_t status = PJ_SUCCESS;
115
116 /* Check if app is running. If it's running then focus on the window */
117 hWnd = FindWindow(MAINWINDOWCLASS, MAINWINDOWTITLE);
118
119 if (NULL != hWnd) {
120 SetForegroundWindow(hWnd);
121 return status;
122 }
123
124 wc.style = CS_HREDRAW | CS_VREDRAW;
125 wc.lpfnWndProc = (WNDPROC)DialogProc;
126 wc.cbClsExtra = 0;
127 wc.cbWndExtra = 0;
128 wc.hInstance = g_hInst;
129 wc.hIcon = 0;
130 wc.hCursor = 0;
131 wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
132 wc.lpszMenuName = 0;
133 wc.lpszClassName = MAINWINDOWCLASS;
134
135 if (!RegisterClass(&wc) != 0) {
136 DWORD err = GetLastError();
137 return PJ_RETURN_OS_ERROR(err);
138 }
139
140 /* Create the app. window */
141 g_hWndMain = CreateWindow(MAINWINDOWCLASS, MAINWINDOWTITLE,
142 WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
143 CW_USEDEFAULT, CW_USEDEFAULT,
144 (HWND)NULL, NULL, g_hInst, (LPSTR)NULL);
145 if (g_hWndMain == NULL) {
146 DWORD err = GetLastError();
147 return PJ_RETURN_OS_ERROR(err);
148 }
149
150 /* Create exit menu */
151 hRootMenu = CreateMenu();
152 AppendMenu(hRootMenu, MF_STRING, MENU_ID_EXIT, L"Exit");
153
154 /* Initialize menubar */
155 ZeroMemory(&mbi, sizeof(SHMENUBARINFO));
156 mbi.cbSize = sizeof(SHMENUBARINFO);
157 mbi.hwndParent = g_hWndMain;
158 mbi.dwFlags = SHCMBF_HIDESIPBUTTON|SHCMBF_HMENU;
159 mbi.nToolBarId = (UINT)hRootMenu;
160 mbi.hInstRes = g_hInst;
161
162 if (FALSE == SHCreateMenuBar(&mbi)) {
163 DWORD err = GetLastError();
164 return PJ_RETURN_OS_ERROR(err);
165 }
166
167 /* Store menu window handle */
168 g_hWndMenuBar = mbi.hwndMB;
169
170 /* Show the menu */
171 DrawMenuBar(g_hWndMain);
172 ShowWindow(g_hWndMenuBar, SW_SHOW);
173
174 /* Override back button */
175 SendMessage(g_hWndMenuBar, SHCMBM_OVERRIDEKEY, VK_TBACK,
176 MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY,
177 SHMBOF_NODEFAULT | SHMBOF_NOTIFY));
178
179 /* Get main window size */
180 GetClientRect(g_hWndMain, &r);
181#if defined(WIN32_PLATFORM_PSPC) && WIN32_PLATFORM_PSPC != 0
182 /* Adjust the height for PocketPC platform */
183 r.bottom -= GetSystemMetrics(SM_CYMENU);
184#endif
185
186 /* Create logo */
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000187 g_hBmp = SHLoadDIBitmap(LOGO_PATH); /* for jpeg, uses SHLoadImageFile() */
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000188 if (g_hBmp == NULL) {
189 DWORD err = GetLastError();
190 return PJ_RETURN_OS_ERROR(err);
191 }
192 GetObject(g_hBmp, sizeof(bmp), &bmp);
193
194 dwStyle = SS_CENTERIMAGE | SS_REALSIZEIMAGE | SS_BITMAP |
195 WS_CHILD | WS_VISIBLE;
196 g_hWndImg = CreateWindow(TEXT("STATIC"), NULL, dwStyle,
197 (r.right-r.left-bmp.bmWidth)/2,
198 (r.bottom-r.top-bmp.bmHeight)/2,
199 bmp.bmWidth, bmp.bmHeight,
200 g_hWndMain, (HMENU)0, g_hInst, NULL);
201 if (g_hWndImg == NULL) {
202 DWORD err = GetLastError();
203 return PJ_RETURN_OS_ERROR(err);
204 }
205 SendMessage(g_hWndImg, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)g_hBmp);
206
207 /* Create label */
208 dwStyle = WS_CHILD | WS_VISIBLE | ES_CENTER;
209 g_hWndLbl = CreateWindow(TEXT("STATIC"), NULL, dwStyle,
210 0, r.bottom-LABEL_HEIGHT, r.right-r.left, LABEL_HEIGHT,
211 g_hWndMain, (HMENU)0, g_hInst, NULL);
212 if (g_hWndLbl == NULL) {
213 DWORD err = GetLastError();
214 return PJ_RETURN_OS_ERROR(err);
215 }
216 SetWindowText(g_hWndLbl, _T("Please wait.."));
217
218 return status;
219}
220
221
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000222pj_status_t GuiStart()
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000223{
224 MSG msg;
225 while (GetMessage(&msg, NULL, 0, 0)) {
226 TranslateMessage(&msg);
227 DispatchMessage(&msg);
228 }
229
230 return (msg.wParam);
231}
232
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000233void GuiDestroy(void)
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000234{
235 if (g_hWndMain) {
236 DestroyWindow(g_hWndMain);
237 g_hWndMain = NULL;
238 }
239 if (g_hWndMenuBar) {
240 DestroyWindow(g_hWndMenuBar);
241 g_hWndMenuBar = NULL;
242 }
243 if (g_hWndLbl) {
244 DestroyWindow(g_hWndLbl);
245 g_hWndLbl = NULL;
246 }
247 if (g_hWndImg) {
248 DestroyWindow(g_hWndImg);
249 g_hWndImg = NULL;
250 }
251 if (g_hBmp) {
252 DeleteObject(g_hBmp);
253 g_hBmp = NULL;
254 }
255 UnregisterClass(MAINWINDOWCLASS, g_hInst);
256}
257
258/* === ENGINE === */
259
260/* Called when pjsua is started */
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000261void PjsuaOnStarted(pj_status_t status, const char* title)
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000262{
263 wchar_t wtitle[128];
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000264 char err_msg[128];
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000265
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000266 if (status != PJ_SUCCESS || title == NULL) {
267 char err_str[PJ_ERR_MSG_SIZE];
268 pj_strerror(status, err_str, sizeof(err_str));
269 pj_ansi_snprintf(err_msg, sizeof(err_msg), "%s: %s",
270 (title?title:"App start error"), err_str);
271 title = err_msg;
272 }
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000273
274 pj_ansi_to_unicode(title, strlen(title), wtitle, PJ_ARRAY_SIZE(wtitle));
275 SetWindowText(g_hWndLbl, wtitle);
276}
277
278/* Called when pjsua is stopped */
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000279void PjsuaOnStopped(pj_bool_t restart, int argc, char** argv)
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000280{
281 if (restart) {
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000282 start_argc = argc;
283 start_argv = argv;
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000284
285 // Schedule Lib Restart
286 PostMessage(g_hWndMain, WM_APP_RESTART, 0, 0);
287 } else {
288 /* Destroy & quit GUI, e.g: clean up window, resources */
289 PostMessage(g_hWndMain, WM_APP_DESTROY, 0, 0);
290 }
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000291}
292
293/* Called before pjsua initializing config. */
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000294void PjsuaOnConfig(pjsua_app_config *cfg)
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000295{
296 PJ_UNUSED_ARG(cfg);
297}
298
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000299void PjsuaInit()
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000300{
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000301 pjsua_app_cfg_t app_cfg;
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000302 pj_status_t status;
303
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000304 /* Destroy pjsua app first */
305 pjsua_app_destroy();
306
307 /* Init pjsua app */
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000308 pj_bzero(&app_cfg, sizeof(app_cfg));
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000309 app_cfg.argc = start_argc;
310 app_cfg.argv = start_argv;
311 app_cfg.on_started = &PjsuaOnStarted;
312 app_cfg.on_stopped = &PjsuaOnStopped;
313 app_cfg.on_config_init = &PjsuaOnConfig;
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000314
315 SetWindowText(g_hWndLbl, _T("Initializing.."));
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000316 status = pjsua_app_init(&app_cfg);
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000317 if (status != PJ_SUCCESS)
318 goto on_return;
319
320 SetWindowText(g_hWndLbl, _T("Starting.."));
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000321 status = pjsua_app_run(PJ_FALSE);
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000322 if (status != PJ_SUCCESS)
323 goto on_return;
324
325on_return:
326 if (status != PJ_SUCCESS)
327 SetWindowText(g_hWndLbl, _T("Initialization failed"));
328}
329
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000330void PjsuaDestroy()
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000331{
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000332 pjsua_app_destroy();
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000333}
334
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000335/* === MAIN === */
336
337int WINAPI WinMain(
338 HINSTANCE hInstance,
339 HINSTANCE hPrevInstance,
340 LPWSTR lpCmdLine,
341 int nShowCmd
342)
343{
344 int status;
345
346 PJ_UNUSED_ARG(hPrevInstance);
347 PJ_UNUSED_ARG(lpCmdLine);
348 PJ_UNUSED_ARG(nShowCmd);
349
350 // store the hInstance in global
351 g_hInst = hInstance;
352
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000353 // Start GUI
354 status = GuiInit();
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000355 if (status != 0)
356 goto on_return;
357
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000358 // Setup args and start pjsua
359 start_argc = pjsua_app_def_argc;
360 start_argv = (char**)pjsua_app_def_argv;
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000361 PostMessage(g_hWndMain, WM_APP_INIT, 0, 0);
362
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000363 status = GuiStart();
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000364
365on_return:
Nanang Izzuddincd9e8912013-04-23 10:59:52 +0000366 PjsuaDestroy();
367 GuiDestroy();
Nanang Izzuddinae5394d2013-04-19 10:36:11 +0000368
369 return status;
370}