enum gui_key gui_msgbox(const char *title, const char *message, enum gui_flag flag) { wchar_t buf_title[64]; wchar_t buf_msg[512]; UINT wflag = 0; int retcode; pj_ansi_to_unicode(title, pj_ansi_strlen(title), buf_title, 64); pj_ansi_to_unicode(message, pj_ansi_strlen(message), buf_msg, 512); switch (flag) { case WITH_OK: wflag = MB_OK; break; case WITH_YESNO: wflag = MB_YESNO; break; case WITH_OKCANCEL: wflag = MB_OKCANCEL; break; } retcode = MessageBox(g_hWndMain, buf_msg, buf_title, wflag); switch (retcode) { case IDOK: return KEY_OK; case IDYES: return KEY_YES; case IDNO: return KEY_NO; default: return KEY_CANCEL; } }
/* generate submenu and register the menu handler, then return next menu id */ static UINT generate_submenu(HMENU parent, UINT id_start, gui_menu *menu) { unsigned i; UINT id = id_start; if (!menu) return id; /* generate submenu */ for (i = 0; i < menu->submenu_cnt; ++i) { if (menu->submenus[i] == NULL) { /* add separator */ AppendMenu(parent, MF_SEPARATOR, 0, 0); } else if (menu->submenus[i]->submenu_cnt != 0) { /* this submenu item has children, generate popup menu */ HMENU hMenu; wchar_t buf[64]; pj_ansi_to_unicode(menu->submenus[i]->title, pj_ansi_strlen(menu->submenus[i]->title), buf, 64); hMenu = CreatePopupMenu(); AppendMenu(parent, MF_STRING|MF_ENABLED|MF_POPUP, (UINT)hMenu, buf); id = generate_submenu(hMenu, id, menu->submenus[i]); } else { /* this submenu item is leaf, register the handler */ wchar_t buf[64]; pj_ansi_to_unicode(menu->submenus[i]->title, pj_ansi_strlen(menu->submenus[i]->title), buf, 64); AppendMenu(parent, MF_STRING, id, buf); if (menu->submenus[i]->handler) { g_menu_handlers[g_menu_handler_cnt].id = id; g_menu_handlers[g_menu_handler_cnt].handler = menu->submenus[i]->handler; ++g_menu_handler_cnt; } ++id; } } return id; }
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 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); }
/* Logging callback */ static void log_writer(int level, const char *buf, unsigned len) { static wchar_t buf16[PJ_LOG_MAX_SIZE]; PJ_UNUSED_ARG(level); pj_ansi_to_unicode(buf, len, buf16, PJ_ARRAY_SIZE(buf16)); TPtrC16 aBuf((const TUint16*)buf16, (TInt)len); console->Write(aBuf); }
/* * Convert text to IPv4/IPv6 address. */ PJ_DEF(pj_status_t) pj_inet_pton(int af, const pj_str_t *src, void *dst) { char tempaddr[PJ_INET6_ADDRSTRLEN]; PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6, PJ_EINVAL); PJ_ASSERT_RETURN(src && src->slen && dst, PJ_EINVAL); /* Initialize output with PJ_IN_ADDR_NONE for IPv4 (to be * compatible with pj_inet_aton() */ if (af==PJ_AF_INET) { ((pj_in_addr*)dst)->s_addr = PJ_INADDR_NONE; } /* Caution: * this function might be called with cp->slen >= 46 * (i.e. when called with hostname to check if it's an IP addr). */ if (src->slen >= PJ_INET6_ADDRSTRLEN) { return PJ_ENAMETOOLONG; } pj_memcpy(tempaddr, src->ptr, src->slen); tempaddr[src->slen] = '\0'; wchar_t tempaddr16[PJ_INET6_ADDRSTRLEN]; pj_ansi_to_unicode(tempaddr, pj_ansi_strlen(tempaddr), tempaddr16, sizeof(tempaddr16)); TBuf<PJ_INET6_ADDRSTRLEN> ip_addr((const TText*)tempaddr16); TInetAddr addr; addr.Init(KAfInet6); if (addr.Input(ip_addr) == KErrNone) { if (af==PJ_AF_INET) { /* Success (Symbian IP address is in host byte order) */ pj_uint32_t ip = pj_htonl(addr.Address()); pj_memcpy(dst, &ip, 4); } else if (af==PJ_AF_INET6) { const TIp6Addr & ip6 = addr.Ip6Address(); pj_memcpy(dst, ip6.u.iAddr8, 16); } else { pj_assert(!"Unexpected!"); return PJ_EBUG; } return PJ_SUCCESS; } else { /* Error */ return PJ_EINVAL; } }
/* 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); }
/* * This function converts the Internet host address cp from the standard * numbers-and-dots notation into binary data and stores it in the structure * that inp points to. */ PJ_DEF(int) pj_inet_aton(const pj_str_t *cp, struct pj_in_addr *inp) { enum { MAXIPLEN = PJ_INET_ADDRSTRLEN }; /* Initialize output with PJ_INADDR_NONE. * Some apps relies on this instead of the return value * (and anyway the return value is quite confusing!) */ inp->s_addr = PJ_INADDR_NONE; /* Caution: * this function might be called with cp->slen >= 16 * (i.e. when called with hostname to check if it's an IP addr). */ PJ_ASSERT_RETURN(cp && cp->slen && inp, 0); if (cp->slen >= 16) { return 0; } char tempaddr8[MAXIPLEN]; pj_memcpy(tempaddr8, cp->ptr, cp->slen); tempaddr8[cp->slen] = '\0'; wchar_t tempaddr16[MAXIPLEN]; pj_ansi_to_unicode(tempaddr8, pj_ansi_strlen(tempaddr8), tempaddr16, sizeof(tempaddr16)); TBuf<MAXIPLEN> ip_addr((const TText*)tempaddr16); TInetAddr addr; addr.Init(KAfInet); if (addr.Input(ip_addr) == KErrNone) { /* Success (Symbian IP address is in host byte order) */ inp->s_addr = pj_htonl(addr.Address()); return 1; } else { /* Error */ return 0; } }
static void log_writer(int level, const char *buffer, int len) { wchar_t buf[512]; int cur_len; PJ_UNUSED_ARG(level); pj_ansi_to_unicode(buffer, len, buf, 512); if (!g_hWndLog) return; /* For now, ignore log messages from other thread to avoid deadlock */ if (g_log_thread == pj_thread_this()) { cur_len = (int)SendMessage(g_hWndLog, WM_GETTEXTLENGTH, 0, 0); SendMessage(g_hWndLog, EM_SETSEL, (WPARAM)cur_len, (LPARAM)cur_len); SendMessage(g_hWndLog, EM_REPLACESEL, (WPARAM)0, (LPARAM)buf); } //uncomment to forward to the original log writer if (g_log_writer_orig) (*g_log_writer_orig)(level, buffer, len); }
// Resolve for specific address family static pj_status_t getaddrinfo_by_af(int af, const pj_str_t *name, unsigned *count, pj_addrinfo ai[]) { unsigned i; pj_status_t status; PJ_ASSERT_RETURN(name && count && ai, PJ_EINVAL); #if !defined(PJ_HAS_IPV6) || !PJ_HAS_IPV6 if (af == PJ_AF_INET6) return PJ_EIPV6NOTSUP; #endif // Return failure if access point is marked as down by app. PJ_SYMBIAN_CHECK_CONNECTION(); // Get resolver for the specified address family RHostResolver &resv = PjSymbianOS::Instance()->GetResolver(af); // Convert name to Unicode wchar_t name16[PJ_MAX_HOSTNAME]; pj_ansi_to_unicode(name->ptr, name->slen, name16, PJ_ARRAY_SIZE(name16)); TPtrC16 data((const TUint16*)name16); // Resolve! TNameEntry nameEntry; TRequestStatus reqStatus; resv.GetByName(data, nameEntry, reqStatus); User::WaitForRequest(reqStatus); // Iterate each result i = 0; while (reqStatus == KErrNone && i < *count) { // Get the resolved TInetAddr TInetAddr inetAddr(nameEntry().iAddr); int addrlen; #if TRACE_ME if (1) { pj_sockaddr a; char ipaddr[PJ_INET6_ADDRSTRLEN+2]; int namelen; namelen = sizeof(pj_sockaddr); if (PjSymbianOS::Addr2pj(inetAddr, a, &namelen, PJ_FALSE) == PJ_SUCCESS) { PJ_LOG(5,(THIS_FILE, "resolve %.*s: %s", (int)name->slen, name->ptr, pj_sockaddr_print(&a, ipaddr, sizeof(ipaddr), 2))); } } #endif // Ignore if this is not the same address family // Not a good idea, as Symbian mapps IPv4 to IPv6. //fam = inetAddr.Family(); //if (fam != af) { // resv.Next(nameEntry, reqStatus); // User::WaitForRequest(reqStatus); // continue; //} // Convert IP address first to get IPv4 mapped address addrlen = sizeof(ai[i].ai_addr); status = PjSymbianOS::Addr2pj(inetAddr, ai[i].ai_addr, &addrlen, PJ_TRUE); if (status != PJ_SUCCESS) return status; // Ignore if address family doesn't match if (ai[i].ai_addr.addr.sa_family != af) { resv.Next(nameEntry, reqStatus); User::WaitForRequest(reqStatus); continue; } // Convert the official address to ANSI. pj_unicode_to_ansi((const wchar_t*)nameEntry().iName.Ptr(), nameEntry().iName.Length(), ai[i].ai_canonname, sizeof(ai[i].ai_canonname)); // Next ++i; resv.Next(nameEntry, reqStatus); User::WaitForRequest(reqStatus); } *count = i; return PJ_SUCCESS; }