1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/* 2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle 3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2004--2005, Google Inc. 4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without 6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met: 7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 1. Redistributions of source code must retain the above copyright notice, 9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer. 10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 2. Redistributions in binary form must reproduce the above copyright notice, 11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer in the documentation 12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * and/or other materials provided with the distribution. 13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 3. The name of the author may not be used to endorse or promote products 14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * derived from this software without specific prior written permission. 15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */ 27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 28f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/examples/call/callclient.h" 29f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <string> 31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "talk/base/basicpacketsocketfactory.h" 33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/helpers.h" 34dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "talk/base/logging.h" 35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/network.h" 36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/socketaddress.h" 374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "talk/base/stringencode.h" 38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "talk/base/stringutils.h" 39dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "talk/base/thread.h" 40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/examples/call/console.h" 41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/examples/call/presencepushtask.h" 42f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/examples/call/presenceouttask.h" 43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/examples/call/mucinviterecvtask.h" 44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/examples/call/mucinvitesendtask.h" 45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/examples/call/friendinvitesendtask.h" 46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/examples/call/muc.h" 47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/examples/call/voicemailjidrequester.h" 48dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "talk/p2p/base/sessionmanager.h" 49dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "talk/p2p/client/basicportallocator.h" 50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "talk/p2p/client/sessionmanagertask.h" 51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "talk/session/phone/devicemanager.h" 52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "talk/session/phone/mediaengine.h" 53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "talk/session/phone/mediasessionclient.h" 54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "talk/xmpp/constants.h" 55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 57f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochclass NullRenderer : public cricket::VideoRenderer { 58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch public: 59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch explicit NullRenderer(const char* s) : s_(s) {} 60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch private: 61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch bool SetSize(int width, int height, int reserved) { 62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_INFO) << "Video size for " << s_ << ": " << width << "x" << height; 63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch bool RenderFrame(const cricket::VideoFrame *frame) { 66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const char* s_; 69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}; 70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace { 72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst char* DescribeStatus(buzz::Status::Show show, const std::string& desc) { 74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch switch (show) { 75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::Status::SHOW_XA: return desc.c_str(); 76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::Status::SHOW_ONLINE: return "online"; 77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::Status::SHOW_AWAY: return "away"; 78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::Status::SHOW_DND: return "do not disturb"; 79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::Status::SHOW_CHAT: return "ready to chat"; 80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch default: return "offline"; 81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochstd::string GetWord(const std::vector<std::string>& words, 854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch size_t index, const std::string& def) { 864a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (words.size() > index) { 874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return words[index]; 884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else { 894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return def; 904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochint GetInt(const std::vector<std::string>& words, size_t index, int def) { 944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch int val; 954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (words.size() > index && talk_base::FromString(words[index], &val)) { 964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return val; 974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else { 984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return def; 994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 1004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 1014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} // namespace 104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst char* CALL_COMMANDS = 106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch"Available commands:\n" 107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch"\n" 108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch" hangup Ends the call.\n" 109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch" mute Stops sending voice.\n" 110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch" unmute Re-starts sending voice.\n" 111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch" dtmf Sends a DTMF tone.\n" 112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch" quit Quits the application.\n" 113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch""; 114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst char* RECEIVE_COMMANDS = 116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch"Available commands:\n" 117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch"\n" 1184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch" accept [bw] Accepts the incoming call and switches to it.\n" 119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch" reject Rejects the incoming call and stays with the current call.\n" 120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch" quit Quits the application.\n" 121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch""; 122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst char* CONSOLE_COMMANDS = 124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch"Available commands:\n" 125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch"\n" 126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch" roster Prints the online friends from your roster.\n" 127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch" friend user Request to add a user to your roster.\n" 1284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch" call [jid] [bw] Initiates a call to the user[/room] with the\n" 1294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch" given JID and with optional bandwidth.\n" 1304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch" vcall [jid] [bw] Initiates a video call to the user[/room] with\n" 1314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch" the given JID and with optional bandwidth.\n" 132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch" voicemail [jid] Leave a voicemail for the user with the given JID.\n" 133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch" join [room] Joins a multi-user-chat.\n" 134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch" invite user [room] Invites a friend to a multi-user-chat.\n" 135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch" leave [room] Leaves a multi-user-chat.\n" 136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch" getdevs Prints the available media devices.\n" 137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch" quit Quits the application.\n" 138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch""; 139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::ParseLine(const std::string& line) { 141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::vector<std::string> words; 142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int start = -1; 143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int state = 0; 144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (int index = 0; index <= static_cast<int>(line.size()); ++index) { 145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (state == 0) { 146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!isspace(line[index])) { 147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch start = index; 148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch state = 1; 149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT(state == 1); 1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT(start >= 0); 153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (isspace(line[index])) { 154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::string word(line, start, index - start); 155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch words.push_back(word); 156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch start = -1; 157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch state = 0; 158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Global commands 1634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const std::string& command = GetWord(words, 0, ""); 1644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (command == "quit") { 165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Quit(); 166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (call_ && incoming_call_) { 1674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (command == "accept") { 1684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch cricket::CallOptions options; 1694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch options.video_bandwidth = GetInt(words, 1, cricket::kAutoBandwidth); 1704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch Accept(options); 1714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else if (command == "reject") { 172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Reject(); 173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Print(RECEIVE_COMMANDS); 175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (call_) { 1774a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (command == "hangup") { 178731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO: do more shutdown here, move to Terminate() 179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch call_->Terminate(); 180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch call_ = NULL; 181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch session_ = NULL; 182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->SetPrompt(NULL); 1834a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else if (command == "mute") { 184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch call_->Mute(true); 1854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else if (command == "unmute") { 186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch call_->Mute(false); 1874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else if ((command == "dtmf") && (words.size() == 2)) { 188731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int ev = std::string("0123456789*#").find(words[1][0]); 189731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick call_->PressDTMF(ev); 190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Print(CALL_COMMANDS); 192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 1944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (command == "roster") { 195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch PrintRoster(); 1964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else if (command == "send") { 1974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch buzz::Jid jid(words[1]); 1984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (jid.IsValid()) { 1994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch last_sent_to_ = words[1]; 2004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch SendChat(words[1], words[2]); 2014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else if (!last_sent_to_.empty()) { 2024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch SendChat(last_sent_to_, words[1]); 2034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else { 2044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch console_->Printf( 2054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch "Invalid JID. JIDs should be in the form user@domain\n"); 2064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 2074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else if ((words.size() == 2) && (command == "friend")) { 208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch InviteFriend(words[1]); 2094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else if (command == "call") { 2104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string to = GetWord(words, 1, ""); 2114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch MakeCallTo(to, cricket::CallOptions()); 2124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else if (command == "vcall") { 2134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string to = GetWord(words, 1, ""); 2144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch int bandwidth = GetInt(words, 2, cricket::kAutoBandwidth); 2154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch cricket::CallOptions options; 2164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch options.is_video = true; 2174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch options.video_bandwidth = bandwidth; 2184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch MakeCallTo(to, options); 2194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else if (command == "join") { 2204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch JoinMuc(GetWord(words, 1, "")); 2214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else if ((words.size() >= 2) && (command == "invite")) { 2224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch InviteToMuc(words[1], GetWord(words, 2, "")); 2234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else if (command == "leave") { 2244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch LeaveMuc(GetWord(words, 1, "")); 2254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else if (command == "getdevs") { 226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch GetDevices(); 2274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else if ((words.size() == 2) && (command == "setvol")) { 228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SetVolume(words[1]); 2294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else if (command == "voicemail") { 230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch CallVoicemail((words.size() >= 2) ? words[1] : ""); 231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Print(CONSOLE_COMMANDS); 233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochCallClient::CallClient(buzz::XmppClient* xmpp_client) 238dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen : xmpp_client_(xmpp_client), 239dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen media_engine_(NULL), 240dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen media_client_(NULL), 241dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen call_(NULL), 242dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen incoming_call_(false), 243dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen auto_accept_(false), 244dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen pmuc_domain_("groupchat.google.com"), 245dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen local_renderer_(NULL), 246dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen remote_renderer_(NULL), 247dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen roster_(new RosterMap), 248dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen portallocator_flags_(0), 249dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen allow_local_ips_(false), 250dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen initial_protocol_(cricket::PROTOCOL_HYBRID), 251dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen secure_policy_(cricket::SEC_DISABLED) { 252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch xmpp_client_->SignalStateChange.connect(this, &CallClient::OnStateChange); 253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 255f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochCallClient::~CallClient() { 256f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete media_client_; 257f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete roster_; 258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 260f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst std::string CallClient::strerror(buzz::XmppEngine::Error err) { 261f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch switch (err) { 262f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::XmppEngine::ERROR_NONE: 263f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return ""; 264f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::XmppEngine::ERROR_XML: 265f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return "Malformed XML or encoding error"; 266f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::XmppEngine::ERROR_STREAM: 267f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return "XMPP stream error"; 268f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::XmppEngine::ERROR_VERSION: 269f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return "XMPP version error"; 270f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::XmppEngine::ERROR_UNAUTHORIZED: 271f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return "User is not authorized (Check your username and password)"; 272f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::XmppEngine::ERROR_TLS: 273f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return "TLS could not be negotiated"; 274f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::XmppEngine::ERROR_AUTH: 275f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return "Authentication could not be negotiated"; 276f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::XmppEngine::ERROR_BIND: 277f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return "Resource or session binding could not be negotiated"; 278f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::XmppEngine::ERROR_CONNECTION_CLOSED: 279f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return "Connection closed by output handler."; 280f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::XmppEngine::ERROR_DOCUMENT_CLOSED: 281f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return "Closed by </stream:stream>"; 282f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::XmppEngine::ERROR_SOCKET: 283f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return "Socket error"; 284f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch default: 285f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return "Unknown error"; 286f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 287f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 288f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 289f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::OnCallDestroy(cricket::Call* call) { 290f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (call == call_) { 291f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (remote_renderer_) { 292f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete remote_renderer_; 293f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch remote_renderer_ = NULL; 294f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 295f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (local_renderer_) { 296f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete local_renderer_; 297f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch local_renderer_ = NULL; 298f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 299f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->SetPrompt(NULL); 300f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Print("call destroyed"); 301f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch call_ = NULL; 302f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch session_ = NULL; 303f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 304f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 305f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 306f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::OnStateChange(buzz::XmppEngine::State state) { 307f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch switch (state) { 308f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::XmppEngine::STATE_START: 309f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Print("connecting..."); 310f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 311f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 312f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::XmppEngine::STATE_OPENING: 313f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Print("logging in..."); 314f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 315f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 316f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::XmppEngine::STATE_OPEN: 317f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Print("logged in..."); 318f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch InitPhone(); 319f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch InitPresence(); 320f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 321f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 322f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case buzz::XmppEngine::STATE_CLOSED: 323f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::XmppEngine::Error error = xmpp_client_->GetError(NULL); 324f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Print("logged out..." + strerror(error)); 325f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Quit(); 326f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 327f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 328f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 329f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::InitPhone() { 330f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::string client_unique = xmpp_client_->jid().Str(); 331f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch talk_base::InitRandom(client_unique.c_str(), client_unique.size()); 332f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 333f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch worker_thread_ = new talk_base::Thread(); 334f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // The worker thread must be started here since initialization of 335f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // the ChannelManager will generate messages that need to be 336f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // dispatched by it. 337f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch worker_thread_->Start(); 338f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 339dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // TODO: It looks like we are leaking many 340dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // objects. E.g. |network_manager_| and |socket_factory_| are never 341dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // deleted. 342dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 343f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch network_manager_ = new talk_base::NetworkManager(); 344dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen socket_factory_ = new talk_base::BasicPacketSocketFactory(worker_thread_); 345f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 346731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO: Decide if the relay address should be specified here. 347f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch talk_base::SocketAddress stun_addr("stun.l.google.com", 19302); 348dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen port_allocator_ = new cricket::BasicPortAllocator( 349dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen network_manager_, socket_factory_, stun_addr, 350dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen talk_base::SocketAddress(), talk_base::SocketAddress(), 351dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen talk_base::SocketAddress()); 352f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 353f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (portallocator_flags_ != 0) { 354f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch port_allocator_->set_flags(portallocator_flags_); 355f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 356f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch session_manager_ = new cricket::SessionManager( 357f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch port_allocator_, worker_thread_); 358f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch session_manager_->SignalRequestSignaling.connect( 359f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch this, &CallClient::OnRequestSignaling); 3604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch session_manager_->SignalSessionCreate.connect( 3614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch this, &CallClient::OnSessionCreate); 362f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch session_manager_->OnSignalingReady(); 363f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 364f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch session_manager_task_ = 365f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch new cricket::SessionManagerTask(xmpp_client_, session_manager_); 366f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch session_manager_task_->EnableOutgoingMessages(); 367f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch session_manager_task_->Start(); 368f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 369f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!media_engine_) { 370dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen media_engine_ = cricket::MediaEngine::Create(); 371f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 372f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 373f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch media_client_ = new cricket::MediaSessionClient( 374f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch xmpp_client_->jid(), 375f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch session_manager_, 376f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch media_engine_, 377dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen new cricket::DeviceManager()); 378f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch media_client_->SignalCallCreate.connect(this, &CallClient::OnCallCreate); 379f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch media_client_->SignalDevicesChange.connect(this, 380f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch &CallClient::OnDevicesChange); 381dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen media_client_->set_secure(secure_policy_); 382f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 383f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 384f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::OnRequestSignaling() { 385f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch session_manager_->OnSignalingReady(); 386f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 387f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 3884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid CallClient::OnSessionCreate(cricket::Session* session, bool initiate) { 3894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch session->set_allow_local_ips(allow_local_ips_); 3904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch session->set_current_protocol(initial_protocol_); 3914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 3924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 393f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::OnCallCreate(cricket::Call* call) { 394f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch call->SignalSessionState.connect(this, &CallClient::OnSessionState); 395f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (call->video()) { 396f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch local_renderer_ = new NullRenderer("local"); 397f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch remote_renderer_ = new NullRenderer("remote"); 398f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 399f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 400f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 401f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::OnSessionState(cricket::Call* call, 402f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch cricket::BaseSession* session, 403f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch cricket::BaseSession::State state) { 404f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (state == cricket::Session::STATE_RECEIVEDINITIATE) { 405f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::Jid jid(session->remote_name()); 406f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Incoming call from '%s'", jid.Str().c_str()); 407f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch call_ = call; 408f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch session_ = session; 409f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch incoming_call_ = true; 4104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch cricket::CallOptions options; 411f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (auto_accept_) { 4124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch Accept(options); 413f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 414f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (state == cricket::Session::STATE_SENTINITIATE) { 415f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Print("calling..."); 416f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (state == cricket::Session::STATE_RECEIVEDACCEPT) { 417f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Print("call answered"); 418f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (state == cricket::Session::STATE_RECEIVEDREJECT) { 419f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Print("call not answered"); 420f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (state == cricket::Session::STATE_INPROGRESS) { 421f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Print("call in progress"); 422f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (state == cricket::Session::STATE_RECEIVEDTERMINATE) { 423f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Print("other side hung up"); 424f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 425f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 426f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 427f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::InitPresence() { 428f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch presence_push_ = new buzz::PresencePushTask(xmpp_client_, this); 429f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch presence_push_->SignalStatusUpdate.connect( 430f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch this, &CallClient::OnStatusUpdate); 431f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch presence_push_->SignalMucJoined.connect(this, &CallClient::OnMucJoined); 432f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch presence_push_->SignalMucLeft.connect(this, &CallClient::OnMucLeft); 433f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch presence_push_->SignalMucStatusUpdate.connect( 434f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch this, &CallClient::OnMucStatusUpdate); 435f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch presence_push_->Start(); 436f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 437f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch presence_out_ = new buzz::PresenceOutTask(xmpp_client_); 438f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch RefreshStatus(); 439f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch presence_out_->Start(); 440f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 441f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch muc_invite_recv_ = new buzz::MucInviteRecvTask(xmpp_client_); 442f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch muc_invite_recv_->SignalInviteReceived.connect(this, 443f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch &CallClient::OnMucInviteReceived); 444f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch muc_invite_recv_->Start(); 445f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 446f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch muc_invite_send_ = new buzz::MucInviteSendTask(xmpp_client_); 447f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch muc_invite_send_->Start(); 448f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 449f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch friend_invite_send_ = new buzz::FriendInviteSendTask(xmpp_client_); 450f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch friend_invite_send_->Start(); 451f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 452f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 453f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::RefreshStatus() { 454f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int media_caps = media_client_->GetCapabilities(); 455f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch my_status_.set_jid(xmpp_client_->jid()); 456f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch my_status_.set_available(true); 457f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch my_status_.set_show(buzz::Status::SHOW_ONLINE); 458f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch my_status_.set_priority(0); 459f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch my_status_.set_know_capabilities(true); 460f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch my_status_.set_pmuc_capability(true); 461f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch my_status_.set_phone_capability( 462f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch (media_caps & cricket::MediaEngine::AUDIO_RECV) != 0); 463f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch my_status_.set_video_capability( 464f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch (media_caps & cricket::MediaEngine::VIDEO_RECV) != 0); 465f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch my_status_.set_camera_capability( 466f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch (media_caps & cricket::MediaEngine::VIDEO_SEND) != 0); 467f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch my_status_.set_is_google_client(true); 468f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch my_status_.set_version("1.0.0.67"); 469f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch presence_out_->Send(my_status_); 470f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 471f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 472f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::OnStatusUpdate(const buzz::Status& status) { 473f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch RosterItem item; 474f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch item.jid = status.jid(); 475f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch item.show = status.show(); 476f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch item.status = status.status(); 477f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 478f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::string key = item.jid.Str(); 479f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 480f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (status.available() && status.phone_capability()) { 481f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Adding to roster: %s", key.c_str()); 482f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch (*roster_)[key] = item; 483f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 484f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Removing from roster: %s", key.c_str()); 485f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch RosterMap::iterator iter = roster_->find(key); 486f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (iter != roster_->end()) 487f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch roster_->erase(iter); 488f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 489f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 490f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 491f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::PrintRoster() { 492f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->SetPrompting(false); 493f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Roster contains %d callable", roster_->size()); 494f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch RosterMap::iterator iter = roster_->begin(); 495f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch while (iter != roster_->end()) { 496f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("%s - %s", 497f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch iter->second.jid.BareJid().Str().c_str(), 498f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch DescribeStatus(iter->second.show, iter->second.status)); 499f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch iter++; 500f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 501f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->SetPrompting(true); 502f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 503f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 5044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid CallClient::SendChat(const std::string& to, const std::string msg) { 5054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch buzz::XmlElement* stanza = new buzz::XmlElement(buzz::QN_MESSAGE); 5064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch stanza->AddAttr(buzz::QN_TO, to); 5074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch stanza->AddAttr(buzz::QN_ID, talk_base::CreateRandomString(16)); 5084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch stanza->AddAttr(buzz::QN_TYPE, "chat"); 5094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch buzz::XmlElement* body = new buzz::XmlElement(buzz::QN_BODY); 5104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch body->SetBodyText(msg); 5114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch stanza->AddElement(body); 5124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 5134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch xmpp_client_->SendStanza(stanza); 5144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch delete stanza; 5154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 5164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 517f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::InviteFriend(const std::string& name) { 518f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::Jid jid(name); 519f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!jid.IsValid() || jid.node() == "") { 520f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Invalid JID. JIDs should be in the form user@domain\n"); 521f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 522f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 523f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Note: for some reason the Buzz backend does not forward our presence 524f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // subscription requests to the end user when that user is another call 525f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // client as opposed to a Smurf user. Thus, in that scenario, you must 526f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // run the friend command as the other user too to create the linkage 527f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // (and you won't be notified to do so). 528f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch friend_invite_send_->Send(jid); 529f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Requesting to befriend %s.\n", name.c_str()); 530f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 531f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 5324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid CallClient::MakeCallTo(const std::string& name, 5334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const cricket::CallOptions& given_options) { 5344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Copy so we can change .is_muc. 5354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch cricket::CallOptions options = given_options; 5364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 537f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch bool found = false; 5384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch options.is_muc = false; 539f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::Jid callto_jid(name); 540f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::Jid found_jid; 541f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (name.length() == 0 && mucs_.size() > 0) { 542f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // if no name, and in a MUC, establish audio with the MUC 543f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch found_jid = mucs_.begin()->first; 544f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch found = true; 5454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch options.is_muc = true; 546731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else if (name[0] == '+') { 547731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // if the first character is a +, assume it's a phone number 548731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick found_jid = callto_jid; 549731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick found = true; 550f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (callto_jid.resource() == "voicemail") { 551f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // if the resource is /voicemail, allow that 552f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch found_jid = callto_jid; 553f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch found = true; 554f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 555f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // otherwise, it's a friend 556f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (RosterMap::iterator iter = roster_->begin(); 557f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch iter != roster_->end(); ++iter) { 558f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (iter->second.jid.BareEquals(callto_jid)) { 559f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch found = true; 560f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch found_jid = iter->second.jid; 561f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 562f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 563f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 564f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 565f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!found) { 566f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (mucs_.count(callto_jid) == 1 && 567f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch mucs_[callto_jid]->state() == buzz::Muc::MUC_JOINED) { 568f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch found = true; 569f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch found_jid = callto_jid; 5704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch options.is_muc = true; 571f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 572f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 573f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 574f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 575f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (found) { 5764a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch console_->Printf("Found %s '%s'", options.is_muc ? "room" : "online friend", 577f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch found_jid.Str().c_str()); 5784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch PlaceCall(found_jid, options); 579f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 580f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Could not find online friend '%s'", name.c_str()); 581f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 582f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 583f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 5844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid CallClient::PlaceCall(const buzz::Jid& jid, 5854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const cricket::CallOptions& options) { 586f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch media_client_->SignalCallDestroy.connect( 587f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch this, &CallClient::OnCallDestroy); 588f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!call_) { 5894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch call_ = media_client_->CreateCall(); 590f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->SetPrompt(jid.Str().c_str()); 5914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch session_ = call_->InitiateSession(jid, options); 5924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (options.is_muc) { 593f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // If people in this room are already in a call, must add all their 594f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // streams. 595f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::Muc::MemberMap& members = mucs_[jid]->members(); 596f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (buzz::Muc::MemberMap::iterator elem = members.begin(); 597f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch elem != members.end(); 598f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ++elem) { 599f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch AddStream(elem->second.audio_src_id(), elem->second.video_src_id()); 600f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 601f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 602f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 603f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch media_client_->SetFocus(call_); 604f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (call_->video()) { 605f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch call_->SetLocalRenderer(local_renderer_); 606731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO: Call this once for every different remote SSRC 607f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // once we get to testing multiway video. 608f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch call_->SetVideoRenderer(session_, 0, remote_renderer_); 609f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 610f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 611f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 612f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::CallVoicemail(const std::string& name) { 613f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::Jid jid(name); 614f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!jid.IsValid() || jid.node() == "") { 615f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Invalid JID. JIDs should be in the form user@domain\n"); 616f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 617f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 618f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::VoicemailJidRequester *request = 619f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch new buzz::VoicemailJidRequester(xmpp_client_, jid, my_status_.jid()); 620f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch request->SignalGotVoicemailJid.connect(this, 621f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch &CallClient::OnFoundVoicemailJid); 622f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch request->SignalVoicemailJidError.connect(this, 623f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch &CallClient::OnVoicemailJidError); 624f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch request->Start(); 625f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 626f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 627f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::OnFoundVoicemailJid(const buzz::Jid& to, 628f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const buzz::Jid& voicemail) { 629f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Calling %s's voicemail.\n", to.Str().c_str()); 6304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch PlaceCall(voicemail, cricket::CallOptions()); 631f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 632f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 633f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::OnVoicemailJidError(const buzz::Jid& to) { 634f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Unable to voicemail %s.\n", to.Str().c_str()); 635f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 636f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 637f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::AddStream(uint32 audio_src_id, uint32 video_src_id) { 638f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (audio_src_id || video_src_id) { 639f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Adding stream (%u, %u)\n", audio_src_id, video_src_id); 640f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch call_->AddStream(session_, audio_src_id, video_src_id); 641f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 642f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 643f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 644f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::RemoveStream(uint32 audio_src_id, uint32 video_src_id) { 645f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (audio_src_id || video_src_id) { 646f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Removing stream (%u, %u)\n", audio_src_id, video_src_id); 647f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch call_->RemoveStream(session_, audio_src_id, video_src_id); 648f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 649f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 650f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 6514a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid CallClient::Accept(const cricket::CallOptions& options) { 6523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT(call_ && incoming_call_); 6533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT(call_->sessions().size() == 1); 6544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch call_->AcceptSession(call_->sessions()[0], options); 655f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch media_client_->SetFocus(call_); 656f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (call_->video()) { 657f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch call_->SetLocalRenderer(local_renderer_); 658f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // The client never does an accept for multiway, so this must be 1:1, 659f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // so there's no SSRC. 660f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch call_->SetVideoRenderer(session_, 0, remote_renderer_); 661f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 662f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch incoming_call_ = false; 663f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 664f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 665f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::Reject() { 6663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT(call_ && incoming_call_); 667f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch call_->RejectSession(call_->sessions()[0]); 668f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch incoming_call_ = false; 669f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 670f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 671f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::Quit() { 672f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch talk_base::Thread::Current()->Quit(); 673f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 674f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 675f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::JoinMuc(const std::string& room) { 676f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::Jid room_jid; 677f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (room.length() > 0) { 678f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch room_jid = buzz::Jid(room); 679f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 680f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // generate a GUID of the form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, 681f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // for an eventual JID of private-chat-<GUID>@groupchat.google.com 682f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch char guid[37], guid_room[256]; 683f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (size_t i = 0; i < ARRAY_SIZE(guid) - 1;) { 684f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (i == 8 || i == 13 || i == 18 || i == 23) { 685f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch guid[i++] = '-'; 686f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 687f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch sprintf(guid + i, "%04x", rand()); 688f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch i += 4; 689f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 690f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 691f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 692f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch talk_base::sprintfn(guid_room, ARRAY_SIZE(guid_room), 693f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch "private-chat-%s@%s", guid, pmuc_domain_.c_str()); 694f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch room_jid = buzz::Jid(guid_room); 695f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 696f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 697f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!room_jid.IsValid()) { 698f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Unable to make valid muc endpoint for %s", room.c_str()); 699f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 700f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 701f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 702f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch MucMap::iterator elem = mucs_.find(room_jid); 703f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (elem != mucs_.end()) { 704f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("This MUC already exists."); 705f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 706f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 707f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 708f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::Muc* muc = new buzz::Muc(room_jid, xmpp_client_->jid().node()); 709f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch mucs_[room_jid] = muc; 710f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch presence_out_->SendDirected(muc->local_jid(), my_status_); 711f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 712f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 713f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::OnMucInviteReceived(const buzz::Jid& inviter, 714f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const buzz::Jid& room, 715f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const std::vector<buzz::AvailableMediaEntry>& avail) { 716f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 717f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Invited to join %s by %s.\n", room.Str().c_str(), 718f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch inviter.Str().c_str()); 719f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Available media:\n"); 720f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (avail.size() > 0) { 721f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (std::vector<buzz::AvailableMediaEntry>::const_iterator i = 722f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch avail.begin(); 723f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch i != avail.end(); 724f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ++i) { 725f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf(" %s, %s\n", 726f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::AvailableMediaEntry::TypeAsString(i->type), 727f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::AvailableMediaEntry::StatusAsString(i->status)); 728f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 729f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 730f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf(" None\n"); 731f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 732f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // We automatically join the room. 733f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch JoinMuc(room.Str()); 734f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 735f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 736f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::OnMucJoined(const buzz::Jid& endpoint) { 737f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch MucMap::iterator elem = mucs_.find(endpoint); 738f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(elem != mucs_.end() && 739f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch elem->second->state() == buzz::Muc::MUC_JOINING); 740f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 741f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::Muc* muc = elem->second; 742f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch muc->set_state(buzz::Muc::MUC_JOINED); 743f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Joined \"%s\"", muc->jid().Str().c_str()); 744f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 745f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 746f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::OnMucStatusUpdate(const buzz::Jid& jid, 747f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const buzz::MucStatus& status) { 748f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 749f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Look up this muc. 750f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch MucMap::iterator elem = mucs_.find(jid); 751f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(elem != mucs_.end() && 752f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch elem->second->state() == buzz::Muc::MUC_JOINED); 753f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 754f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::Muc* muc = elem->second; 755f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 756f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (status.jid().IsBare() || status.jid() == muc->local_jid()) { 757f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // We are only interested in status about other users. 758f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 759f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 760f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 761f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!status.available()) { 762f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // User is leaving the room. 763f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::Muc::MemberMap::iterator elem = 764f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch muc->members().find(status.jid().resource()); 765f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 766f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(elem != muc->members().end()); 767f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 768f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // If user had src-ids, they have the left the room without explicitly 769f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // hanging-up; must tear down the stream if in a call to this room. 770f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (call_ && session_->remote_name() == muc->jid().Str()) { 771f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch RemoveStream(elem->second.audio_src_id(), elem->second.video_src_id()); 772f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 773f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 774f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Remove them from the room. 775f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch muc->members().erase(elem); 776f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 777f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Either user has joined or something changed about them. 778f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Note: The [] operator here will create a new entry if it does not 779f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // exist, which is what we want. 780f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::MucStatus& member_status( 781f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch muc->members()[status.jid().resource()]); 782f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (call_ && session_->remote_name() == muc->jid().Str()) { 783f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // We are in a call to this muc. Must potentially update our streams. 784f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // The following code will correctly update our streams regardless of 785f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // whether the SSRCs have been removed, added, or changed and regardless 786f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // of whether that has been done to both or just one. This relies on the 787f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // fact that AddStream/RemoveStream do nothing for SSRC arguments that are 788f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // zero. 789f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch uint32 remove_audio_src_id = 0; 790f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch uint32 remove_video_src_id = 0; 791f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch uint32 add_audio_src_id = 0; 792f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch uint32 add_video_src_id = 0; 793f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (member_status.audio_src_id() != status.audio_src_id()) { 794f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch remove_audio_src_id = member_status.audio_src_id(); 795f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch add_audio_src_id = status.audio_src_id(); 796f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 797f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (member_status.video_src_id() != status.video_src_id()) { 798f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch remove_video_src_id = member_status.video_src_id(); 799f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch add_video_src_id = status.video_src_id(); 800f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 801f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Remove the old SSRCs, if any. 802f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch RemoveStream(remove_audio_src_id, remove_video_src_id); 803f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Add the new SSRCs, if any. 804f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch AddStream(add_audio_src_id, add_video_src_id); 805f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 806f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Update the status. This will use the compiler-generated copy 807f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // constructor, which is perfectly adequate for this class. 808f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch member_status = status; 809f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 810f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 811f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 812f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::LeaveMuc(const std::string& room) { 813f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::Jid room_jid; 814f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (room.length() > 0) { 815f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch room_jid = buzz::Jid(room); 816f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (mucs_.size() > 0) { 817f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // leave the first MUC if no JID specified 818f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch room_jid = mucs_.begin()->first; 819f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 820f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 821f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!room_jid.IsValid()) { 822f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Invalid MUC JID."); 823f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 824f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 825f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 826f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch MucMap::iterator elem = mucs_.find(room_jid); 827f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (elem == mucs_.end()) { 828f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("No such MUC."); 829f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 830f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 831f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 832f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::Muc* muc = elem->second; 833f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch muc->set_state(buzz::Muc::MUC_LEAVING); 834f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 835f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::Status status; 836f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch status.set_jid(my_status_.jid()); 837f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch status.set_available(false); 838f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch status.set_priority(0); 839f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch presence_out_->SendDirected(muc->local_jid(), status); 840f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 841f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 842f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::OnMucLeft(const buzz::Jid& endpoint, int error) { 843f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // We could be kicked from a room from any state. We would hope this 844f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // happens While in the MUC_LEAVING state 845f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch MucMap::iterator elem = mucs_.find(endpoint); 846f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (elem == mucs_.end()) 847f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 848f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 849f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::Muc* muc = elem->second; 850f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (muc->state() == buzz::Muc::MUC_JOINING) { 851f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Failed to join \"%s\", code=%d", 852f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch muc->jid().Str().c_str(), error); 853f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (muc->state() == buzz::Muc::MUC_JOINED) { 854f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Kicked from \"%s\"", 855f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch muc->jid().Str().c_str()); 856f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 857f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 858f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete muc; 859f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch mucs_.erase(elem); 860f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 861f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 862f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::InviteToMuc(const std::string& user, const std::string& room) { 863f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // First find the room. 864f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const buzz::Muc* found_muc; 865f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (room.length() == 0) { 866f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (mucs_.size() == 0) { 867f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Not in a room yet; can't invite.\n"); 868f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 869f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 870f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Invite to the first muc 871f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch found_muc = mucs_.begin()->second; 872f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 873f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch MucMap::iterator elem = mucs_.find(buzz::Jid(room)); 874f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (elem == mucs_.end()) { 875f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("Not in room %s.\n", room.c_str()); 876f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 877f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 878f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch found_muc = elem->second; 879f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 880f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Now find the user. We invite all of their resources. 881f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch bool found_user = false; 882f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buzz::Jid user_jid(user); 883f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (RosterMap::iterator iter = roster_->begin(); 884f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch iter != roster_->end(); ++iter) { 885f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (iter->second.jid.BareEquals(user_jid)) { 886f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch muc_invite_send_->Send(iter->second.jid, *found_muc); 887f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch found_user = true; 888f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 889f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 890f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!found_user) { 891f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch console_->Printf("No such friend as %s.\n", user.c_str()); 892f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 893f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 894f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 895f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 896f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::GetDevices() { 897f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::vector<std::string> names; 898f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch media_client_->GetAudioInputDevices(&names); 899f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch printf("Audio input devices:\n"); 900f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch PrintDevices(names); 901f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch media_client_->GetAudioOutputDevices(&names); 902f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch printf("Audio output devices:\n"); 903f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch PrintDevices(names); 904f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch media_client_->GetVideoCaptureDevices(&names); 905f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch printf("Video capture devices:\n"); 906f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch PrintDevices(names); 907f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 908f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 909f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::PrintDevices(const std::vector<std::string>& names) { 910f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (size_t i = 0; i < names.size(); ++i) { 911f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch printf("%d: %s\n", static_cast<int>(i), names[i].c_str()); 912f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 913f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 914f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 915f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::OnDevicesChange() { 916f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch printf("Devices changed.\n"); 917f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch RefreshStatus(); 918f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 919f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 920f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid CallClient::SetVolume(const std::string& level) { 921f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch media_client_->SetOutputVolume(strtol(level.c_str(), NULL, 10)); 922f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 923