diff options
Diffstat (limited to 'Plugins/jingle/libjingle_callclient.cpp')
-rw-r--r-- | Plugins/jingle/libjingle_callclient.cpp | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/Plugins/jingle/libjingle_callclient.cpp b/Plugins/jingle/libjingle_callclient.cpp new file mode 100644 index 0000000..fcafd8f --- /dev/null +++ b/Plugins/jingle/libjingle_callclient.cpp @@ -0,0 +1,281 @@ +/* + * Jingle call example + * Copyright 2004--2005, Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + +#include "commons.h" + + + + +CallClient::CallClient(DATA *aData) +{ + data = aData; + phone_client_ = NULL; + signaling = false; + needSignal = false; +} + +CallClient::~CallClient() +{ +} + +void CallClient::StartSignaling() +{ + if (!signaling && needSignal) + data->session_manager_->OnSignalingReady(); + + signaling = true; +} + +void CallClient::StopSignaling() +{ + signaling = false; + needSignal = false; +} + +void CallClient::OnSignalingReady() +{ + if (signaling) + data->session_manager_->OnSignalingReady(); + else + needSignal = true; +} + +void CallClient::OnConnect() +{ + std::string jid = ToString(data->fullJID); + cricket::InitRandom(jid.c_str(), jid.size());
+
+ phone_client_ = new cricket::PhoneSessionClient(buzz::Jid(jid), data->session_manager_);
+ phone_client_->SignalCallCreate.connect(this, &CallClient::OnCallCreate); +} + +void CallClient::OnDisconnect() +{ + if (phone_client_ != NULL) + { + delete phone_client_; + phone_client_ = NULL; + } +} + +void CallClient::OnCallCreate(cricket::Call* call) +{ + call->SignalSessionState.connect(this, &CallClient::OnSessionState); +} + +void CallClient::OnCallDestroy(cricket::Call* call) +{ +} + +#ifdef UNICODE + +static WCHAR *mir_dupToUnicode(const char *ptr)
+{
+ if (ptr == NULL)
+ return NULL;
+
+ size_t size = strlen(ptr) + 1;
+ WCHAR *tmp = (WCHAR *) mir_alloc(size * sizeof(WCHAR));
+
+ MultiByteToWideChar(CP_ACP, 0, ptr, -1, tmp, size * sizeof(WCHAR));
+
+ return tmp;
+}
+ +#endif + +void CallClient::NofifyState(cricket::Call* call, + cricket::Session* session, + int state) +{ + char id[20];
+ VOICE_CALL vc = {0};
+ vc.cbSize = sizeof(vc);
+ vc.szModule = data->jabber->protocolName;
+ vc.id = itoa(call->id(), id, 10);
+ vc.flags = VOICE_CALL_CONTACT;
+ vc.state = state;
+#ifdef UNICODE + TCHAR *jid = mir_dupToUnicode(session->remote_name().c_str()); + vc.hContact = data->jabber->pfHContactFromJID(jid);
+ mir_free(jid);
+#else
+ vc.hContact = data->jabber->pfHContactFromJID(session->remote_name().c_str());
+#endif
+ NotifyEventHooks(data->hVoiceNotify, (WPARAM) &vc, 0);
+} + +void CallClient::OnSessionState(cricket::Call* call, + cricket::Session* session, + cricket::Session::State state) +{ + if (state == cricket::Session::STATE_RECEIVEDINITIATE) { + NofifyState(call, session, VOICE_STATE_RINGING); + + } else if (state == cricket::Session::STATE_SENTINITIATE) { + NofifyState(call, session, VOICE_STATE_CALLING); + + } else if (state == cricket::Session::STATE_SENTACCEPT + || state == cricket::Session::STATE_RECEIVEDACCEPT) { + StartSignaling();
+
+ } else if (state == cricket::Session::STATE_INPROGRESS) { + NofifyState(call, session, VOICE_STATE_TALKING); +
+ } else if (state == cricket::Session::STATE_DEINIT) { + NofifyState(call, session, VOICE_STATE_ENDED); + StopSignaling();
+ } +} + +void CallClient::OnMessage(talk_base::Message *pmsg) +{ + switch(pmsg->message_id) + { + case MSG_TIMER: + { + EnterCriticalSection(&data->csPendingIqMap);
+
+ time_t expire = time(NULL) - 3;
+ for(PendingIqMap::iterator it = data->pendingIqs.begin(); it != data->pendingIqs.end(); )
+ {
+ PendingIq &piq = it->second;
+ if (piq.sent < expire)
+ {
+ buzz::XmlElement *stanza = (buzz::XmlElement *) piq.param;
+ data->session_manager_->OnFailedSend(stanza, NULL);
+ delete stanza;
+
+ it = data->pendingIqs.erase(it);
+ }
+ else
+ ++it;
+ }
+
+ LeaveCriticalSection(&data->csPendingIqMap);
+ break; + } + case MSG_REPLY_MSG: + { + ReplyMessageData *rmd = (ReplyMessageData *) pmsg->pdata; +
+ if (rmd->newStanza->Attr(buzz::QN_TYPE) == buzz::STR_RESULT) { + data->session_manager_->OnIncomingResponse(rmd->oldStanza, rmd->newStanza); + } else { + data->session_manager_->OnFailedSend(rmd->oldStanza, rmd->newStanza); + } +
+ delete rmd->oldStanza;
+ delete rmd->newStanza;
+ delete rmd;
+ + break; + } + case MSG_INCOMING_MSG: + { + buzz::XmlElement *el = (buzz::XmlElement *) pmsg->pdata; + if (el == NULL) + return; +
+ if (data->session_manager_->IsSessionMessage(el))
+ data->session_manager_->OnIncomingMessage(el);
+
+ delete el;
+ break; + } + case MSG_MAKE_CALL_TO: + { + HANDLE hContact = (HANDLE) pmsg->pdata; + if ( hContact == NULL ) + return; + + DBVARIANT dbv;
+ if (DBGetContactSettingTString(hContact, data->jabber->protocolName, "jid", &dbv))
+ return;
+
+ TCHAR jid[512];
+ _tcsncpy(jid, dbv.ptszVal, MAX_REGS(jid));
+ DBFreeVariant(&dbv); + + if (DBGetContactSettingWord(hContact, data->jabber->protocolName, "Status", ID_STATUS_OFFLINE) <= ID_STATUS_OFFLINE)
+ return;
+
+ TCHAR szJid[512];
+ const TCHAR *bestResName = data->jabber->pfGetBestClientResourceNamePtr(jid);
+ mir_sntprintf(szJid, MAX_REGS(szJid), bestResName ? _T("%s/%s") : _T("%s"), jid, bestResName);
+ + phone_client_->SignalCallDestroy.connect(this, &CallClient::OnCallDestroy); + cricket::Call * call = phone_client_->CreateCall(); + call->InitiateSession(buzz::Jid(ToString(szJid)), NULL); + phone_client_->SetFocus(call); + break; + } + case MSG_ANSWER_CALL: + { + uint32 id = (uint32) pmsg->pdata; + cricket::Call * call = phone_client_->GetCall(id);
+ if (call == NULL)
+ return;
+
+ call->AcceptSession(call->sessions()[0]); + phone_client_->SetFocus(call); + break; + } + case MSG_DROP_CALL: + { + uint32 id = (uint32) pmsg->pdata; + cricket::Call * call = phone_client_->GetCall(id);
+ if (call == NULL)
+ return;
+
+ if (call->sessions()[0]->state() == cricket::Session::STATE_RECEIVEDINITIATE
+ || call->sessions()[0]->state() == cricket::Session::STATE_RECEIVEDMODIFY)
+ call->RejectSession(call->sessions()[0]); + else + call->Terminate(); + break; + } + case TERMINATE_ALL: + {
+ data->session_manager_->TerminateAll();
+ break; + } + } +} + +void CallClient::MakeCallTo(HANDLE hContact) +{ + if ( hContact == NULL ) + return; + + data->signaling_thread_->Post(this, MSG_MAKE_CALL_TO, (talk_base::MessageData *) hContact); +} + +void CallClient::AnswerCall(int id) +{ + data->signaling_thread_->Post(this, MSG_ANSWER_CALL, (talk_base::MessageData *) id); +} + +void CallClient::DropCall(int id) +{ + data->signaling_thread_->Post(this, MSG_DROP_CALL, (talk_base::MessageData *) id); +} + |