From 4ffd0909f7990643a0253849d46a750bd9f3233b Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Sun, 22 Feb 2015 21:14:05 +0000 Subject: Tox: some code for group chats git-svn-id: http://svn.miranda-ng.org/main/trunk@12241 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Tox/src/tox_chatrooms.cpp | 332 ++++++++++++++++++++++++++++++++++++ 1 file changed, 332 insertions(+) create mode 100644 protocols/Tox/src/tox_chatrooms.cpp (limited to 'protocols/Tox/src/tox_chatrooms.cpp') diff --git a/protocols/Tox/src/tox_chatrooms.cpp b/protocols/Tox/src/tox_chatrooms.cpp new file mode 100644 index 0000000000..684cac1246 --- /dev/null +++ b/protocols/Tox/src/tox_chatrooms.cpp @@ -0,0 +1,332 @@ +#include "common.h" + +MCONTACT CToxProto::GetChatRoom(int groupNumber) +{ + MCONTACT hContact = NULL; + for (hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) + { + if (!isChatRoom(hContact)) + { + continue; + } + int chatRoumNumber = getWord(hContact, TOX_SETTINGS_CHAT_ID, TOX_ERROR); + if (groupNumber == chatRoumNumber) + { + break; + } + } + return hContact; +} + +MCONTACT CToxProto::AddChatRoom(int groupNumber) +{ + MCONTACT hContact = GetChatRoom(groupNumber); + if (!hContact) + { + hContact = (MCONTACT)CallService(MS_DB_CONTACT_ADD, 0, 0); + CallService(MS_PROTO_ADDTOCONTACT, hContact, (LPARAM)m_szModuleName); + + setWord(hContact, TOX_SETTINGS_CHAT_ID, groupNumber); + + TCHAR title[MAX_PATH]; + mir_sntprintf(title, SIZEOF(title), _T("%s #%d"), TranslateT("Groupchat"), groupNumber); + setTString(hContact, "Nick", title); + + DBVARIANT dbv; + if (!db_get_s(NULL, "Chat", "AddToGroup", &dbv, DBVT_TCHAR)) + { + db_set_ts(hContact, "CList", "Group", dbv.ptszVal); + db_free(&dbv); + } + + setByte(hContact, "ChatRoom", 1); + } + return hContact; +} + +void CToxProto::LoadChatRoomList(void*) +{ + uint32_t count = tox_count_chatlist(tox); + if (count == 0) + { + debugLogA("CToxProto::LoadGroupChatList: your group chat list is empty"); + return; + } + int32_t *groupChats = (int32_t*)mir_alloc(count * sizeof(int32_t)); + tox_get_chatlist(tox, groupChats, count); + for (uint32_t i = 0; i < count; i++) + { + int32_t groupNumber = groupChats[i]; + int type = tox_group_get_type(tox, groupNumber); + if (type == TOX_GROUPCHAT_TYPE_AV) + { + continue; + } + MCONTACT hContact = AddChatRoom(groupNumber); + if (hContact) + { + uint8_t title[TOX_MAX_NAME_LENGTH] = { 0 }; + tox_group_get_title(tox, groupNumber, title, TOX_MAX_NAME_LENGTH); + setWString(hContact, "Nick", ptrT(mir_utf8decodeT((char*)title))); + } + } + mir_free(groupChats); +} + +int CToxProto::OnGroupChatEventHook(WPARAM, LPARAM lParam) +{ + GCHOOK *gch = (GCHOOK*)lParam; + if (!gch) + { + return 1; + } + else if (strcmp(gch->pDest->pszModule, this->m_szModuleName) != 0) + { + return 0; + } + return 0; +} + +int CToxProto::OnGroupChatMenuHook(WPARAM, LPARAM lParam) +{ + GCMENUITEMS *gcmi = (GCMENUITEMS*)lParam; + if (stricmp(gcmi->pszModule, this->m_szModuleName) != 0) + { + return 0; + } + return 0; +} + +INT_PTR CToxProto::OnJoinChatRoom(WPARAM hContact, LPARAM) +{ + if (hContact) + { + } + return 0; +} + +INT_PTR CToxProto::OnLeaveChatRoom(WPARAM hContact, LPARAM) +{ + if (hContact) + { + } + return 0; +} + +INT_PTR CToxProto::OnCreateChatRoom(WPARAM, LPARAM) +{ + if (!IsToxCoreInited()) + { + return 1; + } + int groupNumber = tox_add_groupchat(tox); + if (groupNumber == TOX_ERROR) + { + return 1; + } + MCONTACT hContact = AddChatRoom(groupNumber); + if (!hContact) + { + return 1; + } + return 0; +} + +void CToxProto::InitGroupChatModule() +{ + GCREGISTER gcr = { sizeof(gcr) }; + gcr.iMaxText = 0; + gcr.ptszDispName = this->m_tszUserName; + gcr.pszModule = this->m_szModuleName; + CallServiceSync(MS_GC_REGISTER, 0, (LPARAM)&gcr); + + HookProtoEvent(ME_GC_EVENT, &CToxProto::OnGroupChatEventHook); + HookProtoEvent(ME_GC_BUILDMENU, &CToxProto::OnGroupChatMenuHook); +} + +void CToxProto::CloseAllChatChatSessions() +{ + GC_INFO gci = { 0 }; + gci.Flags = GCF_BYINDEX | GCF_ID | GCF_DATA; + gci.pszModule = m_szModuleName; + + int count = CallServiceSync(MS_GC_GETSESSIONCOUNT, 0, (LPARAM)m_szModuleName); + for (int i = 0; i < count; i++) + { + gci.iItem = i; + if (!CallServiceSync(MS_GC_GETINFO, 0, (LPARAM)&gci)) + { + GCDEST gcd = { m_szModuleName, gci.pszID, GC_EVENT_CONTROL }; + GCEVENT gce = { sizeof(gce), &gcd }; + CallServiceSync(MS_GC_EVENT, SESSION_OFFLINE, (LPARAM)&gce); + CallServiceSync(MS_GC_EVENT, SESSION_TERMINATE, (LPARAM)&gce); + } + } +} + +void CToxProto::OnGroupChatInvite(Tox *tox, int32_t friendNumber, uint8_t type, const uint8_t *data, uint16_t length, void *arg) +{ + CToxProto *proto = (CToxProto*)arg; + + if (type == TOX_GROUPCHAT_TYPE_AV) + { + proto->debugLogA("CToxProto::OnGroupChatInvite: audio chat is not supported yet"); + return; + } + + int groupNumber = tox_join_groupchat(tox, friendNumber, data, length); + if (groupNumber == TOX_ERROR) + { + proto->debugLogA("CToxProto::OnFriendRequest: failed to join to group chat"); + return; + } + + MCONTACT hContact = proto->AddChatRoom(groupNumber); + if (!hContact) + { + proto->debugLogA("CToxProto::OnFriendRequest: failed to create group chat"); + } +} + +void CToxProto::ChatValidateContact(HWND hwndList, const std::vector &contacts, MCONTACT hContact) +{ + //if (mir_strcmpi(GetContactProto(hContact), m_szModuleName) == 0 && !isChatRoom(hContact)) + { + if (std::find(contacts.begin(), contacts.end(), hContact) != contacts.end()) + { + SendMessage(hwndList, CLM_DELETEITEM, (WPARAM)hContact, 0); + } + return; + } + SendMessage(hwndList, CLM_DELETEITEM, (WPARAM)hContact, 0); +} + +void CToxProto::ChatPrepare(HWND hwndList, const std::vector &contacts, MCONTACT hContact) +{ + if (hContact == NULL) + { + hContact = (MCONTACT)::SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_ROOT, 0); + } + while (hContact) + { + if (IsHContactGroup(hContact)) + { + MCONTACT hSubContact = (MCONTACT)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hContact); + if (hSubContact) + { + ChatPrepare(hwndList, contacts, hSubContact); + } + } + else if (IsHContactContact(hContact)) + { + ChatValidateContact(hwndList, contacts, hContact); + } + hContact = (MCONTACT)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXT, (LPARAM)hContact); + } +} + +std::vector CToxProto::GetInvitedContacts(HWND hwndList, MCONTACT hContact) +{ + std::vector contacts; + if (hContact == NULL) + { + hContact = (MCONTACT)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_ROOT, 0); + } + while (hContact) + { + if (IsHContactGroup(hContact)) + { + MCONTACT hSubContact = (MCONTACT)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hContact); + if (hSubContact) + { + std::vector subContacts = GetInvitedContacts(hwndList, hSubContact); + contacts.insert(contacts.end(), subContacts.begin(), subContacts.end()); + } + } + else + { + int cheked = SendMessage(hwndList, CLM_GETCHECKMARK, (WPARAM)hContact, 0); + if (cheked) + { + contacts.push_back(hContact); + } + } + hContact = (MCONTACT)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXT, (LPARAM)hContact); + } + return contacts; +} + +INT_PTR CALLBACK CToxProto::ChatRoomInviteProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HWND hwndList = GetDlgItem(hwndDlg, IDC_CCLIST); + CToxProto *proto = (CToxProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + { + proto = (CToxProto*)lParam; + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); + { + HWND hwndClist = GetDlgItem(hwndDlg, IDC_CCLIST); + SetWindowLongPtr(hwndClist, GWL_STYLE, GetWindowLongPtr(hwndClist, GWL_STYLE) & ~CLS_HIDEOFFLINE); + } + } + break; + + case WM_CLOSE: + EndDialog(hwndDlg, 0); + break; + + case WM_NOTIFY: + { + NMCLISTCONTROL *nmc = (NMCLISTCONTROL*)lParam; + if (nmc->hdr.idFrom == IDC_CCLIST) + { + switch (nmc->hdr.code) + { + case CLN_NEWCONTACT: + if ((nmc->flags & (CLNF_ISGROUP | CLNF_ISINFO)) == 0) + { + std::vector invitedContacts; + proto->ChatValidateContact(nmc->hdr.hwndFrom, invitedContacts, (MCONTACT)nmc->hItem); + } + break; + + case CLN_LISTREBUILT: + { + std::vector invitedContacts; + proto->ChatPrepare(nmc->hdr.hwndFrom, invitedContacts); + } + break; + } + } + } + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDOK: + { + std::vector invitedContacts = GetInvitedContacts(hwndList); + if (invitedContacts.empty()) + { + proto->ShowNotification(TranslateT("You did not select any contact")); + } + else + { + //SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); + EndDialog(hwndDlg, IDOK); + } + } + break; + + case IDCANCEL: + EndDialog(hwndDlg, IDCANCEL); + break; + } + break; + } + return FALSE; +} -- cgit v1.2.3