summaryrefslogtreecommitdiff
path: root/Plugins/jingle/libjingle_callclient.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Plugins/jingle/libjingle_callclient.cpp')
-rw-r--r--Plugins/jingle/libjingle_callclient.cpp281
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);
+}
+