// // File: // // Written by: David M. Stanhope [voip@fobbit.com] // // Fobbit Phone Windows Wrapper // // this is used just to build and test the gui // #define TESTING 1 #ifndef TESTING #include "vblast.h" static FILE *_log_fp = NULL ; static char *_log_name = "vb.log"; #else // TESTING #include #define TXT_BUF_SIZE 512 #define sprintf wsprintf #define vsprintf wvsprintf #define VERSION_MAJOR 9 #define VERSION_MINOR 99 #define VERSION_DATE "TESTING" #endif // TESTING #include "resource.h" #include "direct.h" #define BIG_TXT_BUF_SIZE (TXT_BUF_SIZE * 4) LRESULT APIENTRY WndProc(HWND, UINT, WPARAM, LPARAM); void Init(HINSTANCE); // ---------------------------------------------------------------------------- #define ID_LOCAL 1 #define ID_REMOTE 2 #define ID_STATUS 3 #define ID_ABOUT 4 #define ID_EXIT 5 #define ID_LOG 6 #define ID_KEY_0 7 #define ID_KEY_1 8 #define ID_KEY_2 9 #define ID_KEY_3 10 #define ID_KEY_4 11 #define ID_KEY_5 12 #define ID_KEY_6 13 #define ID_KEY_7 14 #define ID_KEY_8 15 #define ID_KEY_9 16 #define ID_KEY_STAR 17 #define ID_KEY_POUND 18 #define ID_HOOK_OFF 19 #define ID_HOOK_ON 20 #define ID_VOL_UP 21 #define ID_VOL_DN 22 #define ID_MUTE_ON 23 #define ID_MUTE_OFF 24 HINSTANCE g_hInst ; HWND w_main ; // main window HWND w_local ; HWND w_remote; HWND w_status; HWND w_log ; #define W_BORDER 5 // width of border #define W_SCROLLBAR 5 // width of scrollbar #define W_BUTTONS 124 // width of buttons (text area ) #define H_BUTTONS 28 // height of buttons (text area ) #define W_KEYS 45 // width of buttons (text area ) #define H_KEYS 18 // height of buttons (text area ) #define W_LOG 660 // width of log window #define H_LOG 300 // height of log window #define H_LOCAL 180 // height of the id windows #define X_LOCAL W_BORDER #define Y_LOCAL ((W_BORDER * 4) + (H_KEYS * 4) + W_BORDER) #define W_LOCAL ((W_LOG / 2) - 3) // FUDGE? #define X_REMOTE (W_BORDER + W_LOCAL + W_BORDER) #define Y_REMOTE Y_LOCAL #define W_REMOTE W_LOCAL #define H_REMOTE H_LOCAL #define X_LOG W_BORDER // position #define Y_LOG (Y_LOCAL + H_LOCAL + W_BORDER) // position #define W_MAIN (W_BORDER + W_LOG + W_SCROLLBAR + W_BORDER) #define H_MAIN (Y_LOG + H_LOG + W_BORDER + 16) // FUDGE? #define X_KEY_3 (W_MAIN - (W_BORDER + W_KEYS + 5)) // FUDGE? #define Y_KEY_3 W_BORDER #define W_KEY_3 W_KEYS #define H_KEY_3 H_KEYS #define X_KEY_2 (X_KEY_3 - (W_BORDER + W_KEYS)) #define Y_KEY_2 W_BORDER #define W_KEY_2 W_KEYS #define H_KEY_2 H_KEYS #define X_KEY_1 (X_KEY_2 - (W_BORDER + W_KEYS)) #define Y_KEY_1 W_BORDER #define W_KEY_1 W_KEYS #define H_KEY_1 H_KEYS #define X_KEY_6 X_KEY_3 #define Y_KEY_6 ((W_BORDER * 2) + H_KEYS) #define W_KEY_6 W_KEYS #define H_KEY_6 H_KEYS #define X_KEY_5 X_KEY_2 #define Y_KEY_5 Y_KEY_6 #define W_KEY_5 W_KEYS #define H_KEY_5 H_KEYS #define X_KEY_4 X_KEY_1 #define Y_KEY_4 Y_KEY_6 #define W_KEY_4 W_KEYS #define H_KEY_4 H_KEYS #define X_KEY_9 X_KEY_3 #define Y_KEY_9 ((W_BORDER * 3) + (H_KEYS * 2)) #define W_KEY_9 W_KEYS #define H_KEY_9 H_KEYS #define X_KEY_8 X_KEY_2 #define Y_KEY_8 Y_KEY_9 #define W_KEY_8 W_KEYS #define H_KEY_8 H_KEYS #define X_KEY_7 X_KEY_1 #define Y_KEY_7 Y_KEY_9 #define W_KEY_7 W_KEYS #define H_KEY_7 H_KEYS #define X_KEY_POUND X_KEY_3 #define Y_KEY_POUND ((W_BORDER * 4) + (H_KEYS * 3)) #define W_KEY_POUND W_KEYS #define H_KEY_POUND H_KEYS #define X_KEY_0 X_KEY_2 #define Y_KEY_0 Y_KEY_POUND #define W_KEY_0 W_KEYS #define H_KEY_0 H_KEYS #define X_KEY_STAR X_KEY_1 #define Y_KEY_STAR Y_KEY_POUND #define W_KEY_STAR W_KEYS #define H_KEY_STAR H_KEYS #define X_ABOUT W_BORDER #define Y_ABOUT ((W_BORDER + H_BUTTONS) - 1) // FUDGE #define W_ABOUT W_BUTTONS #define H_ABOUT H_BUTTONS #define X_EXIT W_BORDER #define Y_EXIT ((W_BORDER * 2) + (H_BUTTONS * 2) - 2) // FUDGE #define W_EXIT W_BUTTONS #define H_EXIT H_BUTTONS #define X_STATUS W_BORDER #define Y_STATUS W_BORDER #define W_STATUS (X_KEY_1 - (W_BORDER * 2)) #define H_STATUS (H_BUTTONS - 6) #define X_MUTE_ON ((W_BORDER * 2) + W_BUTTONS) #define Y_MUTE_ON Y_ABOUT #define W_MUTE_ON W_BUTTONS #define H_MUTE_ON H_BUTTONS #define X_MUTE_OFF X_MUTE_ON #define Y_MUTE_OFF Y_EXIT #define W_MUTE_OFF W_BUTTONS #define H_MUTE_OFF H_BUTTONS #define X_VOL_UP ((W_BORDER * 3) + (W_BUTTONS * 2)) #define Y_VOL_UP Y_ABOUT #define W_VOL_UP W_BUTTONS #define H_VOL_UP H_BUTTONS #define X_VOL_DN X_VOL_UP #define Y_VOL_DN Y_EXIT #define W_VOL_DN W_BUTTONS #define H_VOL_DN H_BUTTONS #define X_HOOK_ON ((W_BORDER * 4) + (W_BUTTONS * 3)) #define Y_HOOK_ON Y_ABOUT #define W_HOOK_ON W_BUTTONS #define H_HOOK_ON H_BUTTONS #define X_HOOK_OFF X_HOOK_ON #define Y_HOOK_OFF Y_EXIT #define W_HOOK_OFF W_BUTTONS #define H_HOOK_OFF H_BUTTONS // ---------------------------------------------------------------------------- void do_exit(void) { SendMessage(w_main, WM_CLOSE, 0, 0); while(1) { ; } } void x_exit(int x) { MessageBox(w_main, "Aborting Fobbit Phone\n" "Check the log window for the reason", "Fatal Error", MB_OK | MB_ICONSTOP); do_exit(); } // ---------------------------------------------------------------------------- HWND create_listbox(HWND parent, int x, int y, int width, int height, int id) { return CreateWindow("ListBox", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | LBS_DISABLENOSCROLL | LBS_HASSTRINGS | LBS_NOSEL | LBS_NOTIFY, x, y, width, height, parent, (HMENU) id, g_hInst, 0); } HWND create_button(HWND parent, int x, int y, int width, int height, int id, char *value) { return CreateWindow("Button", value, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, x, y, width, height, parent, (HMENU) id, g_hInst, 0); } HWND create_static(HWND parent, int x, int y, int width, int height, int id, char *value) { return CreateWindow("Static", value, WS_CHILD | WS_VISIBLE | WS_BORDER, x, y, width, height, parent, (HMENU) id, g_hInst, 0); } // ---------------------------------------------------------------------------- static HWND find_window(char *name) { int n; char nbuf[128]; HWND h = GetTopWindow(NULL); while(h) { if((n = GetWindowText(h, nbuf, 127)) < 0) { ERR(("GetWindowText() Failed\n")) return 0; } if(n) { nbuf[n] = '\0'; if(strcmp(nbuf, name) == 0) break; } h = GetNextWindow(h, GW_HWNDNEXT); } return h; } // ---------------------------------------------------------------------------- #include static void add_log1(char *s) { static int have = 0; while(have >= 1000) { SendMessage(w_log, LB_DELETESTRING, 0, 0); have--; } SendMessage(w_log, LB_ADDSTRING , 0, (LPARAM) (LPCSTR) s); SendMessage(w_log, LB_SETTOPINDEX, have, 0); have++; } static void put_status(char *s) { // 'SetWindowText' might work here (no tab expansion, so may not?) SendMessage(w_status, WM_SETTEXT, 0, (LPARAM) (LPCSTR) s); } static void add_log(char *s, int flag) { char *d, buf[TXT_BUF_SIZE]; int c, n; if(_log_fp) { fputs(s, _log_fp); fflush(_log_fp); } d = buf + 1; n = 0; while(1) { c = *s++; if((c == '\n') || (c == '\r') || (c == '\0')) { if(n > 0) { *d++ = '\0'; add_log1(buf + 1); if(flag) { buf[0] = ' '; put_status(buf); } } if(c == '\0') break; d = buf + 1; n = 0; } else { *d++ = c; n++; } } } void logger(char *fmt, ...) { char buf[BIG_TXT_BUF_SIZE]; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); va_end(ap); add_log(buf, 0); } void progress(char *fmt, ...) { char buf[TXT_BUF_SIZE]; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); va_end(ap); add_log(buf, 1); } #define ID_FMT " %s%s\n" \ " Serial-Number\t: %s\n" \ " IP\t\t: %s\n" \ " Port\t\t: %s\n" \ " Name\t\t: %s\n" \ " Location\t: %s\n" \ " Email\t\t: %s\n" \ " Flags\t\t: %s\n" \ " Version\t: %s\n" \ " OS\t\t: %s\n" \ " Last Registered\t: %s" void build_empty_info(char *dst, char *type) { sprintf(dst, ID_FMT, type, "", // subtype "", // SN "", // IP "", // PORT "", // NAME "", // LOC "", // EMAIL "", // FLAGS "", // VERSION "", // OS ""); // REG } #ifndef TESTING // only thing that changes is the 'last registered time' void update_local(long t) { char buf[BIG_TXT_BUF_SIZE], s_port[16], s_flags[16], s_version[16]; sprintf(s_port , "%d" , ntohs(public_ip_and_port_tcp.sin_port)); sprintf(s_flags , "%d" , can_accept_inbound ); sprintf(s_version, "%d.%d", VERSION_MAJOR, VERSION_MINOR ); sprintf(buf, ID_FMT, "Local", "", serial_number_string , inet_ntoa(public_ip_and_port_tcp.sin_addr), s_port , public_name , public_location , public_email , s_flags , s_version , os_name() , (t == 0) ? "" : time_string_time_t(t)); SendMessage(w_local, WM_SETTEXT, 0, (LPARAM) (LPCSTR) buf); } void update_remote(char *sub_type, char *serial_number , char *listen_ip , char *listen_port , char *remote_name , char *remote_location, char *remote_email , char *remote_flags , char *remote_version , char *remote_os , char *received ) { char buf[BIG_TXT_BUF_SIZE]; sprintf(buf, ID_FMT, "Local", sub_type , serial_number , listen_ip , listen_port , remote_name , remote_location, remote_email , remote_flags , remote_version , remote_os , (received == NULL) ? "" : time_string_str(received)); SendMessage(w_remote, WM_SETTEXT, 0, (LPARAM) (LPCSTR) buf); } void clear_remote(void) { char buf[BIG_TXT_BUF_SIZE]; build_empty_info(buf, "Remote"); SendMessage(w_remote, WM_SETTEXT, 0, (LPARAM) (LPCSTR) buf); } #endif // TESTING void update_status(int tt, int tu, int rt, int ru, int dropped, int mq, int queued) { char buf[TXT_BUF_SIZE]; sprintf(buf, " TCP/UDP TX %d/%d RX %d/%d Dropped %d Queued %d/%d", tt, tu, rt, ru, dropped, mq, queued); put_status(buf); } // ---------------------------------------------------------------------------- #define P(x) X_##x, Y_##x, W_##x, H_##x, ID_##x // build main window void create_top_level_window(HWND w) { #ifdef TESTING int i; #endif char s_local[BIG_TXT_BUF_SIZE], s_remote[BIG_TXT_BUF_SIZE]; // build initial displays build_empty_info(s_local , "Local" ); build_empty_info(s_remote, "Remote"); w_status = create_static (w, P(STATUS ), " Initializing" ); w_local = create_static (w, P(LOCAL ), s_local ); w_remote = create_static (w, P(REMOTE ), s_remote ); w_log = create_listbox(w, P(LOG ) ); create_button (w, P(ABOUT ), "About" ); create_button (w, P(EXIT ), "Exit" ); create_button (w, P(KEY_1 ), "1" ); create_button (w, P(KEY_2 ), "2" ); create_button (w, P(KEY_3 ), "3" ); create_button (w, P(KEY_4 ), "4" ); create_button (w, P(KEY_5 ), "5" ); create_button (w, P(KEY_6 ), "6" ); create_button (w, P(KEY_7 ), "7" ); create_button (w, P(KEY_8 ), "8" ); create_button (w, P(KEY_9 ), "9" ); create_button (w, P(KEY_0 ), "0" ); create_button (w, P(KEY_STAR ), "*" ); create_button (w, P(KEY_POUND), "#" ); create_button (w, P(HOOK_OFF ), "Headset OffHook"); create_button (w, P(HOOK_ON ), "Headset Hangup" ); create_button (w, P(VOL_UP ), "Volume-Up" ); create_button (w, P(VOL_DN ), "Volume-Down" ); create_button (w, P(MUTE_ON ), "Mute-On" ); create_button (w, P(MUTE_OFF ), "Mute-Off" ); // use fixed width Font here since don't want to re-format all the messages SendMessage(w_log, WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), MAKELPARAM(TRUE, 0)); #ifdef TESTING for(i = 0; i < 500; i++) { sprintf(s_local, "LINE-%d", i); logger(s_local); } logger("0123456789012345678901234567890123456789" "012345678901234567890123456789012345678*"); #endif } // ---------------------------------------------------------------------------- static char vb_title[32]; #define VB_TITLE_FMT "VBWIN:%d - Fobbit Phone" #define VB_TITLE_OLD "VBWIN - Fobbit Phone" #define VB_TITLE_STARTUP "START - Fobbit Phone" void check_not_running(int device_index) { char tbuf[64]; int found = 0; sprintf(tbuf, VB_TITLE_FMT, device_index); if(find_window(VB_TITLE_OLD) != 0) { MSG(("Found Window (%s)\n", VB_TITLE_OLD)) found = 1; } else if(find_window(tbuf) != 0) { MSG(("Found Window (%s)\n", tbuf)) found = 1; } if(found) { sprintf(tbuf, "Fobbit Phone (%d) Already Running", device_index); MessageBox(w_main, tbuf, "Aborting", MB_OK | MB_ICONSTOP); do_exit(); } strcpy(vb_title, tbuf); SetWindowText(w_main, vb_title); } static void call_main(void) { #ifndef TESTING x_main(0, NULL, NULL); #else check_not_running(0); #endif } // application entry point int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR line, int CmdShow) { MSG msg; strcpy(vb_title, VB_TITLE_STARTUP); g_hInst = hInst; Init(hInst); #ifndef TESTING _log_fp = fopen(_log_name, "a"); #endif _beginthread((void *) call_main, 0, NULL); while(GetMessage(&msg,0,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } // initlize application void Init(HINSTANCE hInst) { WNDCLASS wc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH); wc.hInstance = hInst; wc.hIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDI_ICON1)); wc.hCursor = LoadCursor(NULL,IDC_ARROW); wc.lpfnWndProc = (WNDPROC) WndProc; wc.lpszClassName = "PPhone"; wc.lpszMenuName = 0; wc.style = CS_HREDRAW | CS_VREDRAW; RegisterClass(&wc); // // leave off WS_THICKFRAME and WS_MAXIMIZEBOX so can't change the // windows size, since for now not ready to handle that // w_main = CreateWindow("PPhone", vb_title, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, W_MAIN, H_MAIN, 0, 0, hInst, 0); ShowWindow(w_main, SW_SHOW); UpdateWindow(w_main); } // main window callback function LRESULT APIENTRY WndProc(HWND w, UINT msg, WPARAM wParam, LPARAM lParam) { char buf[TXT_BUF_SIZE]; switch(msg) { case WM_DESTROY: PostQuitMessage(0); break; case WM_CREATE: create_top_level_window(w); break; case WM_COMMAND: { switch(HIWORD(wParam)) { case BN_CLICKED: switch(LOWORD(wParam)) { case ID_ABOUT: sprintf(buf, "%s\n" "Version %d.%d, %s\n" "Written By: David M. Stanhope\n" "Send Questions/Comments to:\n" " voip@fobbit.com", vb_title, VERSION_MAJOR, VERSION_MINOR, VERSION_DATE); MessageBox(w, buf, "About", MB_OK | MB_ICONINFORMATION); break; case ID_EXIT: if(MessageBox(w, "About to Shutdown Fobbit Phone", "Exit", MB_OKCANCEL | MB_ICONQUESTION) == IDOK) { SendMessage(w, WM_CLOSE, 0, 0); } break; case ID_KEY_0 : keyboard_send('0'); break; case ID_KEY_1 : keyboard_send('1'); break; case ID_KEY_2 : keyboard_send('2'); break; case ID_KEY_3 : keyboard_send('3'); break; case ID_KEY_4 : keyboard_send('4'); break; case ID_KEY_5 : keyboard_send('5'); break; case ID_KEY_6 : keyboard_send('6'); break; case ID_KEY_7 : keyboard_send('7'); break; case ID_KEY_8 : keyboard_send('8'); break; case ID_KEY_9 : keyboard_send('9'); break; case ID_KEY_STAR : keyboard_send('*'); break; case ID_KEY_POUND: keyboard_send('#'); break; case ID_MUTE_ON : keyboard_send('M'); break; case ID_MUTE_OFF : keyboard_send('U'); break; case ID_HOOK_ON : keyboard_send('H'); break; case ID_HOOK_OFF : keyboard_send('O'); break; case ID_VOL_UP : keyboard_send('+'); break; case ID_VOL_DN : keyboard_send('-'); break; } SetFocus(w_main); // keep keyboard focus in main window break; case LBN_SETFOCUS: // don't let log window get keyboard focus if(LOWORD(wParam) == ID_LOG) { SetFocus(w_main); // keep keyboard focus in main window } break; } return DefWindowProc(w, msg, wParam, lParam); } case WM_CHAR: { MSG1(("CHAR(%lx,%lx)\n", (long) wParam, (long) lParam)) keyboard_send(wParam); return DefWindowProc(w, msg, wParam, lParam); } default: { return DefWindowProc(w, msg, wParam, lParam); } } return 0; } // // The End! //