15976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org/* 25976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * libjingle 35976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Copyright 2011, Google Inc. 45976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 55976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Redistribution and use in source and binary forms, with or without 65976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * modification, are permitted provided that the following conditions are met: 75976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 85976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 1. Redistributions of source code must retain the above copyright notice, 95976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * this list of conditions and the following disclaimer. 105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 2. Redistributions in binary form must reproduce the above copyright notice, 115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * this list of conditions and the following disclaimer in the documentation 125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * and/or other materials provided with the distribution. 135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 3. The name of the author may not be used to endorse or promote products 145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * derived from this software without specific prior written permission. 155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org */ 275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/xmpp/hangoutpubsubclient.h" 295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/logging.h" 315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/xmpp/constants.h" 325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/xmpp/jid.h" 335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/xmllite/qname.h" 345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/xmllite/xmlelement.h" 355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Gives a high-level API for MUC call PubSub needs such as 385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// presenter state, recording state, mute state, and remote mute. 395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace buzz { 415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace { 435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char kPresenting[] = "s"; 445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char kNotPresenting[] = "o"; 455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char kEmpty[] = ""; 465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst std::string GetPublisherNickFromPubSubItem(const XmlElement* item_elem) { 485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (item_elem == NULL) { 495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return ""; 505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return Jid(item_elem->Attr(QN_ATTR_PUBLISHER)).resource(); 535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} // namespace 565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Knows how to handle specific states and XML. 595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgtemplate <typename C> 605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass PubSubStateSerializer { 615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual ~PubSubStateSerializer() {} 635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual XmlElement* Write(const QName& state_name, const C& state) = 0; 645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual C Parse(const XmlElement* state_elem) = 0; 655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Knows how to create "keys" for states, which determines their 685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// uniqueness. Most states are per-nick, but block is 695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// per-blocker-and-blockee. This is independent of itemid, especially 705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// in the case of presenter state. 715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass PubSubStateKeySerializer { 725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual ~PubSubStateKeySerializer() {} 745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual std::string GetKey(const std::string& publisher_nick, 755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& published_nick) = 0; 765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass PublishedNickKeySerializer : public PubSubStateKeySerializer { 795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual std::string GetKey(const std::string& publisher_nick, 815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& published_nick) { 825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return published_nick; 835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass PublisherAndPublishedNicksKeySerializer 875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org : public PubSubStateKeySerializer { 885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual std::string GetKey(const std::string& publisher_nick, 905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& published_nick) { 915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return publisher_nick + ":" + published_nick; 925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// A simple serialiazer where presence of item => true, lack of item 965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// => false. 975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass BoolStateSerializer : public PubSubStateSerializer<bool> { 985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual XmlElement* Write(const QName& state_name, const bool& state) { 995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!state) { 1005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return NULL; 1015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return new XmlElement(state_name, true); 1045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual bool Parse(const XmlElement* state_elem) { 1075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return state_elem != NULL; 1085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 1105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Adapts PubSubClient to be specifically suited for pub sub call 1125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// states. Signals state changes and keeps track of keys, which are 1135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// normally nicks. 1145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// TODO: Expose this as a generally useful class, not just 1155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// private to hangouts. 1165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgtemplate <typename C> 1175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass PubSubStateClient : public sigslot::has_slots<> { 1185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 1195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Gets ownership of the serializers, but not the client. 1205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PubSubStateClient(const std::string& publisher_nick, 1215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PubSubClient* client, 1225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const QName& state_name, 1235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org C default_state, 1245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PubSubStateKeySerializer* key_serializer, 1255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PubSubStateSerializer<C>* state_serializer) 1265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org : publisher_nick_(publisher_nick), 1275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org client_(client), 1285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_name_(state_name), 1295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org default_state_(default_state) { 1305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org key_serializer_.reset(key_serializer); 1315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_serializer_.reset(state_serializer); 1325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org client_->SignalItems.connect( 1335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &PubSubStateClient<C>::OnItems); 1345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org client_->SignalPublishResult.connect( 1355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &PubSubStateClient<C>::OnPublishResult); 1365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org client_->SignalPublishError.connect( 1375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &PubSubStateClient<C>::OnPublishError); 1385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org client_->SignalRetractResult.connect( 1395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &PubSubStateClient<C>::OnRetractResult); 1405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org client_->SignalRetractError.connect( 1415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &PubSubStateClient<C>::OnRetractError); 1425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual ~PubSubStateClient() {} 1455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual void Publish(const std::string& published_nick, 1475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const C& state, 1485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::string* task_id_out) { 1495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::string key = key_serializer_->GetKey(publisher_nick_, published_nick); 1505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::string itemid = state_name_.LocalPart() + ":" + key; 1515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (StatesEqual(state, default_state_)) { 1525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org client_->RetractItem(itemid, task_id_out); 1535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 1545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org XmlElement* state_elem = state_serializer_->Write(state_name_, state); 1555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_elem->AddAttr(QN_NICK, published_nick); 1565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org client_->PublishItem(itemid, state_elem, task_id_out); 1575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org }; 1595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sigslot::signal1<const PubSubStateChange<C>&> SignalStateChange; 1615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Signal (task_id, item). item is NULL for retract. 1625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sigslot::signal2<const std::string&, 1635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const XmlElement*> SignalPublishResult; 1645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Signal (task_id, item, error stanza). item is NULL for retract. 1655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org sigslot::signal3<const std::string&, 1665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const XmlElement*, 1675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const XmlElement*> SignalPublishError; 1685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org protected: 1705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // return false if retracted item (no info or state given) 1715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual bool ParseStateItem(const PubSubItem& item, 1725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StateItemInfo* info_out, 1735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool* state_out) { 1745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const XmlElement* state_elem = item.elem->FirstNamed(state_name_); 1755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (state_elem == NULL) { 1765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 1775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org info_out->publisher_nick = GetPublisherNickFromPubSubItem(item.elem); 1805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org info_out->published_nick = state_elem->Attr(QN_NICK); 1815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *state_out = state_serializer_->Parse(state_elem); 1825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 1835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org }; 1845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual bool StatesEqual(C state1, C state2) { 1865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return state1 == state2; 1875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PubSubClient* client() { return client_; } 1905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org private: 1925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void OnItems(PubSubClient* pub_sub_client, 1935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::vector<PubSubItem>& items) { 1945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (std::vector<PubSubItem>::const_iterator item = items.begin(); 1955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org item != items.end(); ++item) { 1965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org OnItem(*item); 1975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void OnItem(const PubSubItem& item) { 2015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& itemid = item.itemid; 2025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StateItemInfo info; 2035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org C new_state; 2045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool retracted = !ParseStateItem(item, &info, &new_state); 2065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (retracted) { 2075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool known_itemid = 2085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org (info_by_itemid_.find(itemid) != info_by_itemid_.end()); 2095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!known_itemid) { 2105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Nothing to retract, and nothing to publish. 2115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Probably a different state type. 2125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return; 2135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 2145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org info = info_by_itemid_[itemid]; 2155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org info_by_itemid_.erase(itemid); 2165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org new_state = default_state_; 2175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 2195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO: Assert new key matches the known key. It 2205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // shouldn't change! 2215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org info_by_itemid_[itemid] = info; 2225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::string key = key_serializer_->GetKey( 2255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org info.publisher_nick, info.published_nick); 2265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool has_old_state = (state_by_key_.find(key) != state_by_key_.end()); 2275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org C old_state = has_old_state ? state_by_key_[key] : default_state_; 2285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((retracted && !has_old_state) || StatesEqual(new_state, old_state)) { 2295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Nothing change, so don't bother signalling. 2305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return; 2315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (retracted || StatesEqual(new_state, default_state_)) { 2345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // We treat a default state similar to a retract. 2355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_by_key_.erase(key); 2365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 2375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_by_key_[key] = new_state; 2385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PubSubStateChange<C> change; 2415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org change.publisher_nick = info.publisher_nick; 2425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org change.published_nick = info.published_nick; 2435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org change.old_state = old_state; 2445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org change.new_state = new_state; 2455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalStateChange(change); 2465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void OnPublishResult(PubSubClient* pub_sub_client, 2495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& task_id, 2505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const XmlElement* item) { 2515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalPublishResult(task_id, item); 2525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void OnPublishError(PubSubClient* pub_sub_client, 2555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& task_id, 2565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const buzz::XmlElement* item, 2575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const buzz::XmlElement* stanza) { 2585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalPublishError(task_id, item, stanza); 2595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void OnRetractResult(PubSubClient* pub_sub_client, 2625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& task_id) { 2635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // There's no point in differentiating between publish and retract 2645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // errors, so we simplify by making them both signal a publish 2655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // result. 2665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const XmlElement* item = NULL; 2675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalPublishResult(task_id, item); 2685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void OnRetractError(PubSubClient* pub_sub_client, 2715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& task_id, 2725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const buzz::XmlElement* stanza) { 2735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // There's no point in differentiating between publish and retract 2745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // errors, so we simplify by making them both signal a publish 2755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // error. 2765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const XmlElement* item = NULL; 2775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalPublishError(task_id, item, stanza); 2785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::string publisher_nick_; 2815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PubSubClient* client_; 2825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const QName state_name_; 2835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org C default_state_; 2845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org talk_base::scoped_ptr<PubSubStateKeySerializer> key_serializer_; 2855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org talk_base::scoped_ptr<PubSubStateSerializer<C> > state_serializer_; 2865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // key => state 2875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::map<std::string, C> state_by_key_; 2885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // itemid => StateItemInfo 2895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::map<std::string, StateItemInfo> info_by_itemid_; 2905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 2915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass PresenterStateClient : public PubSubStateClient<bool> { 2935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public: 2945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PresenterStateClient(const std::string& publisher_nick, 2955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PubSubClient* client, 2965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const QName& state_name, 2975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool default_state) 2985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org : PubSubStateClient<bool>( 2995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org publisher_nick, client, state_name, default_state, 3005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org new PublishedNickKeySerializer(), NULL) { 3015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual void Publish(const std::string& published_nick, 3045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const bool& state, 3055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::string* task_id_out) { 3065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org XmlElement* presenter_elem = new XmlElement(QN_PRESENTER_PRESENTER, true); 3075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org presenter_elem->AddAttr(QN_NICK, published_nick); 3085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org XmlElement* presentation_item_elem = 3105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org new XmlElement(QN_PRESENTER_PRESENTATION_ITEM, false); 3115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& presentation_type = state ? kPresenting : kNotPresenting; 3125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org presentation_item_elem->AddAttr( 3135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org QN_PRESENTER_PRESENTATION_TYPE, presentation_type); 3145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // The Presenter state is kind of dumb in that it doesn't always use 3165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // retracts. It relies on setting the "type" to a special value. 3175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::string itemid = published_nick; 3185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::vector<XmlElement*> children; 3195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org children.push_back(presenter_elem); 3205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org children.push_back(presentation_item_elem); 3215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org client()->PublishItem(itemid, children, task_id_out); 3225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org protected: 3255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual bool ParseStateItem(const PubSubItem& item, 3265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StateItemInfo* info_out, 3275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool* state_out) { 3285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const XmlElement* presenter_elem = 3295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org item.elem->FirstNamed(QN_PRESENTER_PRESENTER); 3305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const XmlElement* presentation_item_elem = 3315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org item.elem->FirstNamed(QN_PRESENTER_PRESENTATION_ITEM); 3325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (presentation_item_elem == NULL || presenter_elem == NULL) { 3335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 3345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org info_out->publisher_nick = GetPublisherNickFromPubSubItem(item.elem); 3375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org info_out->published_nick = presenter_elem->Attr(QN_NICK); 3385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *state_out = (presentation_item_elem->Attr( 3395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org QN_PRESENTER_PRESENTATION_TYPE) != kNotPresenting); 3405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 3415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org virtual bool StatesEqual(bool state1, bool state2) { 3445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; // Make every item trigger an event, even if state doesn't change. 3455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 3475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgHangoutPubSubClient::HangoutPubSubClient(XmppTaskParentInterface* parent, 3495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const Jid& mucjid, 3505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& nick) 3515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org : mucjid_(mucjid), 3525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org nick_(nick) { 3535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org presenter_client_.reset(new PubSubClient(parent, mucjid, NS_PRESENTER)); 3545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org presenter_client_->SignalRequestError.connect( 3555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnPresenterRequestError); 3565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org media_client_.reset(new PubSubClient(parent, mucjid, NS_GOOGLE_MUC_MEDIA)); 3585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org media_client_->SignalRequestError.connect( 3595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnMediaRequestError); 3605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org presenter_state_client_.reset(new PresenterStateClient( 3625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org nick_, presenter_client_.get(), QN_PRESENTER_PRESENTER, false)); 3635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org presenter_state_client_->SignalStateChange.connect( 3645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnPresenterStateChange); 3655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org presenter_state_client_->SignalPublishResult.connect( 3665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnPresenterPublishResult); 3675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org presenter_state_client_->SignalPublishError.connect( 3685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnPresenterPublishError); 3695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org audio_mute_state_client_.reset(new PubSubStateClient<bool>( 3715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org nick_, media_client_.get(), QN_GOOGLE_MUC_AUDIO_MUTE, false, 3725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org new PublishedNickKeySerializer(), new BoolStateSerializer())); 3735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Can't just repeat because we need to watch for remote mutes. 3745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org audio_mute_state_client_->SignalStateChange.connect( 3755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnAudioMuteStateChange); 3765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org audio_mute_state_client_->SignalPublishResult.connect( 3775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnAudioMutePublishResult); 3785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org audio_mute_state_client_->SignalPublishError.connect( 3795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnAudioMutePublishError); 3805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org video_mute_state_client_.reset(new PubSubStateClient<bool>( 3825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org nick_, media_client_.get(), QN_GOOGLE_MUC_VIDEO_MUTE, false, 3835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org new PublishedNickKeySerializer(), new BoolStateSerializer())); 3845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Can't just repeat because we need to watch for remote mutes. 3855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org video_mute_state_client_->SignalStateChange.connect( 3865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnVideoMuteStateChange); 3875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org video_mute_state_client_->SignalPublishResult.connect( 3885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnVideoMutePublishResult); 3895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org video_mute_state_client_->SignalPublishError.connect( 3905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnVideoMutePublishError); 3915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org video_pause_state_client_.reset(new PubSubStateClient<bool>( 3935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org nick_, media_client_.get(), QN_GOOGLE_MUC_VIDEO_PAUSE, false, 3945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org new PublishedNickKeySerializer(), new BoolStateSerializer())); 3955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org video_pause_state_client_->SignalStateChange.connect( 3965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnVideoPauseStateChange); 3975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org video_pause_state_client_->SignalPublishResult.connect( 3985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnVideoPausePublishResult); 3995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org video_pause_state_client_->SignalPublishError.connect( 4005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnVideoPausePublishError); 4015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org recording_state_client_.reset(new PubSubStateClient<bool>( 4035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org nick_, media_client_.get(), QN_GOOGLE_MUC_RECORDING, false, 4045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org new PublishedNickKeySerializer(), new BoolStateSerializer())); 4055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org recording_state_client_->SignalStateChange.connect( 4065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnRecordingStateChange); 4075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org recording_state_client_->SignalPublishResult.connect( 4085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnRecordingPublishResult); 4095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org recording_state_client_->SignalPublishError.connect( 4105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnRecordingPublishError); 4115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org media_block_state_client_.reset(new PubSubStateClient<bool>( 4135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org nick_, media_client_.get(), QN_GOOGLE_MUC_MEDIA_BLOCK, false, 4145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org new PublisherAndPublishedNicksKeySerializer(), 4155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org new BoolStateSerializer())); 4165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org media_block_state_client_->SignalStateChange.connect( 4175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnMediaBlockStateChange); 4185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org media_block_state_client_->SignalPublishResult.connect( 4195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnMediaBlockPublishResult); 4205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org media_block_state_client_->SignalPublishError.connect( 4215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, &HangoutPubSubClient::OnMediaBlockPublishError); 4225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgHangoutPubSubClient::~HangoutPubSubClient() { 4255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::RequestAll() { 4285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org presenter_client_->RequestItems(); 4295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org media_client_->RequestItems(); 4305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnPresenterRequestError( 4335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PubSubClient* client, const XmlElement* stanza) { 4345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalRequestError(client->node(), stanza); 4355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnMediaRequestError( 4385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PubSubClient* client, const XmlElement* stanza) { 4395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalRequestError(client->node(), stanza); 4405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::PublishPresenterState( 4435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool presenting, std::string* task_id_out) { 4445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org presenter_state_client_->Publish(nick_, presenting, task_id_out); 4455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::PublishAudioMuteState( 4485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool muted, std::string* task_id_out) { 4495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org audio_mute_state_client_->Publish(nick_, muted, task_id_out); 4505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::PublishVideoMuteState( 4535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool muted, std::string* task_id_out) { 4545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org video_mute_state_client_->Publish(nick_, muted, task_id_out); 4555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::PublishVideoPauseState( 4585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool paused, std::string* task_id_out) { 4595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org video_pause_state_client_->Publish(nick_, paused, task_id_out); 4605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::PublishRecordingState( 4635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool recording, std::string* task_id_out) { 4645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org recording_state_client_->Publish(nick_, recording, task_id_out); 4655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Remote mute is accomplished by setting another client's mute state. 4685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::RemoteMute( 4695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& mutee_nick, std::string* task_id_out) { 4705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org audio_mute_state_client_->Publish(mutee_nick, true, task_id_out); 4715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Block media is accomplished by setting another client's block 4745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// state, kind of like remote mute. 4755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::BlockMedia( 4765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& blockee_nick, std::string* task_id_out) { 4775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org media_block_state_client_->Publish(blockee_nick, true, task_id_out); 4785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnPresenterStateChange( 4815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const PubSubStateChange<bool>& change) { 4825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalPresenterStateChange( 4835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org change.published_nick, change.old_state, change.new_state); 4845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnPresenterPublishResult( 4875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& task_id, const XmlElement* item) { 4885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalPublishPresenterResult(task_id); 4895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnPresenterPublishError( 4925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& task_id, const XmlElement* item, 4935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const XmlElement* stanza) { 4945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalPublishPresenterError(task_id, stanza); 4955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Since a remote mute is accomplished by another client setting our 4985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// mute state, if our state changes to muted, we should mute ourselves. 4995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Note that remote un-muting is disallowed by the RoomServer. 5005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnAudioMuteStateChange( 5015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const PubSubStateChange<bool>& change) { 5025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool was_muted = change.old_state; 5035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool is_muted = change.new_state; 5045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool remote_action = (!change.publisher_nick.empty() && 5055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org (change.publisher_nick != change.published_nick)); 5065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (remote_action) { 5075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& mutee_nick = change.published_nick; 5085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& muter_nick = change.publisher_nick; 5095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!is_muted) { 5105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // The server should prevent remote un-mute. 5115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_WARNING) << muter_nick << " remote unmuted " << mutee_nick; 5125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return; 5135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool should_mute_locally = (mutee_nick == nick_); 5155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalRemoteMute(mutee_nick, muter_nick, should_mute_locally); 5165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 5175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalAudioMuteStateChange(change.published_nick, was_muted, is_muted); 5185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 5205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst std::string GetAudioMuteNickFromItem(const XmlElement* item) { 5225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (item != NULL) { 5235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const XmlElement* audio_mute_state = 5245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org item->FirstNamed(QN_GOOGLE_MUC_AUDIO_MUTE); 5255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (audio_mute_state != NULL) { 5265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return audio_mute_state->Attr(QN_NICK); 5275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return std::string(); 5305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 5315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst std::string GetBlockeeNickFromItem(const XmlElement* item) { 5335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (item != NULL) { 5345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const XmlElement* media_block_state = 5355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org item->FirstNamed(QN_GOOGLE_MUC_MEDIA_BLOCK); 5365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (media_block_state != NULL) { 5375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return media_block_state->Attr(QN_NICK); 5385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return std::string(); 5415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 5425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnAudioMutePublishResult( 5445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& task_id, const XmlElement* item) { 5455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& mutee_nick = GetAudioMuteNickFromItem(item); 5465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (mutee_nick != nick_) { 5475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalRemoteMuteResult(task_id, mutee_nick); 5485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 5495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalPublishAudioMuteResult(task_id); 5505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 5525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnAudioMutePublishError( 5545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& task_id, const XmlElement* item, 5555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const XmlElement* stanza) { 5565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& mutee_nick = GetAudioMuteNickFromItem(item); 5575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (mutee_nick != nick_) { 5585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalRemoteMuteError(task_id, mutee_nick, stanza); 5595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 5605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalPublishAudioMuteError(task_id, stanza); 5615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 5635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnVideoMuteStateChange( 5655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const PubSubStateChange<bool>& change) { 5665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalVideoMuteStateChange( 5675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org change.published_nick, change.old_state, change.new_state); 5685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 5695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnVideoMutePublishResult( 5715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& task_id, const XmlElement* item) { 5725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalPublishVideoMuteResult(task_id); 5735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 5745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnVideoMutePublishError( 5765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& task_id, const XmlElement* item, 5775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const XmlElement* stanza) { 5785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalPublishVideoMuteError(task_id, stanza); 5795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 5805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnVideoPauseStateChange( 5825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const PubSubStateChange<bool>& change) { 5835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalVideoPauseStateChange( 5845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org change.published_nick, change.old_state, change.new_state); 5855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 5865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnVideoPausePublishResult( 5885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& task_id, const XmlElement* item) { 5895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalPublishVideoPauseResult(task_id); 5905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 5915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnVideoPausePublishError( 5935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& task_id, const XmlElement* item, 5945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const XmlElement* stanza) { 5955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalPublishVideoPauseError(task_id, stanza); 5965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 5975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnRecordingStateChange( 5995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const PubSubStateChange<bool>& change) { 6005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalRecordingStateChange( 6015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org change.published_nick, change.old_state, change.new_state); 6025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnRecordingPublishResult( 6055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& task_id, const XmlElement* item) { 6065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalPublishRecordingResult(task_id); 6075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnRecordingPublishError( 6105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& task_id, const XmlElement* item, 6115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const XmlElement* stanza) { 6125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalPublishRecordingError(task_id, stanza); 6135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnMediaBlockStateChange( 6165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const PubSubStateChange<bool>& change) { 6175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& blockee_nick = change.published_nick; 6185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& blocker_nick = change.publisher_nick; 6195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool was_blockee = change.old_state; 6215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool is_blockee = change.new_state; 6225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!was_blockee && is_blockee) { 6235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalMediaBlock(blockee_nick, blocker_nick); 6245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO: Should we bother signaling unblock? Currently 6265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // it isn't allowed, but it might happen when a participant leaves 6275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // the room and the item is retracted. 6285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnMediaBlockPublishResult( 6315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& task_id, const XmlElement* item) { 6325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& blockee_nick = GetBlockeeNickFromItem(item); 6335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalMediaBlockResult(task_id, blockee_nick); 6345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid HangoutPubSubClient::OnMediaBlockPublishError( 6375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& task_id, const XmlElement* item, 6385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const XmlElement* stanza) { 6395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::string& blockee_nick = GetBlockeeNickFromItem(item); 6405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SignalMediaBlockError(task_id, blockee_nick, stanza); 6415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} // namespace buzz 644