Bug 811222 - Enable system app to get currently used audio channel. r=sicking a=blocking-basecamp
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 05 Dec 2012 17:20:59 -0800
changeset 118634 c07a72d3f2353228728fd278f40aec9e2984322c
parent 118633 6751e12f4f82dfa09b80b72c6feb22284bf9fbea
child 118635 4dc82515e37db821453314ff13a03f16569c437f
push id2870
push usersicking@mozilla.com
push dateThu, 06 Dec 2012 08:16:25 +0000
treeherdermozilla-aurora@4dc82515e37d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking, blocking-basecamp
bugs811222
milestone19.0a2
Bug 811222 - Enable system app to get currently used audio channel. r=sicking a=blocking-basecamp
b2g/chrome/content/shell.js
dom/audiochannel/AudioChannelService.cpp
dom/audiochannel/AudioChannelService.h
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -917,16 +917,25 @@ window.addEventListener('ContentStart', 
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     shell.sendChromeEvent({
       type: 'headphones-status-changed',
       state: aData
     });
 }, "headphones-status-changed", false);
 })();
 
+(function audioChannelChangedTracker() {
+  Services.obs.addObserver(function(aSubject, aTopic, aData) {
+    shell.sendChromeEvent({
+      type: 'audio-channel-changed',
+      channel: aData
+    });
+}, "audio-channel-changed", false);
+})();
+
 (function recordingStatusTracker() {
   let gRecordingActiveCount = 0;
 
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     let oldCount = gRecordingActiveCount;
     if (aData == "starting") {
       gRecordingActiveCount += 1;
     } else if (aData == "shutdown") {
--- a/dom/audiochannel/AudioChannelService.cpp
+++ b/dom/audiochannel/AudioChannelService.cpp
@@ -50,16 +50,17 @@ AudioChannelService::Shutdown()
     delete gAudioChannelService;
     gAudioChannelService = nullptr;
   }
 }
 
 NS_IMPL_ISUPPORTS0(AudioChannelService)
 
 AudioChannelService::AudioChannelService()
+: mCurrentHigherChannel(AUDIO_CHANNEL_NORMAL)
 {
   mChannelCounters = new int32_t[AUDIO_CHANNEL_PUBLICNOTIFICATION+1];
 
   for (int i = AUDIO_CHANNEL_NORMAL;
        i <= AUDIO_CHANNEL_PUBLICNOTIFICATION;
        ++i) {
     mChannelCounters[i] = 0;
   }
@@ -122,35 +123,61 @@ AudioChannelService::GetMuted(AudioChann
       case AUDIO_CHANNEL_ALARM:
       case AUDIO_CHANNEL_TELEPHONY:
       case AUDIO_CHANNEL_PUBLICNOTIFICATION:
         // Nothing to do
         break;
     }
   }
 
+  bool muted = false;
+
   // Priorities:
   switch (aType) {
     case AUDIO_CHANNEL_NORMAL:
     case AUDIO_CHANNEL_CONTENT:
-      return !!mChannelCounters[AUDIO_CHANNEL_NOTIFICATION] ||
-             !!mChannelCounters[AUDIO_CHANNEL_ALARM] ||
-             !!mChannelCounters[AUDIO_CHANNEL_TELEPHONY] ||
-             !!mChannelCounters[AUDIO_CHANNEL_PUBLICNOTIFICATION];
+      muted = !!mChannelCounters[AUDIO_CHANNEL_NOTIFICATION] ||
+              !!mChannelCounters[AUDIO_CHANNEL_ALARM] ||
+              !!mChannelCounters[AUDIO_CHANNEL_TELEPHONY] ||
+              !!mChannelCounters[AUDIO_CHANNEL_PUBLICNOTIFICATION];
 
     case AUDIO_CHANNEL_NOTIFICATION:
     case AUDIO_CHANNEL_ALARM:
     case AUDIO_CHANNEL_TELEPHONY:
-      return ChannelsActiveWithHigherPriorityThan(aType);
+      muted = ChannelsActiveWithHigherPriorityThan(aType);
 
     case AUDIO_CHANNEL_PUBLICNOTIFICATION:
-      return false;
+      break;
   }
 
-  return false;
+  // Notification if needed.
+  if (!muted) {
+
+    // Calculating the most important unmuted channel:
+    AudioChannelType higher = AUDIO_CHANNEL_NORMAL;
+    for (int32_t type = AUDIO_CHANNEL_NORMAL;
+         type <= AUDIO_CHANNEL_PUBLICNOTIFICATION;
+         ++type) {
+      if (mChannelCounters[type]) {
+        higher = (AudioChannelType)type;
+      }
+    }
+
+    if (higher != mCurrentHigherChannel) {
+      mCurrentHigherChannel = higher;
+
+      nsString channelName;
+      channelName.AssignASCII(ChannelName(mCurrentHigherChannel));
+
+      nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+      obs->NotifyObservers(nullptr, "audio-channel-changed", channelName.get());
+    }
+  }
+
+  return muted;
 }
 
 
 static PLDHashOperator
 NotifyEnumerator(nsHTMLMediaElement* aElement,
                  AudioChannelType aType, void* aData)
 {
   if (aElement) {
@@ -179,8 +206,35 @@ AudioChannelService::ChannelsActiveWithH
 
     if (mChannelCounters[i]) {
       return true;
     }
   }
 
   return false;
 }
+
+const char*
+AudioChannelService::ChannelName(AudioChannelType aType)
+{
+  static struct {
+    int32_t type;
+    const char* value;
+  } ChannelNameTable[] = {
+    { AUDIO_CHANNEL_NORMAL,             "normal" },
+    { AUDIO_CHANNEL_CONTENT,            "normal" },
+    { AUDIO_CHANNEL_NOTIFICATION,       "notification" },
+    { AUDIO_CHANNEL_ALARM,              "alarm" },
+    { AUDIO_CHANNEL_TELEPHONY,          "telephony" },
+    { AUDIO_CHANNEL_PUBLICNOTIFICATION, "publicnotification" },
+    { -1,                               "unknown" }
+  };
+
+  for (int i = AUDIO_CHANNEL_NORMAL; ; ++i) {
+    if (ChannelNameTable[i].type == aType ||
+        ChannelNameTable[i].type == -1) {
+      return ChannelNameTable[i].value;
+    }
+  }
+
+  NS_NOTREACHED("Execution should not reach here!");
+  return nullptr;
+}
--- a/dom/audiochannel/AudioChannelService.h
+++ b/dom/audiochannel/AudioChannelService.h
@@ -54,17 +54,21 @@ public:
   void Notify();
 
 protected:
   AudioChannelService();
   virtual ~AudioChannelService();
 
   bool ChannelsActiveWithHigherPriorityThan(AudioChannelType aType);
 
+  const char* ChannelName(AudioChannelType aType);
+
   nsDataHashtable< nsPtrHashKey<nsHTMLMediaElement>, AudioChannelType > mMediaElements;
 
   int32_t* mChannelCounters;
+
+  AudioChannelType mCurrentHigherChannel;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif