10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/*
20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle
30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2004--2005, Google Inc.
40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without
60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met:
70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer.
100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer in the documentation
120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     and/or other materials provided with the distribution.
130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  3. The name of the author may not be used to endorse or promote products
140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     derived from this software without specific prior written permission.
150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */
270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/examples/call/callclient.h"
290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <string>
310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/examples/call/console.h"
330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/examples/call/friendinvitesendtask.h"
340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/examples/call/muc.h"
350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/examples/call/mucinviterecvtask.h"
360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/examples/call/mucinvitesendtask.h"
370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/examples/call/presencepushtask.h"
380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/base/mediacommon.h"
390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/base/mediaengine.h"
400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/base/rtpdataengine.h"
410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/base/screencastid.h"
42cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/helpers.h"
43cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/logging.h"
44cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/network.h"
45cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/socketaddress.h"
46cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/stringencode.h"
47cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/stringutils.h"
48cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/thread.h"
49cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/windowpickerfactory.h"
500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef HAVE_SCTP
510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/sctp/sctpdataengine.h"
520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif
530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/base/videorenderer.h"
540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/devices/devicemanager.h"
550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/devices/videorendererfactory.h"
560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/sessionmanager.h"
570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/client/basicportallocator.h"
580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/client/sessionmanagertask.h"
590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/session/media/mediamessages.h"
600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/session/media/mediasessionclient.h"
610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/xmpp/constants.h"
620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/xmpp/hangoutpubsubclient.h"
630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/xmpp/mucroomconfigtask.h"
640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/xmpp/mucroomlookuptask.h"
650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/xmpp/pingtask.h"
66cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "talk/xmpp/presenceouttask.h"
670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace {
690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Must be period >= timeout.
710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 kPingPeriodMillis = 10000;
720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 kPingTimeoutMillis = 10000;
730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst char* DescribeStatus(buzz::PresenceStatus::Show show,
750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           const std::string& desc) {
760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (show) {
770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  case buzz::PresenceStatus::SHOW_XA:      return desc.c_str();
780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  case buzz::PresenceStatus::SHOW_ONLINE:  return "online";
790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  case buzz::PresenceStatus::SHOW_AWAY:    return "away";
800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  case buzz::PresenceStatus::SHOW_DND:     return "do not disturb";
810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  case buzz::PresenceStatus::SHOW_CHAT:    return "ready to chat";
820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  default:                                 return "offline";
830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstd::string GetWord(const std::vector<std::string>& words,
870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    size_t index, const std::string& def) {
880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (words.size() > index) {
890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return words[index];
900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return def;
920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint GetInt(const std::vector<std::string>& words, size_t index, int def) {
960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int val;
972a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  if (words.size() > index && rtc::FromString(words[index], &val)) {
980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return val;
990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return def;
1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}  // namespace
1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst char* CALL_COMMANDS =
1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"Available commands:\n"
1080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"\n"
1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  hangup            Ends the call.\n"
1100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  hold              Puts the current call on hold\n"
1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  calls             Lists the current calls and their sessions\n"
1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  switch [call_id]  Switch to the specified call\n"
1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  addsession [jid]  Add a new session to the current call.\n"
1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  rmsession [sid]   Remove specified session.\n"
1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  mute              Stops sending voice.\n"
1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  unmute            Re-starts sending voice.\n"
1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  vmute             Stops sending video.\n"
1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  vunmute           Re-starts sending video.\n"
1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  dtmf              Sends a DTMF tone.\n"
1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  stats             Print voice stats for the current call.\n"
1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  quit              Quits the application.\n"
1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"";
1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// TODO: Make present and record really work.
1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst char* HANGOUT_COMMANDS =
1260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"Available MUC commands:\n"
1270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"\n"
1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  present    Starts presenting (just signalling; not actually presenting.)\n"
1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  unpresent  Stops presenting (just signalling; not actually presenting.)\n"
1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  record     Starts recording (just signalling; not actually recording.)\n"
1310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  unrecord   Stops recording (just signalling; not actually recording.)\n"
1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  rmute [nick] Remote mute another participant.\n"
1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  block [nick] Block another participant.\n"
1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  screencast [fps] Starts screencast. \n"
1350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  unscreencast Stops screencast. \n"
1360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  quit       Quits the application.\n"
1370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"";
1380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst char* RECEIVE_COMMANDS =
1400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"Available commands:\n"
1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"\n"
1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  accept [bw] Accepts the incoming call and switches to it.\n"
1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  reject  Rejects the incoming call and stays with the current call.\n"
1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  quit    Quits the application.\n"
1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"";
1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst char* CONSOLE_COMMANDS =
1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"Available commands:\n"
1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"\n"
1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  roster              Prints the online friends from your roster.\n"
1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  friend user         Request to add a user to your roster.\n"
1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  call [jid] [bw]     Initiates a call to the user[/room] with the\n"
1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"                      given JID and with optional bandwidth.\n"
1540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  vcall [jid] [bw]    Initiates a video call to the user[/room] with\n"
1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"                      the given JID and with optional bandwidth.\n"
1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  calls               Lists the current calls\n"
1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  switch [call_id]    Switch to the specified call\n"
1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  join [room_jid]     Joins a multi-user-chat with room JID.\n"
1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  ljoin [room_name]   Joins a MUC by looking up JID from room name.\n"
1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  invite user [room]  Invites a friend to a multi-user-chat.\n"
1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  leave [room]        Leaves a multi-user-chat.\n"
1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  nick [nick]         Sets the nick.\n"
1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  priority [int]      Sets the priority.\n"
1640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  getdevs             Prints the available media devices.\n"
1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"  quit                Quits the application.\n"
1660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org"";
1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::ParseLine(const std::string& line) {
1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<std::string> words;
1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int start = -1;
1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int state = 0;
1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (int index = 0; index <= static_cast<int>(line.size()); ++index) {
1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (state == 0) {
1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (!isspace(line[index])) {
1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        start = index;
1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        state = 1;
1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ASSERT(state == 1);
1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ASSERT(start >= 0);
1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (isspace(line[index])) {
1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        std::string word(line, start, index - start);
1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        words.push_back(word);
1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        start = -1;
1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        state = 0;
1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Global commands
1910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const std::string& command = GetWord(words, 0, "");
1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (command == "quit") {
1930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    Quit();
1940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (call_ && incoming_call_) {
1950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (command == "accept") {
1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      cricket::CallOptions options;
1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      options.video_bandwidth = GetInt(words, 1, cricket::kAutoBandwidth);
1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      options.has_video = true;
1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      options.data_channel_type = data_channel_type_;
2000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      Accept(options);
2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "reject") {
2020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      Reject();
2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      console_->PrintLine(RECEIVE_COMMANDS);
2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (call_) {
2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (command == "hangup") {
2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      call_->Terminate();
2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "hold") {
2100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      media_client_->SetFocus(NULL);
2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      call_ = NULL;
2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "addsession") {
2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      std::string to = GetWord(words, 1, "");
2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      cricket::CallOptions options;
2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      options.has_video = call_->has_video();
2160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      options.video_bandwidth = cricket::kAutoBandwidth;
2170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      options.data_channel_type = data_channel_type_;
2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      options.AddStream(cricket::MEDIA_TYPE_VIDEO, "", "");
2190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (!InitiateAdditionalSession(to, options)) {
2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        console_->PrintLine("Failed to initiate additional session.");
2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "rmsession") {
2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      std::string id = GetWord(words, 1, "");
2240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      TerminateAndRemoveSession(call_, id);
2250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "calls") {
2260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      PrintCalls();
2270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if ((words.size() == 2) && (command == "switch")) {
2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      SwitchToCall(GetInt(words, 1, -1));
2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "mute") {
2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      call_->Mute(true);
2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (InMuc()) {
2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        hangout_pubsub_client_->PublishAudioMuteState(true);
2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "unmute") {
2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      call_->Mute(false);
2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (InMuc()) {
2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        hangout_pubsub_client_->PublishAudioMuteState(false);
2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "vmute") {
2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      call_->MuteVideo(true);
2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (InMuc()) {
2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        hangout_pubsub_client_->PublishVideoMuteState(true);
2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "vunmute") {
2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      call_->MuteVideo(false);
2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (InMuc()) {
2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        hangout_pubsub_client_->PublishVideoMuteState(false);
2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "screencast") {
2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (screencast_ssrc_ != 0) {
2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        console_->PrintLine("Can't screencast twice.  Unscreencast first.");
2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      } else {
2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        std::string streamid = "screencast";
2542a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org        screencast_ssrc_ = rtc::CreateRandomId();
2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        int fps = GetInt(words, 1, 5);  // Default to 5 fps.
2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        cricket::ScreencastId screencastid;
2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        cricket::Session* session = GetFirstSession();
2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        if (session && SelectFirstDesktopScreencastId(&screencastid)) {
2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          call_->StartScreencast(
2610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org              session, streamid, screencast_ssrc_, screencastid, fps);
2620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
2630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
2640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "unscreencast") {
2650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // TODO: Use a random ssrc
2660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      std::string streamid = "screencast";
2670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      cricket::Session* session = GetFirstSession();
2690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (session) {
2700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        call_->StopScreencast(session, streamid, screencast_ssrc_);
2710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        screencast_ssrc_ = 0;
2720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "present") {
2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (InMuc()) {
2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        hangout_pubsub_client_->PublishPresenterState(true);
2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "unpresent") {
2780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (InMuc()) {
2790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        hangout_pubsub_client_->PublishPresenterState(false);
2800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
2810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "record") {
2820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (InMuc()) {
2830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        hangout_pubsub_client_->PublishRecordingState(true);
2840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
2850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "unrecord") {
2860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (InMuc()) {
2870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        hangout_pubsub_client_->PublishRecordingState(false);
2880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
2890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if ((command == "rmute") && (words.size() == 2)) {
2900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (InMuc()) {
2910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        const std::string& nick = words[1];
2920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        hangout_pubsub_client_->RemoteMute(nick);
2930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if ((command == "block") && (words.size() == 2)) {
2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (InMuc()) {
2960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        const std::string& nick = words[1];
2970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        hangout_pubsub_client_->BlockMedia(nick);
2980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
2990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "senddata") {
3000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // "" is the default streamid.
3010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      SendData("", words[1]);
3020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if ((command == "dtmf") && (words.size() == 2)) {
3030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      int ev = std::string("0123456789*#").find(words[1][0]);
3040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      call_->PressDTMF(ev);
3050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "stats") {
3060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      PrintStats();
3070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
3080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      console_->PrintLine(CALL_COMMANDS);
3090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (InMuc()) {
3100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        console_->PrintLine(HANGOUT_COMMANDS);
3110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
3120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
3140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (command == "roster") {
3150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      PrintRoster();
3160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "send") {
3170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      buzz::Jid jid(words[1]);
3180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (jid.IsValid()) {
3190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        last_sent_to_ = words[1];
3200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        SendChat(words[1], words[2]);
3210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      } else if (!last_sent_to_.empty()) {
3220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        SendChat(last_sent_to_, words[1]);
3230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      } else {
3240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        console_->PrintLine(
3250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org            "Invalid JID. JIDs should be in the form user@domain");
3260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
3270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if ((words.size() == 2) && (command == "friend")) {
3280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      InviteFriend(words[1]);
3290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "call") {
3300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      std::string to = GetWord(words, 1, "");
3310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      cricket::CallOptions options;
3320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      options.data_channel_type = data_channel_type_;
3330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (!PlaceCall(to, options)) {
3340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        console_->PrintLine("Failed to initiate call.");
3350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
3360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "vcall") {
3370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      std::string to = GetWord(words, 1, "");
3380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      int bandwidth = GetInt(words, 2, cricket::kAutoBandwidth);
3390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      cricket::CallOptions options;
3400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      options.has_video = true;
3410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      options.video_bandwidth = bandwidth;
3420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      options.data_channel_type = data_channel_type_;
3430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (!PlaceCall(to, options)) {
3440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        console_->PrintLine("Failed to initiate call.");
3450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
3460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "calls") {
3470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      PrintCalls();
3480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if ((words.size() == 2) && (command == "switch")) {
3490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      SwitchToCall(GetInt(words, 1, -1));
3500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "join") {
3510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      JoinMuc(GetWord(words, 1, ""));
3520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "ljoin") {
3530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LookupAndJoinMuc(GetWord(words, 1, ""));
3540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if ((words.size() >= 2) && (command == "invite")) {
3550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      InviteToMuc(words[1], GetWord(words, 2, ""));
3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "leave") {
3570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LeaveMuc(GetWord(words, 1, ""));
3580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "nick") {
3590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      SetNick(GetWord(words, 1, ""));
3600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "priority") {
3610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      int priority = GetInt(words, 1, 0);
3620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      SetPriority(priority);
3630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      SendStatus();
3640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (command == "getdevs") {
3650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      GetDevices();
3660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if ((words.size() == 2) && (command == "setvol")) {
3670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      SetVolume(words[1]);
3680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
3690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      console_->PrintLine(CONSOLE_COMMANDS);
3700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgCallClient::CallClient(buzz::XmppClient* xmpp_client,
3750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                       const std::string& caps_node, const std::string& version)
3760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : xmpp_client_(xmpp_client),
3770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      worker_thread_(NULL),
3780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      media_engine_(NULL),
3790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      data_engine_(NULL),
3800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      media_client_(NULL),
3810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      call_(NULL),
3820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      hangout_pubsub_client_(NULL),
3830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      incoming_call_(false),
3840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      auto_accept_(false),
3850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      pmuc_domain_("groupchat.google.com"),
3860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      render_(true),
3870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      data_channel_type_(cricket::DCT_NONE),
3880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      multisession_enabled_(false),
3890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      local_renderer_(NULL),
3900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      static_views_accumulated_count_(0),
3910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      screencast_ssrc_(0),
3920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      roster_(new RosterMap),
3930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      portallocator_flags_(0),
3940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      allow_local_ips_(false),
3950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      signaling_protocol_(cricket::PROTOCOL_HYBRID),
3960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      transport_protocol_(cricket::ICEPROTO_HYBRID),
3970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      sdes_policy_(cricket::SEC_DISABLED),
3980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      dtls_policy_(cricket::SEC_DISABLED),
3995c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org      ssl_identity_(),
4000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      show_roster_messages_(false) {
4010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  xmpp_client_->SignalStateChange.connect(this, &CallClient::OnStateChange);
4020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  my_status_.set_caps_node(caps_node);
4030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  my_status_.set_version(version);
4040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgCallClient::~CallClient() {
4070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  delete media_client_;
4080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  delete roster_;
4090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  delete worker_thread_;
4100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst std::string CallClient::strerror(buzz::XmppEngine::Error err) {
4130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (err) {
4140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case buzz::XmppEngine::ERROR_NONE:
4150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return "";
4160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case buzz::XmppEngine::ERROR_XML:
4170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return "Malformed XML or encoding error";
4180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case buzz::XmppEngine::ERROR_STREAM:
4190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return "XMPP stream error";
4200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case buzz::XmppEngine::ERROR_VERSION:
4210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return "XMPP version error";
4220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case buzz::XmppEngine::ERROR_UNAUTHORIZED:
4230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return "User is not authorized (Check your username and password)";
4240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case buzz::XmppEngine::ERROR_TLS:
4250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return "TLS could not be negotiated";
4260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case buzz::XmppEngine::ERROR_AUTH:
4270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return "Authentication could not be negotiated";
4280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case buzz::XmppEngine::ERROR_BIND:
4290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return "Resource or session binding could not be negotiated";
4300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case buzz::XmppEngine::ERROR_CONNECTION_CLOSED:
4310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return "Connection closed by output handler.";
4320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case buzz::XmppEngine::ERROR_DOCUMENT_CLOSED:
4330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return "Closed by </stream:stream>";
4340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case buzz::XmppEngine::ERROR_SOCKET:
4350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return "Socket error";
4360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    default:
4370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return "Unknown error";
4380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnCallDestroy(cricket::Call* call) {
4420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  RemoveCallsStaticRenderedViews(call);
4430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (call == call_) {
4440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (local_renderer_) {
4450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      delete local_renderer_;
4460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      local_renderer_ = NULL;
4470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
4480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("call destroyed");
4490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    call_ = NULL;
4500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    delete hangout_pubsub_client_;
4510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    hangout_pubsub_client_ = NULL;
4520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnStateChange(buzz::XmppEngine::State state) {
4560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (state) {
4570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case buzz::XmppEngine::STATE_START:
4580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      console_->PrintLine("connecting...");
4590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
4600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case buzz::XmppEngine::STATE_OPENING:
4610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      console_->PrintLine("logging in...");
4620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
4630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case buzz::XmppEngine::STATE_OPEN:
4640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      console_->PrintLine("logged in...");
4650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      InitMedia();
4660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      InitPresence();
4670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
4680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case buzz::XmppEngine::STATE_CLOSED:
4690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      {
4700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        buzz::XmppEngine::Error error = xmpp_client_->GetError(NULL);
4710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        console_->PrintLine("logged out... %s", strerror(error).c_str());
4720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        Quit();
4730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
4740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
4750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    default:
4760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
4770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::InitMedia() {
4812a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  worker_thread_ = new rtc::Thread();
4820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // The worker thread must be started here since initialization of
4830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // the ChannelManager will generate messages that need to be
4840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // dispatched by it.
4850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  worker_thread_->Start();
4860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO: It looks like we are leaking many objects. E.g.
4880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // |network_manager_| is never deleted.
4892a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  network_manager_ = new rtc::BasicNetworkManager();
4900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO: Decide if the relay address should be specified here.
4922a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::SocketAddress stun_addr("stun.l.google.com", 19302);
493459f356846e5dc1e9b2c5182568660f5eaacfe3ebuildbot@webrtc.org  cricket::ServerAddresses stun_servers;
494459f356846e5dc1e9b2c5182568660f5eaacfe3ebuildbot@webrtc.org  stun_servers.insert(stun_addr);
4950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  port_allocator_ =  new cricket::BasicPortAllocator(
4962a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      network_manager_, stun_servers, rtc::SocketAddress(),
4972a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      rtc::SocketAddress(), rtc::SocketAddress());
4980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (portallocator_flags_ != 0) {
5000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    port_allocator_->set_flags(portallocator_flags_);
5010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  session_manager_ = new cricket::SessionManager(
5030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      port_allocator_, worker_thread_);
5040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  session_manager_->set_secure(dtls_policy_);
5050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  session_manager_->set_identity(ssl_identity_.get());
5060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  session_manager_->set_transport_protocol(transport_protocol_);
5070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  session_manager_->SignalRequestSignaling.connect(
5080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      this, &CallClient::OnRequestSignaling);
5090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  session_manager_->SignalSessionCreate.connect(
5100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      this, &CallClient::OnSessionCreate);
5110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  session_manager_->OnSignalingReady();
5120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  session_manager_task_ =
5140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      new cricket::SessionManagerTask(xmpp_client_, session_manager_);
5150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  session_manager_task_->EnableOutgoingMessages();
5160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  session_manager_task_->Start();
5170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!media_engine_) {
5190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    media_engine_ = cricket::MediaEngineFactory::Create();
5200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!data_engine_) {
5230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (data_channel_type_ == cricket::DCT_SCTP) {
5240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef HAVE_SCTP
5250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      data_engine_ = new cricket::SctpDataEngine();
5260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#else
5270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_WARNING) << "SCTP Data Engine not supported.";
5280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      data_channel_type_ = cricket::DCT_NONE;
5290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      data_engine_ = new cricket::RtpDataEngine();
5300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif
5310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
5320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Even if we have DCT_NONE, we still have a data engine, just
5330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // to make sure it isn't NULL.
5340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      data_engine_ = new cricket::RtpDataEngine();
5350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
5360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  media_client_ = new cricket::MediaSessionClient(
5390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      xmpp_client_->jid(),
5400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      session_manager_,
5410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      media_engine_,
5420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      data_engine_,
5430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      cricket::DeviceManagerFactory::Create());
5440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  media_client_->SignalCallCreate.connect(this, &CallClient::OnCallCreate);
5450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  media_client_->SignalCallDestroy.connect(this, &CallClient::OnCallDestroy);
5460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  media_client_->SignalDevicesChange.connect(this,
5470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                             &CallClient::OnDevicesChange);
5480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  media_client_->set_secure(sdes_policy_);
5490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  media_client_->set_multisession_enabled(multisession_enabled_);
5500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnRequestSignaling() {
5530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  session_manager_->OnSignalingReady();
5540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnSessionCreate(cricket::Session* session, bool initiate) {
5570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  session->set_current_protocol(signaling_protocol_);
5580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnCallCreate(cricket::Call* call) {
5610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  call->SignalSessionState.connect(this, &CallClient::OnSessionState);
5620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  call->SignalMediaStreamsUpdate.connect(
5630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      this, &CallClient::OnMediaStreamsUpdate);
5640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnSessionState(cricket::Call* call,
5670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                cricket::Session* session,
5680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                cricket::Session::State state) {
5690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (state == cricket::Session::STATE_RECEIVEDINITIATE) {
5700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    buzz::Jid jid(session->remote_name());
5710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (call_ == call && multisession_enabled_) {
5720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // We've received an initiate for an existing call. This is actually a
5730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // new session for that call.
5740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      console_->PrintLine("Incoming session from '%s'", jid.Str().c_str());
5750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      AddSession(session);
5760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      cricket::CallOptions options;
5780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      options.has_video = call_->has_video();
5790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      options.data_channel_type = data_channel_type_;
5800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      call_->AcceptSession(session, options);
5810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (call_->has_video() && render_) {
5830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        RenderAllStreams(call, session, true);
5840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
5850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
5860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      console_->PrintLine("Incoming call from '%s'", jid.Str().c_str());
5870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      call_ = call;
5880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      AddSession(session);
5890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      incoming_call_ = true;
5900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (call->has_video() && render_) {
5910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        local_renderer_ =
5920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org            cricket::VideoRendererFactory::CreateGuiVideoRenderer(160, 100);
5930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
5940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (auto_accept_) {
5950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        cricket::CallOptions options;
5960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        options.has_video = true;
5970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        options.data_channel_type = data_channel_type_;
5980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        Accept(options);
5990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
6000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
6010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (state == cricket::Session::STATE_SENTINITIATE) {
6020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (call->has_video() && render_) {
6030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      local_renderer_ =
6040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          cricket::VideoRendererFactory::CreateGuiVideoRenderer(160, 100);
6050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
6060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("calling...");
6070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (state == cricket::Session::STATE_RECEIVEDACCEPT) {
6080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("call answered");
6090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SetupAcceptedCall();
6100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (state == cricket::Session::STATE_RECEIVEDREJECT) {
6110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("call not answered");
6120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (state == cricket::Session::STATE_INPROGRESS) {
6130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("call in progress");
6140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    call->SignalSpeakerMonitor.connect(this, &CallClient::OnSpeakerChanged);
6150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    call->StartSpeakerMonitor(session);
6160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (state == cricket::Session::STATE_RECEIVEDTERMINATE) {
6170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("other side terminated");
6180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    TerminateAndRemoveSession(call, session->id());
6190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnSpeakerChanged(cricket::Call* call,
6230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                  cricket::Session* session,
6240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                  const cricket::StreamParams& speaker) {
6250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!speaker.has_ssrcs()) {
6260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Session %s has no current speaker.",
6270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        session->id().c_str());
6280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (speaker.id.empty()) {
6290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Session %s speaker change to unknown (%u).",
6300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        session->id().c_str(), speaker.first_ssrc());
6310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
6320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Session %s speaker changed to %s (%u).",
6330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        session->id().c_str(), speaker.id.c_str(),
6340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        speaker.first_ssrc());
6350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SetMediaCaps(int media_caps, buzz::PresenceStatus* status) {
6390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  status->set_voice_capability((media_caps & cricket::AUDIO_RECV) != 0);
6400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  status->set_video_capability((media_caps & cricket::VIDEO_RECV) != 0);
6410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  status->set_camera_capability((media_caps & cricket::VIDEO_SEND) != 0);
6420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SetCaps(int media_caps, buzz::PresenceStatus* status) {
6450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  status->set_know_capabilities(true);
6460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  status->set_pmuc_capability(true);
6470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SetMediaCaps(media_caps, status);
6480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SetAvailable(const buzz::Jid& jid, buzz::PresenceStatus* status) {
6510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  status->set_jid(jid);
6520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  status->set_available(true);
6530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  status->set_show(buzz::PresenceStatus::SHOW_ONLINE);
6540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::InitPresence() {
6570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  presence_push_ = new buzz::PresencePushTask(xmpp_client_, this);
6580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  presence_push_->SignalStatusUpdate.connect(
6590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    this, &CallClient::OnStatusUpdate);
6600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  presence_push_->SignalMucJoined.connect(this, &CallClient::OnMucJoined);
6610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  presence_push_->SignalMucLeft.connect(this, &CallClient::OnMucLeft);
6620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  presence_push_->SignalMucStatusUpdate.connect(
6630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    this, &CallClient::OnMucStatusUpdate);
6640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  presence_push_->Start();
6650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  presence_out_ = new buzz::PresenceOutTask(xmpp_client_);
6670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SetAvailable(xmpp_client_->jid(), &my_status_);
6680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SetCaps(media_client_->GetCapabilities(), &my_status_);
6690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SendStatus(my_status_);
6700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  presence_out_->Start();
6710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  muc_invite_recv_ = new buzz::MucInviteRecvTask(xmpp_client_);
6730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  muc_invite_recv_->SignalInviteReceived.connect(this,
6740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      &CallClient::OnMucInviteReceived);
6750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  muc_invite_recv_->Start();
6760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  muc_invite_send_ = new buzz::MucInviteSendTask(xmpp_client_);
6780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  muc_invite_send_->Start();
6790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  friend_invite_send_ = new buzz::FriendInviteSendTask(xmpp_client_);
6810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  friend_invite_send_->Start();
6820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  StartXmppPing();
6840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::StartXmppPing() {
6870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::PingTask* ping = new buzz::PingTask(
6882a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      xmpp_client_, rtc::Thread::Current(),
6890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      kPingPeriodMillis, kPingTimeoutMillis);
6900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ping->SignalTimeout.connect(this, &CallClient::OnPingTimeout);
6910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ping->Start();
6920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnPingTimeout() {
6950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_WARNING) << "XMPP Ping timeout. Will keep trying...";
6960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  StartXmppPing();
6970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Or should we do this instead?
6990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Quit();
7000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::SendStatus(const buzz::PresenceStatus& status) {
7030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  presence_out_->Send(status);
7040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnStatusUpdate(const buzz::PresenceStatus& status) {
7070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  RosterItem item;
7080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  item.jid = status.jid();
7090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  item.show = status.show();
7100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  item.status = status.status();
7110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::string key = item.jid.Str();
7130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (status.available() && status.voice_capability()) {
7150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (show_roster_messages_) {
7160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      console_->PrintLine("Adding to roster: %s", key.c_str());
7170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
7180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    (*roster_)[key] = item;
7190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // TODO: Make some of these constants.
7200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
7210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (show_roster_messages_) {
7220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      console_->PrintLine("Removing from roster: %s", key.c_str());
7230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
7240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    RosterMap::iterator iter = roster_->find(key);
7250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (iter != roster_->end())
7260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      roster_->erase(iter);
7270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::PrintRoster() {
7310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  console_->PrintLine("Roster contains %d callable", roster_->size());
7320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  RosterMap::iterator iter = roster_->begin();
7330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  while (iter != roster_->end()) {
7340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("%s - %s",
7350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        iter->second.jid.BareJid().Str().c_str(),
7360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        DescribeStatus(iter->second.show, iter->second.status));
7370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    iter++;
7380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::SendChat(const std::string& to, const std::string msg) {
7420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::XmlElement* stanza = new buzz::XmlElement(buzz::QN_MESSAGE);
7430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  stanza->AddAttr(buzz::QN_TO, to);
7442a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  stanza->AddAttr(buzz::QN_ID, rtc::CreateRandomString(16));
7450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  stanza->AddAttr(buzz::QN_TYPE, "chat");
7460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::XmlElement* body = new buzz::XmlElement(buzz::QN_BODY);
7470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  body->SetBodyText(msg);
7480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  stanza->AddElement(body);
7490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  xmpp_client_->SendStanza(stanza);
7510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  delete stanza;
7520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::SendData(const std::string& streamid,
7550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const std::string& text) {
7560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO(mylesj): Support sending data over sessions other than the first.
7570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  cricket::Session* session = GetFirstSession();
7580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!call_ || !session) {
7590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Must be in a call to send data.");
7600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
7610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!call_->has_data()) {
7630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("This call doesn't have a data channel.");
7640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
7650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const cricket::DataContentDescription* data =
7680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      cricket::GetFirstDataContentDescription(session->local_description());
7690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!data) {
7700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("This call doesn't have a data content.");
7710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
7720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  cricket::StreamParams stream;
7750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!cricket::GetStreamByIds(
7760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          data->streams(), "", streamid, &stream)) {
7770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Could not send data: no such stream: "
7780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    << streamid << ".";
7790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
7800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  cricket::SendDataParams params;
7830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  params.ssrc = stream.first_ssrc();
7842a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::Buffer payload(text.data(), text.length());
7850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  cricket::SendDataResult result;
7860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool sent = call_->SendData(session, params, payload, &result);
7870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!sent) {
7880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (result == cricket::SDR_BLOCK) {
7890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_WARNING) << "Could not send data because it would block.";
7900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
7910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_WARNING) << "Could not send data for unknown reason.";
7920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
7930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::InviteFriend(const std::string& name) {
7970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::Jid jid(name);
7980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!jid.IsValid() || jid.node() == "") {
7990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Invalid JID. JIDs should be in the form user@domain.");
8000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
8010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Note: for some reason the Buzz backend does not forward our presence
8030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // subscription requests to the end user when that user is another call
8040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // client as opposed to a Smurf user. Thus, in that scenario, you must
8050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // run the friend command as the other user too to create the linkage
8060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // (and you won't be notified to do so).
8070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  friend_invite_send_->Send(jid);
8080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  console_->PrintLine("Requesting to befriend %s.", name.c_str());
8090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool CallClient::FindJid(const std::string& name, buzz::Jid* found_jid,
8120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         cricket::CallOptions* options) {
8130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool found = false;
8140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  options->is_muc = false;
8150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::Jid callto_jid(name);
8160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (name.length() == 0 && mucs_.size() > 0) {
8170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // if no name, and in a MUC, establish audio with the MUC
8180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    *found_jid = mucs_.begin()->first;
8190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    found = true;
8200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    options->is_muc = true;
8210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (name[0] == '+') {
8220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // if the first character is a +, assume it's a phone number
8230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    *found_jid = callto_jid;
8240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    found = true;
8250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
8260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // otherwise, it's a friend
8270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    for (RosterMap::iterator iter = roster_->begin();
8280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org         iter != roster_->end(); ++iter) {
8290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (iter->second.jid.BareEquals(callto_jid)) {
8300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        found = true;
8310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        *found_jid = iter->second.jid;
8320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        break;
8330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
8340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
8350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!found) {
8370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (mucs_.count(callto_jid) == 1 &&
8380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          mucs_[callto_jid]->state() == buzz::Muc::MUC_JOINED) {
8390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        found = true;
8400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        *found_jid = callto_jid;
8410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        options->is_muc = true;
8420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
8430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
8440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (found) {
8470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Found %s '%s'",
8480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        options->is_muc ? "room" : "online friend",
8490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        found_jid->Str().c_str());
8500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
8510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Could not find online friend '%s'", name.c_str());
8520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return found;
8550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnDataReceived(cricket::Call*,
8580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                const cricket::ReceiveDataParams& params,
8592a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                                const rtc::Buffer& payload) {
8600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO(mylesj): Support receiving data on sessions other than the first.
8610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  cricket::Session* session = GetFirstSession();
8620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!session)
8630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
8640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  cricket::StreamParams stream;
8660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const std::vector<cricket::StreamParams>* data_streams =
8670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      call_->GetDataRecvStreams(session);
8680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::string text(payload.data(), payload.length());
8690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (data_streams && GetStreamBySsrc(*data_streams, params.ssrc, &stream)) {
8700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine(
8710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        "Received data from '%s' on stream '%s' (ssrc=%u): %s",
8720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        stream.groupid.c_str(), stream.id.c_str(),
8730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        params.ssrc, text.c_str());
8740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
8750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine(
8760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        "Received data (ssrc=%u): %s",
8770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        params.ssrc, text.c_str());
8780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool CallClient::PlaceCall(const std::string& name,
8820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           cricket::CallOptions options) {
8830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::Jid jid;
8840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!FindJid(name, &jid, &options))
8850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
8860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!call_) {
8880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    call_ = media_client_->CreateCall();
8890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    AddSession(call_->InitiateSession(jid, media_client_->jid(), options));
8900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  media_client_->SetFocus(call_);
8922b73e54efd883e483dfee48c5417601306faf10ebuildbot@webrtc.org  if (call_->has_video() && render_ && !options.is_muc) {
8932b73e54efd883e483dfee48c5417601306faf10ebuildbot@webrtc.org    // TODO(pthatcher): Hookup local_render_ to the local capturer.
8940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (options.is_muc) {
8960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::string& nick = mucs_[jid]->local_jid().resource();
8970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    hangout_pubsub_client_ =
8980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        new buzz::HangoutPubSubClient(xmpp_client_, jid, nick);
8990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    hangout_pubsub_client_->SignalPresenterStateChange.connect(
9000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        this, &CallClient::OnPresenterStateChange);
9010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    hangout_pubsub_client_->SignalAudioMuteStateChange.connect(
9020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        this, &CallClient::OnAudioMuteStateChange);
9030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    hangout_pubsub_client_->SignalRecordingStateChange.connect(
9040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        this, &CallClient::OnRecordingStateChange);
9050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    hangout_pubsub_client_->SignalRemoteMute.connect(
9060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        this, &CallClient::OnRemoteMuted);
9070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    hangout_pubsub_client_->SignalMediaBlock.connect(
9080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        this, &CallClient::OnMediaBlocked);
9090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    hangout_pubsub_client_->SignalRequestError.connect(
9100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        this, &CallClient::OnHangoutRequestError);
9110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    hangout_pubsub_client_->SignalPublishAudioMuteError.connect(
9120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        this, &CallClient::OnHangoutPublishAudioMuteError);
9130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    hangout_pubsub_client_->SignalPublishPresenterError.connect(
9140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        this, &CallClient::OnHangoutPublishPresenterError);
9150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    hangout_pubsub_client_->SignalPublishRecordingError.connect(
9160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        this, &CallClient::OnHangoutPublishRecordingError);
9170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    hangout_pubsub_client_->SignalRemoteMuteError.connect(
9180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        this, &CallClient::OnHangoutRemoteMuteError);
9190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    hangout_pubsub_client_->RequestAll();
9200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
9230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
9240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool CallClient::InitiateAdditionalSession(const std::string& name,
9260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                           cricket::CallOptions options) {
9270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Can't add a session if there is no call yet.
9280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!call_)
9290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
9300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::Jid jid;
9320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!FindJid(name, &jid, &options))
9330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
9340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<cricket::Session*>& call_sessions = sessions_[call_->id()];
9360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  call_sessions.push_back(
9370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      call_->InitiateSession(jid,
9380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             buzz::Jid(call_sessions[0]->remote_name()),
9390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             options));
9400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
9420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
9430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::TerminateAndRemoveSession(cricket::Call* call,
9450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                           const std::string& id) {
9460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<cricket::Session*>& call_sessions = sessions_[call->id()];
9470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::vector<cricket::Session*>::iterator iter = call_sessions.begin();
9480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       iter != call_sessions.end(); ++iter) {
9490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if ((*iter)->id() == id) {
9500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      RenderAllStreams(call, *iter, false);
9510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      call_->TerminateSession(*iter);
9520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      call_sessions.erase(iter);
9530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
9540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
9550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
9570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::PrintCalls() {
9590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const std::map<uint32, cricket::Call*>& calls = media_client_->calls();
9600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::map<uint32, cricket::Call*>::const_iterator i = calls.begin();
9610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       i != calls.end(); ++i) {
9620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Call (id:%d), is %s",
9630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        i->first,
9640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        i->second == call_ ? "active" : "on hold");
9650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    std::vector<cricket::Session *>& sessions = sessions_[call_->id()];
9660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    for (std::vector<cricket::Session *>::const_iterator j = sessions.begin();
9670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org         j != sessions.end(); ++j) {
9680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      console_->PrintLine("|--Session (id:%s), to %s", (*j)->id().c_str(),
9690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          (*j)->remote_name().c_str());
9700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      std::vector<cricket::StreamParams>::const_iterator k;
9720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      const std::vector<cricket::StreamParams>* streams =
9730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          i->second->GetAudioRecvStreams(*j);
9740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (streams)
9750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        for (k = streams->begin(); k != streams->end(); ++k) {
9760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          console_->PrintLine("|----Audio Stream: %s", k->ToString().c_str());
9770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
9780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      streams = i->second->GetVideoRecvStreams(*j);
9790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (streams)
9800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        for (k = streams->begin(); k != streams->end(); ++k) {
9810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          console_->PrintLine("|----Video Stream: %s", k->ToString().c_str());
9820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
9830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      streams = i->second->GetDataRecvStreams(*j);
9840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (streams)
9850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        for (k = streams->begin(); k != streams->end(); ++k) {
9860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          console_->PrintLine("|----Data Stream: %s", k->ToString().c_str());
9870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
9880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
9890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
9910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::SwitchToCall(uint32 call_id) {
9930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const std::map<uint32, cricket::Call*>& calls = media_client_->calls();
9940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::map<uint32, cricket::Call*>::const_iterator call_iter =
9950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      calls.find(call_id);
9960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (call_iter != calls.end()) {
9970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    media_client_->SetFocus(call_iter->second);
9980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    call_ = call_iter->second;
9990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
10000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Unable to find call: %d", call_id);
10010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnPresenterStateChange(
10050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::string& nick, bool was_presenting, bool is_presenting) {
10060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!was_presenting && is_presenting) {
10070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("%s now presenting.", nick.c_str());
10080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (was_presenting && !is_presenting) {
10090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("%s no longer presenting.", nick.c_str());
10100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (was_presenting && is_presenting) {
10110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("%s still presenting.", nick.c_str());
10120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (!was_presenting && !is_presenting) {
10130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("%s still not presenting.", nick.c_str());
10140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnAudioMuteStateChange(
10180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::string& nick, bool was_muted, bool is_muted) {
10190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!was_muted && is_muted) {
10200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("%s now muted.", nick.c_str());
10210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (was_muted && !is_muted) {
10220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("%s no longer muted.", nick.c_str());
10230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnRecordingStateChange(
10270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::string& nick, bool was_recording, bool is_recording) {
10280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!was_recording && is_recording) {
10290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("%s now recording.", nick.c_str());
10300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (was_recording && !is_recording) {
10310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("%s no longer recording.", nick.c_str());
10320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnRemoteMuted(const std::string& mutee_nick,
10360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               const std::string& muter_nick,
10370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               bool should_mute_locally) {
10380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (should_mute_locally) {
10390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    call_->Mute(true);
10400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Remote muted by %s.", muter_nick.c_str());
10410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
10420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("%s remote muted by %s.",
10430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        mutee_nick.c_str(), muter_nick.c_str());
10440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnMediaBlocked(const std::string& blockee_nick,
10480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                const std::string& blocker_nick) {
10490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  console_->PrintLine("%s blocked by %s.",
10500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      blockee_nick.c_str(), blocker_nick.c_str());
10510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnHangoutRequestError(const std::string& node,
10540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                       const buzz::XmlElement* stanza) {
10550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  console_->PrintLine("Failed request pub sub items for node %s.",
10560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      node.c_str());
10570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnHangoutPublishAudioMuteError(
10600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::string& task_id, const buzz::XmlElement* stanza) {
10610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  console_->PrintLine("Failed to publish audio mute state.");
10620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnHangoutPublishPresenterError(
10650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::string& task_id, const buzz::XmlElement* stanza) {
10660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  console_->PrintLine("Failed to publish presenting state.");
10670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnHangoutPublishRecordingError(
10700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::string& task_id, const buzz::XmlElement* stanza) {
10710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  console_->PrintLine("Failed to publish recording state.");
10720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnHangoutRemoteMuteError(const std::string& task_id,
10750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                          const std::string& mutee_nick,
10760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                          const buzz::XmlElement* stanza) {
10770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  console_->PrintLine("Failed to remote mute.");
10780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::Accept(const cricket::CallOptions& options) {
10810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(call_ && incoming_call_);
10820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(sessions_[call_->id()].size() == 1);
10830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  cricket::Session* session = GetFirstSession();
10840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  call_->AcceptSession(session, options);
10850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  media_client_->SetFocus(call_);
10860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (call_->has_video() && render_) {
10872b73e54efd883e483dfee48c5417601306faf10ebuildbot@webrtc.org    // TODO(pthatcher): Hookup local_render_ to the local capturer.
10880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    RenderAllStreams(call_, session, true);
10890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SetupAcceptedCall();
10910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  incoming_call_ = false;
10920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::SetupAcceptedCall() {
10950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (call_->has_data()) {
10960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    call_->SignalDataReceived.connect(this, &CallClient::OnDataReceived);
10970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::Reject() {
11010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(call_ && incoming_call_);
11020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  call_->RejectSession(call_->sessions()[0]);
11030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  incoming_call_ = false;
11040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::Quit() {
11072a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::Thread::Current()->Quit();
11080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::SetNick(const std::string& muc_nick) {
11110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  my_status_.set_nick(muc_nick);
11120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO: We might want to re-send presence, but right
11140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // now, it appears to be ignored by the MUC.
11150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  //
11160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // presence_out_->Send(my_status_); for (MucMap::const_iterator itr
11170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // = mucs_.begin(); itr != mucs_.end(); ++itr) {
11180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // presence_out_->SendDirected(itr->second->local_jid(),
11190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // my_status_); }
11200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  console_->PrintLine("Nick set to '%s'.", muc_nick.c_str());
11220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::LookupAndJoinMuc(const std::string& room_name) {
11250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // The room_name can't be empty for lookup task.
11260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (room_name.empty()) {
11270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Please provide a room name or room jid.");
11280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
11290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
11300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::string room = room_name;
11320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::string domain = xmpp_client_->jid().domain();
11330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (room_name.find("@") != std::string::npos) {
11340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Assume the room_name is a fully qualified room name.
11350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // We'll find the room name string and domain name string from it.
11360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    room = room_name.substr(0, room_name.find("@"));
11370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    domain = room_name.substr(room_name.find("@") + 1);
11380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
11390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::MucRoomLookupTask* lookup_query_task =
11410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      buzz::MucRoomLookupTask::CreateLookupTaskForRoomName(
11420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          xmpp_client_, buzz::Jid(buzz::STR_GOOGLE_MUC_LOOKUP_JID), room,
11430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          domain);
11440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  lookup_query_task->SignalResult.connect(this,
11450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      &CallClient::OnRoomLookupResponse);
11460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  lookup_query_task->SignalError.connect(this,
11470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      &CallClient::OnRoomLookupError);
11480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  lookup_query_task->Start();
11490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::JoinMuc(const std::string& room_jid_str) {
11520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (room_jid_str.empty()) {
11530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    buzz::Jid room_jid = GenerateRandomMucJid();
11540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Generated a random room jid: %s",
11550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        room_jid.Str().c_str());
11560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    JoinMuc(room_jid);
11570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
11580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    JoinMuc(buzz::Jid(room_jid_str));
11590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
11600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::JoinMuc(const buzz::Jid& room_jid) {
11630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!room_jid.IsValid()) {
11640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Unable to make valid muc endpoint for %s",
11650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        room_jid.Str().c_str());
11660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
11670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
11680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::string room_nick = room_jid.resource();
11700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (room_nick.empty()) {
11710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    room_nick = (xmpp_client_->jid().node()
11720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                 + "_" + xmpp_client_->jid().resource());
11730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
11740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  MucMap::iterator elem = mucs_.find(room_jid);
11760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (elem != mucs_.end()) {
11770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("This MUC already exists.");
11780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
11790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
11800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::Muc* muc = new buzz::Muc(room_jid.BareJid(), room_nick);
11820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  mucs_[muc->jid()] = muc;
11830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  presence_out_->SendDirected(muc->local_jid(), my_status_);
11840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnRoomLookupResponse(buzz::MucRoomLookupTask* task,
11870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                      const buzz::MucRoomInfo& room) {
11880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // The server requires the room be "configured" before being used.
11890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We only need to configure it if we create it, but rooms are
11900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // auto-created at lookup, so there's currently no way to know if we
11910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // created it.  So, we configure it every time, just in case.
11920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Luckily, it appears to be safe to configure a room that's already
11930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // configured.  Our current flow is:
11940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // 1. Lookup/auto-create
11950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // 2. Configure
11960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // 3. Join
11970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO: In the future, once the server supports it, we
11980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // should:
11990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // 1. Lookup
12000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // 2. Create and Configure if necessary
12010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // 3. Join
12020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<std::string> room_features;
12030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  room_features.push_back(buzz::STR_MUC_ROOM_FEATURE_ENTERPRISE);
12040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::MucRoomConfigTask* room_config_task = new buzz::MucRoomConfigTask(
12050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      xmpp_client_, room.jid, room.full_name(), room_features);
12060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  room_config_task->SignalResult.connect(this,
12070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      &CallClient::OnRoomConfigResult);
12080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  room_config_task->SignalError.connect(this,
12090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      &CallClient::OnRoomConfigError);
12100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  room_config_task->Start();
12110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnRoomLookupError(buzz::IqTask* task,
12140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                   const buzz::XmlElement* stanza) {
12150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (stanza == NULL) {
12160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Room lookup failed.");
12170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
12180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Room lookup error: ", stanza->Str().c_str());
12190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
12200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnRoomConfigResult(buzz::MucRoomConfigTask* task) {
12230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  JoinMuc(task->room_jid());
12240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnRoomConfigError(buzz::IqTask* task,
12270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                   const buzz::XmlElement* stanza) {
12280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  console_->PrintLine("Room config failed.");
12290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We join the muc anyway, because if the room is already
12300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // configured, the configure will fail, but we still want to join.
12310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Idealy, we'd know why the room config failed and only do this on
12320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // "already configured" errors.  But right now all we get back is
12330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // "not-allowed".
12340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::MucRoomConfigTask* config_task =
12350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      static_cast<buzz::MucRoomConfigTask*>(task);
12360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  JoinMuc(config_task->room_jid());
12370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnMucInviteReceived(const buzz::Jid& inviter,
12400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const buzz::Jid& room,
12410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::vector<buzz::AvailableMediaEntry>& avail) {
12420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  console_->PrintLine("Invited to join %s by %s.", room.Str().c_str(),
12440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      inviter.Str().c_str());
12450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  console_->PrintLine("Available media:");
12460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (avail.size() > 0) {
12470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    for (std::vector<buzz::AvailableMediaEntry>::const_iterator i =
12480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org            avail.begin();
12490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        i != avail.end();
12500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        ++i) {
12510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      console_->PrintLine("  %s, %s",
12520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          buzz::AvailableMediaEntry::TypeAsString(i->type),
12530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          buzz::AvailableMediaEntry::StatusAsString(i->status));
12540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
12550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
12560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("  None");
12570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
12580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We automatically join the room.
12590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  JoinMuc(room);
12600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnMucJoined(const buzz::Jid& endpoint) {
12630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  MucMap::iterator elem = mucs_.find(endpoint);
12640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(elem != mucs_.end() &&
12650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org         elem->second->state() == buzz::Muc::MUC_JOINING);
12660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::Muc* muc = elem->second;
12680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  muc->set_state(buzz::Muc::MUC_JOINED);
12690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  console_->PrintLine("Joined \"%s\"", muc->jid().Str().c_str());
12700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnMucStatusUpdate(const buzz::Jid& jid,
12730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const buzz::MucPresenceStatus& status) {
12740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Look up this muc.
12760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  MucMap::iterator elem = mucs_.find(jid);
12770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(elem != mucs_.end());
12780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::Muc* muc = elem->second;
12800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (status.jid().IsBare() || status.jid() == muc->local_jid()) {
12820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // We are only interested in status about other users.
12830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
12840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
12850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12863e4dfed139a08def7ac23673584b4e52542ed694phoglund@webrtc.org  if (status.available()) {
12873e4dfed139a08def7ac23673584b4e52542ed694phoglund@webrtc.org    muc->members()[status.jid().resource()] = status;
12883e4dfed139a08def7ac23673584b4e52542ed694phoglund@webrtc.org  } else {
12890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    muc->members().erase(status.jid().resource());
12900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
12910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool CallClient::InMuc() {
12940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const buzz::Jid* muc_jid = FirstMucJid();
12950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!muc_jid) return false;
12960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return muc_jid->IsValid();
12970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
12980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
12990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst buzz::Jid* CallClient::FirstMucJid() {
13000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (mucs_.empty()) return NULL;
13010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return &(mucs_.begin()->first);
13020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
13030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
13040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::LeaveMuc(const std::string& room) {
13050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::Jid room_jid;
13060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const buzz::Jid* muc_jid = FirstMucJid();
13070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (room.length() > 0) {
13080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    room_jid = buzz::Jid(room);
13090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (mucs_.size() > 0) {
13100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // leave the first MUC if no JID specified
13110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (muc_jid) {
13120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      room_jid = *(muc_jid);
13130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
13140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
13150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
13160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!room_jid.IsValid()) {
13170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Invalid MUC JID.");
13180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
13190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
13200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
13210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  MucMap::iterator elem = mucs_.find(room_jid);
13220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (elem == mucs_.end()) {
13230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("No such MUC.");
13240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
13250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
13260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
13270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::Muc* muc = elem->second;
13280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  muc->set_state(buzz::Muc::MUC_LEAVING);
13290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
13300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::PresenceStatus status;
13310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  status.set_jid(my_status_.jid());
13320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  status.set_available(false);
13330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  status.set_priority(0);
13340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  presence_out_->SendDirected(muc->local_jid(), status);
13350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
13360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
13370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnMucLeft(const buzz::Jid& endpoint, int error) {
13380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We could be kicked from a room from any state.  We would hope this
13390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // happens While in the MUC_LEAVING state
13400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  MucMap::iterator elem = mucs_.find(endpoint);
13410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (elem == mucs_.end())
13420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
13430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
13440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::Muc* muc = elem->second;
13450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (muc->state() == buzz::Muc::MUC_JOINING) {
13460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Failed to join \"%s\", code=%d",
13470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        muc->jid().Str().c_str(), error);
13480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (muc->state() == buzz::Muc::MUC_JOINED) {
13490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Kicked from \"%s\"",
13500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        muc->jid().Str().c_str());
13510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
13520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
13530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  delete muc;
13540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  mucs_.erase(elem);
13550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
13560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
13570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::InviteToMuc(const std::string& given_user,
13580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             const std::string& room) {
13590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::string user = given_user;
13600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
13610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // First find the room.
13620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const buzz::Muc* found_muc;
13630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (room.length() == 0) {
13640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (mucs_.size() == 0) {
13650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      console_->PrintLine("Not in a room yet; can't invite.");
13660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return;
13670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
13680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Invite to the first muc
13690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    found_muc = mucs_.begin()->second;
13700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
13710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    MucMap::iterator elem = mucs_.find(buzz::Jid(room));
13720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (elem == mucs_.end()) {
13730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      console_->PrintLine("Not in room %s.", room.c_str());
13740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return;
13750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
13760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    found_muc = elem->second;
13770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
13780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
13790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::Jid invite_to = found_muc->jid();
13800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
13810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Now find the user. We invite all of their resources.
13820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool found_user = false;
13830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::Jid user_jid(user);
13840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (RosterMap::iterator iter = roster_->begin();
13850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       iter != roster_->end(); ++iter) {
13860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (iter->second.jid.BareEquals(user_jid)) {
13870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      buzz::Jid invitee = iter->second.jid;
13880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      muc_invite_send_->Send(invite_to, invitee);
13890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      found_user = true;
13900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
13910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
13920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!found_user) {
13930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    buzz::Jid invitee = user_jid;
13940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    muc_invite_send_->Send(invite_to, invitee);
13950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
13960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
13970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
13980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::GetDevices() {
13990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<std::string> names;
14000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  media_client_->GetAudioInputDevices(&names);
14010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  console_->PrintLine("Audio input devices:");
14020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  PrintDevices(names);
14030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  media_client_->GetAudioOutputDevices(&names);
14040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  console_->PrintLine("Audio output devices:");
14050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  PrintDevices(names);
14060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  media_client_->GetVideoCaptureDevices(&names);
14070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  console_->PrintLine("Video capture devices:");
14080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  PrintDevices(names);
14090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
14100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::PrintDevices(const std::vector<std::string>& names) {
14120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (size_t i = 0; i < names.size(); ++i) {
14130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("%d: %s", static_cast<int>(i), names[i].c_str());
14140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
14150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
14160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnDevicesChange() {
14180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  console_->PrintLine("Devices changed.");
14190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SetMediaCaps(media_client_->GetCapabilities(), &my_status_);
14200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SendStatus(my_status_);
14210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
14220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::SetVolume(const std::string& level) {
14240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  media_client_->SetOutputVolume(strtol(level.c_str(), NULL, 10));
14250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
14260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::OnMediaStreamsUpdate(cricket::Call* call,
14280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                      cricket::Session* session,
14290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                      const cricket::MediaStreams& added,
14300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                      const cricket::MediaStreams& removed) {
14310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (call && call->has_video()) {
14320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    for (std::vector<cricket::StreamParams>::const_iterator
14330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org         it = removed.video().begin(); it != removed.video().end(); ++it) {
14340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      RemoveStaticRenderedView(it->first_ssrc());
14350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
14360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (render_) {
14380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      RenderStreams(call, session, added.video(), true);
14390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
14400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SendViewRequest(call, session);
14410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
14420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
14430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::RenderAllStreams(cricket::Call* call,
14450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                  cricket::Session* session,
14460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                  bool enable) {
14470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const std::vector<cricket::StreamParams>* video_streams =
14480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      call->GetVideoRecvStreams(session);
14490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (video_streams) {
14500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    RenderStreams(call, session, *video_streams, enable);
14510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
14520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
14530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::RenderStreams(
14550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    cricket::Call* call,
14560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    cricket::Session* session,
14570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::vector<cricket::StreamParams>& video_streams,
14580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    bool enable) {
14590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<cricket::StreamParams>::const_iterator stream;
14600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (stream = video_streams.begin(); stream != video_streams.end();
14610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       ++stream) {
14620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    RenderStream(call, session, *stream, enable);
14630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
14640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
14650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::RenderStream(cricket::Call* call,
14670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              cricket::Session* session,
14680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              const cricket::StreamParams& stream,
14690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              bool enable) {
14700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!stream.has_ssrcs()) {
14710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Nothing to see here; move along.
14720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
14730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
14740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  uint32 ssrc = stream.first_ssrc();
14760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  StaticRenderedViews::iterator iter =
14770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      static_rendered_views_.find(std::make_pair(session, ssrc));
14780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (enable) {
14790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (iter == static_rendered_views_.end()) {
14800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // TODO(pthatcher): Make dimensions and positions more configurable.
14810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      int offset = (50 * static_views_accumulated_count_) % 300;
14820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      AddStaticRenderedView(session, ssrc, 640, 400, 30,
14830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                            offset, offset);
14840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Should have it now.
14850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      iter = static_rendered_views_.find(std::make_pair(session, ssrc));
14860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
14870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    call->SetVideoRenderer(session, ssrc, iter->second.renderer);
14880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
14890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (iter != static_rendered_views_.end()) {
14900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      call->SetVideoRenderer(session, ssrc, NULL);
14910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      RemoveStaticRenderedView(ssrc);
14920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
14930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
14940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
14950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
14960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// TODO: Would these methods to add and remove views make
14970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// more sense in call.cc?  Would other clients use them?
14980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::AddStaticRenderedView(
14990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    cricket::Session* session,
15000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint32 ssrc, int width, int height, int framerate,
15010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    int x_offset, int y_offset) {
15020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  StaticRenderedView rendered_view(
15030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      cricket::StaticVideoView(
15040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          cricket::StreamSelector(ssrc), width, height, framerate),
15050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      cricket::VideoRendererFactory::CreateGuiVideoRenderer(
15060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          x_offset, y_offset));
15070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  rendered_view.renderer->SetSize(width, height, 0);
15080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  static_rendered_views_.insert(std::make_pair(std::make_pair(session, ssrc),
15090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                               rendered_view));
15100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ++static_views_accumulated_count_;
15110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  console_->PrintLine("Added renderer for ssrc %d", ssrc);
15120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
15130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
15140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool CallClient::RemoveStaticRenderedView(uint32 ssrc) {
15150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (StaticRenderedViews::iterator it = static_rendered_views_.begin();
15160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       it != static_rendered_views_.end(); ++it) {
15170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (it->second.view.selector.ssrc == ssrc) {
15180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      delete it->second.renderer;
15190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      static_rendered_views_.erase(it);
15200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      console_->PrintLine("Removed renderer for ssrc %d", ssrc);
15210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return true;
15220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
15230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
15240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return false;
15250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
15260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
15270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::RemoveCallsStaticRenderedViews(cricket::Call* call) {
15280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<cricket::Session*>& sessions = sessions_[call->id()];
15290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::set<cricket::Session*> call_sessions(sessions.begin(), sessions.end());
15300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (StaticRenderedViews::iterator it = static_rendered_views_.begin();
15310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       it != static_rendered_views_.end(); ) {
15320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (call_sessions.find(it->first.first) != call_sessions.end()) {
15330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      delete it->second.renderer;
15340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      static_rendered_views_.erase(it++);
15350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
15360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ++it;
15370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
15380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
15390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
15400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
15410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::SendViewRequest(cricket::Call* call,
15420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                 cricket::Session* session) {
15430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  cricket::ViewRequest request;
15440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (StaticRenderedViews::iterator it = static_rendered_views_.begin();
15450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       it != static_rendered_views_.end(); ++it) {
15460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (it->first.first == session) {
15470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      request.static_video_views.push_back(it->second.view);
15480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
15490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
15500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  call->SendViewRequest(session, request);
15510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
15520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
15530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::Jid CallClient::GenerateRandomMucJid() {
15540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Generate a GUID of the form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX,
15550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // for an eventual JID of private-chat-<GUID>@groupchat.google.com.
15560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  char guid[37], guid_room[256];
15570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (size_t i = 0; i < ARRAY_SIZE(guid) - 1;) {
15580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (i == 8 || i == 13 || i == 18 || i == 23) {
15590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      guid[i++] = '-';
15600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
15610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      sprintf(guid + i, "%04x", rand());
15620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      i += 4;
15630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
15640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
15650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
15662a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::sprintfn(guid_room,
15670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      ARRAY_SIZE(guid_room),
15680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      "private-chat-%s@%s",
15690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      guid,
15700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      pmuc_domain_.c_str());
15710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return buzz::Jid(guid_room);
15720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
15730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
15740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool CallClient::SelectFirstDesktopScreencastId(
15750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    cricket::ScreencastId* screencastid) {
15762a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  if (!rtc::WindowPickerFactory::IsSupported()) {
15770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Window picker not suported on this OS.";
15780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
15790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
15800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
15812a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::WindowPicker* picker =
15822a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      rtc::WindowPickerFactory::CreateWindowPicker();
15830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!picker) {
15840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Could not create a window picker.";
15850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
15860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
15870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
15882a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::DesktopDescriptionList desktops;
15890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!picker->GetDesktopList(&desktops) || desktops.empty()) {
15900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Could not get a list of desktops.";
15910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
15920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
15930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
15940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *screencastid = cricket::ScreencastId(desktops[0].id());
15950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
15960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
15970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
15980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid CallClient::PrintStats() const {
15990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const cricket::VoiceMediaInfo& vmi = call_->last_voice_media_info();
16000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
16010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::vector<cricket::VoiceSenderInfo>::const_iterator it =
16020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       vmi.senders.begin(); it != vmi.senders.end(); ++it) {
16030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Sender: ssrc=%u codec='%s' bytes=%d packets=%d "
16040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        "rtt=%d jitter=%d",
160597fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org                        it->ssrc(), it->codec_name.c_str(), it->bytes_sent,
16060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        it->packets_sent, it->rtt_ms, it->jitter_ms);
16070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
16080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
16090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::vector<cricket::VoiceReceiverInfo>::const_iterator it =
16100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       vmi.receivers.begin(); it != vmi.receivers.end(); ++it) {
16110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    console_->PrintLine("Receiver: ssrc=%u bytes=%d packets=%d "
16120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        "jitter=%d loss=%.2f",
161397fbd309a28be4e38d138b40662507d50cab6d26sergeyu@chromium.org                        it->ssrc(), it->bytes_rcvd, it->packets_rcvd,
16140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        it->jitter_ms, it->fraction_lost);
16150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
16160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1617