main_wm.c 9.8 KB

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