Update to libjingle 0.5.8.

git-svn-id: http://libjingle.googlecode.com/svn/trunk@72 dd674b97-3498-5ee5-1854-bdd07cd0ff33
diff --git a/CHANGELOG b/CHANGELOG
index 427a699..8ab3d49 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,8 @@
 Libjingle
 
+0.5.8 - July 1, 2011
+  - Support for loudest speaker detection
+
 0.5.7 - Jun 23, 2011
   - Support for setting MUC display name
   - Update STUN support to RFC5389
diff --git a/talk/examples/call/callclient.cc b/talk/examples/call/callclient.cc
index da2716f..3fbd579 100644
--- a/talk/examples/call/callclient.cc
+++ b/talk/examples/call/callclient.cc
@@ -49,6 +49,7 @@
 #include "talk/p2p/client/sessionmanagertask.h"
 #include "talk/session/phone/devicemanager.h"
 #include "talk/session/phone/mediaengine.h"
+#include "talk/session/phone/mediamessages.h"
 #include "talk/session/phone/mediasessionclient.h"
 #include "talk/session/phone/videorendererfactory.h"
 #include "talk/xmpp/constants.h"
@@ -416,11 +417,29 @@
     console_->PrintLine("call not answered");
   } else if (state == cricket::Session::STATE_INPROGRESS) {
     console_->PrintLine("call in progress");
+    call->SignalSpeakerMonitor.connect(this, &CallClient::OnSpeakerChanged);
+    call->StartSpeakerMonitor(session);
   } else if (state == cricket::Session::STATE_RECEIVEDTERMINATE) {
     console_->PrintLine("other side hung up");
   }
 }
 
+void CallClient::OnSpeakerChanged(cricket::Call* call,
+                                  cricket::BaseSession* session,
+                                  const cricket::NamedSource& speaker) {
+  if (speaker.ssrc == 0) {
+    console_->PrintLine("Session %s has no current speaker.",
+                        session->id().c_str());
+  } else if (speaker.nick.empty()) {
+    console_->PrintLine("Session %s speaker change to unknown (%u).",
+                        session->id().c_str(), speaker.ssrc);
+  } else {
+    console_->PrintLine("Session %s speaker changed to %s (%u).",
+                        session->id().c_str(), speaker.nick.c_str(),
+                        speaker.ssrc);
+  }
+}
+
 void CallClient::InitPresence() {
   presence_push_ = new buzz::PresencePushTask(xmpp_client_, this);
   presence_push_->SignalStatusUpdate.connect(
@@ -477,6 +496,7 @@
   if (status.available() && status.voice_capability()) {
      console_->PrintLine("Adding to roster: %s", key.c_str());
     (*roster_)[key] = item;
+    // TODO: Make some of these constants.
   } else {
     console_->PrintLine("Removing from roster: %s", key.c_str());
     RosterMap::iterator iter = roster_->find(key);
diff --git a/talk/examples/call/callclient.h b/talk/examples/call/callclient.h
index e39c9d4..5bfeb87 100644
--- a/talk/examples/call/callclient.h
+++ b/talk/examples/call/callclient.h
@@ -34,6 +34,7 @@
 
 #include "talk/p2p/base/session.h"
 #include "talk/session/phone/mediachannel.h"
+#include "talk/session/phone/mediamessages.h"
 #include "talk/session/phone/mediasessionclient.h"
 #include "talk/xmpp/xmppclient.h"
 #include "talk/examples/call/status.h"
@@ -65,6 +66,7 @@
 class PortAllocator;
 class MediaEngine;
 class MediaSessionClient;
+class NamedSource;
 class Receiver;
 class Call;
 struct CallOptions;
@@ -166,6 +168,9 @@
   void OnMediaSourcesUpdate(cricket::Call* call,
                             cricket::Session* session,
                             const cricket::MediaSources& sources);
+  void OnSpeakerChanged(cricket::Call* call,
+                        cricket::BaseSession* session,
+                        const cricket::NamedSource& speaker_source);
   void OnRoomLookupResponse(const buzz::MucRoomInfo& room_info);
   void OnRoomLookupError(const buzz::XmlElement* stanza);
   buzz::Jid GenerateRandomMucJid();
diff --git a/talk/session/phone/call.cc b/talk/session/phone/call.cc
index 27ea76f..5925e30 100644
--- a/talk/session/phone/call.cc
+++ b/talk/session/phone/call.cc
@@ -44,6 +44,8 @@
 const int kSendToVoicemailTimeout = 1000*20;
 const int kNoVoicemailTimeout = 1000*180;
 const int kMediaMonitorInterval = 1000*15;
+// In order to be the same as the server-side switching, this must be 100.
+const int kAudioMonitorPollPeriodMillis = 100;
 }
 
 Call::Call(MediaSessionClient* session_client)
@@ -319,6 +321,9 @@
     session_client_->channel_manager()->DestroyVoiceChannel(voice_channel);
   }
 
+  // Destroy speaker monitor
+  StopSpeakerMonitor(session);
+
   // Signal client
   SignalRemoveSession(this, session);
 
@@ -479,6 +484,43 @@
   }
 }
 
+bool Call::IsAudioMonitorRunning(BaseSession *session) {
+  VoiceChannel *voice_channel = GetVoiceChannel(session);
+  if (voice_channel) {
+    return voice_channel->IsAudioMonitorRunning();
+  } else {
+    return false;
+  }
+}
+
+void Call::StartSpeakerMonitor(BaseSession *session) {
+  if (speaker_monitor_map_.find(session->id()) == speaker_monitor_map_.end()) {
+    if (!IsAudioMonitorRunning(session)) {
+      StartAudioMonitor(session, kAudioMonitorPollPeriodMillis);
+    }
+    CurrentSpeakerMonitor* speaker_monitor =
+        new cricket::CurrentSpeakerMonitor(this, session);
+    speaker_monitor->SignalUpdate.connect(this, &Call::OnSpeakerMonitor);
+    speaker_monitor->Start();
+    speaker_monitor_map_[session->id()] = speaker_monitor;
+  } else {
+    LOG(LS_WARNING) << "Already started speaker monitor for session "
+                    << session->id() << ".";
+  }
+}
+
+void Call::StopSpeakerMonitor(BaseSession *session) {
+  if (speaker_monitor_map_.find(session->id()) == speaker_monitor_map_.end()) {
+    LOG(LS_WARNING) << "Speaker monitor for session "
+                    << session->id() << " already stopped.";
+  } else {
+    CurrentSpeakerMonitor* monitor = speaker_monitor_map_[session->id()];
+    monitor->Stop();
+    speaker_monitor_map_.erase(session->id());
+    delete monitor;
+  }
+}
+
 void Call::OnConnectionMonitor(VoiceChannel *channel,
                                const std::vector<ConnectionInfo> &infos) {
   SignalConnectionMonitor(this, infos);
@@ -492,6 +534,13 @@
   SignalAudioMonitor(this, info);
 }
 
+void Call::OnSpeakerMonitor(CurrentSpeakerMonitor* monitor, uint32 ssrc) {
+  NamedSource source;
+  source.ssrc = ssrc;
+  media_sources_.GetAudioSourceBySsrc(ssrc, &source);
+  SignalSpeakerMonitor(this, monitor->session(), source);
+}
+
 void Call::OnConnectionMonitor(VideoChannel *channel,
                                const std::vector<ConnectionInfo> &infos) {
   SignalVideoConnectionMonitor(this, infos);
diff --git a/talk/session/phone/call.h b/talk/session/phone/call.h
index 38e0684..19dc59a 100644
--- a/talk/session/phone/call.h
+++ b/talk/session/phone/call.h
@@ -37,6 +37,7 @@
 #include "talk/p2p/client/socketmonitor.h"
 #include "talk/xmpp/jid.h"
 #include "talk/session/phone/audiomonitor.h"
+#include "talk/session/phone/currentspeakermonitor.h"
 #include "talk/session/phone/mediamessages.h"
 #include "talk/session/phone/voicechannel.h"
 
@@ -64,6 +65,9 @@
   void StopConnectionMonitor(BaseSession *session);
   void StartAudioMonitor(BaseSession *session, int cms);
   void StopAudioMonitor(BaseSession *session);
+  bool IsAudioMonitorRunning(BaseSession *session);
+  void StartSpeakerMonitor(BaseSession *session);
+  void StopSpeakerMonitor(BaseSession *session);
   void Mute(bool mute);
   void PressDTMF(int event);
 
@@ -94,6 +98,11 @@
       SignalConnectionMonitor;
   sigslot::signal2<Call *, const VoiceMediaInfo&> SignalMediaMonitor;
   sigslot::signal2<Call *, const AudioInfo&> SignalAudioMonitor;
+  // Empty nick on NamedSource means "unknown".
+  // Ssrc of 0 on NamedSource means "no current speaker".
+  sigslot::signal3<Call *,
+                   BaseSession *,
+                   const NamedSource&> SignalSpeakerMonitor;
   sigslot::signal2<Call *, const std::vector<ConnectionInfo> &>
       SignalVideoConnectionMonitor;
   sigslot::signal2<Call *, const VideoMediaInfo&> SignalVideoMediaMonitor;
@@ -117,6 +126,7 @@
                            const std::vector<ConnectionInfo> &infos);
   void OnMediaMonitor(VoiceChannel *channel, const VoiceMediaInfo& info);
   void OnAudioMonitor(VoiceChannel *channel, const AudioInfo& info);
+  void OnSpeakerMonitor(CurrentSpeakerMonitor* monitor, uint32 ssrc);
   void OnConnectionMonitor(VideoChannel *channel,
                            const std::vector<ConnectionInfo> &infos);
   void OnMediaMonitor(VideoChannel *channel, const VideoMediaInfo& info);
@@ -134,6 +144,7 @@
   MediaSources media_sources_;
   std::map<std::string, VoiceChannel *> voice_channel_map_;
   std::map<std::string, VideoChannel *> video_channel_map_;
+  std::map<std::string, CurrentSpeakerMonitor *> speaker_monitor_map_;
   VideoRenderer* local_renderer_;
   bool video_;
   bool muted_;
diff --git a/talk/session/phone/channel.cc b/talk/session/phone/channel.cc
index b23d877..05366a5 100644
--- a/talk/session/phone/channel.cc
+++ b/talk/session/phone/channel.cc
@@ -729,6 +729,10 @@
   }
 }
 
+bool VoiceChannel::IsAudioMonitorRunning() const {
+  return (audio_monitor_.get() != NULL);
+}
+
 int VoiceChannel::GetInputLevel_w() {
   return media_engine()->GetInputLevel();
 }
diff --git a/talk/session/phone/channel.h b/talk/session/phone/channel.h
index 7d6577a..241ca79 100644
--- a/talk/session/phone/channel.h
+++ b/talk/session/phone/channel.h
@@ -298,6 +298,7 @@
 
   void StartAudioMonitor(int cms);
   void StopAudioMonitor();
+  bool IsAudioMonitorRunning() const;
   sigslot::signal2<VoiceChannel*, const AudioInfo&> SignalAudioMonitor;
 
   int GetInputLevel_w();
diff --git a/talk/session/phone/currentspeakermonitor.cc b/talk/session/phone/currentspeakermonitor.cc
index d2d4d9a..bfc20a2 100644
--- a/talk/session/phone/currentspeakermonitor.cc
+++ b/talk/session/phone/currentspeakermonitor.cc
@@ -26,7 +26,9 @@
  */
 
 #include "talk/session/phone/currentspeakermonitor.h"
+
 #include "talk/base/logging.h"
+#include "talk/session/phone/call.h"
 
 namespace cricket {
 
@@ -37,7 +39,7 @@
 const int kDefaultMinTimeBetweenSwitches = 1000;
 }
 
-CurrentSpeakerMonitor::CurrentSpeakerMonitor(Call* call, Session* session)
+CurrentSpeakerMonitor::CurrentSpeakerMonitor(Call* call, BaseSession* session)
     : started_(false),
       call_(call),
       session_(session),
@@ -184,7 +186,8 @@
   }
 }
 
-void CurrentSpeakerMonitor::OnMediaSourcesUpdate(Call* call, Session* session,
+void CurrentSpeakerMonitor::OnMediaSourcesUpdate(Call* call,
+                                                 Session* session,
                                                  const MediaSources& sources) {
   if (call == call_ && session == session_) {
     // Update the speaking state map based on new or removed sources.
diff --git a/talk/session/phone/currentspeakermonitor.h b/talk/session/phone/currentspeakermonitor.h
index 36e23d9..adf6b48 100644
--- a/talk/session/phone/currentspeakermonitor.h
+++ b/talk/session/phone/currentspeakermonitor.h
@@ -33,18 +33,26 @@
 
 #include <map>
 
-#include "talk/session/phone/call.h"
+#include "talk/base/basictypes.h"
 #include "talk/base/sigslot.h"
 
 namespace cricket {
 
+class AudioInfo;
+class BaseSession;
+class Call;
+class MediaSources;
+class Session;
+
 // Note that the call's audio monitor must be started before this is started.
 // It's recommended that the audio monitor be started with a 100 ms period.
 class CurrentSpeakerMonitor : public sigslot::has_slots<> {
  public:
-  CurrentSpeakerMonitor(Call* call, Session* session);
+  CurrentSpeakerMonitor(Call* call, BaseSession* session);
   ~CurrentSpeakerMonitor();
 
+  BaseSession* session() const { return session_; }
+
   void Start();
   void Stop();
 
@@ -77,7 +85,7 @@
 
   bool started_;
   Call* call_;
-  Session* session_;
+  BaseSession* session_;
   std::map<uint32, SpeakingState> ssrc_to_speaking_state_map_;
   uint32 current_speaker_ssrc_;
   // To prevent overswitching, switching is disabled for some time after a