diff options
author | bauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-14 01:11:25 +0000 |
---|---|---|
committer | bauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-14 01:11:25 +0000 |
commit | 6f0321a0afe77f052ade3c9848edf0b56409e4c8 (patch) | |
tree | bf7de722b70bb89042839714bf37d2b9ac68178c | |
parent | 45a6ee05b536b41be6a218a994318bca50a5d86c (diff) | |
download | chromium_src-6f0321a0afe77f052ade3c9848edf0b56409e4c8.zip chromium_src-6f0321a0afe77f052ade3c9848edf0b56409e4c8.tar.gz chromium_src-6f0321a0afe77f052ade3c9848edf0b56409e4c8.tar.bz2 |
Add a method to tab_utils.h to find out whether a tab is playing audio.
BUG=3541
Review URL: https://chromiumcodereview.appspot.com/11573066
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@182364 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/media/audio_stream_indicator.cc | 79 | ||||
-rw-r--r-- | chrome/browser/media/audio_stream_indicator.h | 56 | ||||
-rw-r--r-- | chrome/browser/media/media_capture_devices_dispatcher.cc | 17 | ||||
-rw-r--r-- | chrome/browser/media/media_capture_devices_dispatcher.h | 10 | ||||
-rw-r--r-- | chrome/browser/ui/tabs/tab_utils.cc | 7 | ||||
-rw-r--r-- | chrome/browser/ui/tabs/tab_utils.h | 3 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | content/browser/renderer_host/media/audio_renderer_host.cc | 39 | ||||
-rw-r--r-- | content/browser/renderer_host/media/mock_media_observer.h | 5 | ||||
-rw-r--r-- | content/public/browser/media_observer.h | 7 |
10 files changed, 222 insertions, 3 deletions
diff --git a/chrome/browser/media/audio_stream_indicator.cc b/chrome/browser/media/audio_stream_indicator.cc new file mode 100644 index 0000000..39f0f46 --- /dev/null +++ b/chrome/browser/media/audio_stream_indicator.cc @@ -0,0 +1,79 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/media/audio_stream_indicator.h" + +#include "base/bind.h" +#include "chrome/browser/tab_contents/tab_util.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/invalidate_type.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" + +using content::BrowserThread; +using content::WebContents; + +AudioStreamIndicator::AudioStreamIndicator() {} +AudioStreamIndicator::~AudioStreamIndicator() {} + +void AudioStreamIndicator::UpdateWebContentsStatus(int render_process_id, + int render_view_id, + int stream_id, + bool playing) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&AudioStreamIndicator::UpdateWebContentsStatusOnUIThread, + this, render_process_id, render_view_id, stream_id, playing)); +} + +bool AudioStreamIndicator::IsPlayingAudio(WebContents* contents) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + RenderViewId id(contents->GetRenderProcessHost()->GetID(), + contents->GetRenderViewHost()->GetRoutingID()); + return audio_streams_.find(id) != audio_streams_.end(); +} + +AudioStreamIndicator::RenderViewId::RenderViewId(int render_process_id, + int render_view_id) + : render_process_id(render_process_id), + render_view_id(render_view_id) { +} + +bool AudioStreamIndicator::RenderViewId::operator<( + const RenderViewId& other) const { + if (render_process_id != other.render_process_id) + return render_process_id < other.render_process_id; + + return render_view_id < other.render_view_id; +} + +void AudioStreamIndicator::UpdateWebContentsStatusOnUIThread( + int render_process_id, + int render_view_id, + int stream_id, + bool playing) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + RenderViewId id(render_process_id, render_view_id); + if (playing) { + audio_streams_[id].insert(stream_id); + } else { + std::map<RenderViewId, std::set<int> >::iterator it = + audio_streams_.find(id); + if (it != audio_streams_.end()) + return; + + it->second.erase(stream_id); + if (it->second.empty()) + audio_streams_.erase(it); + } + + WebContents* web_contents = tab_util::GetWebContentsByID(render_process_id, + render_view_id); + if (web_contents) + web_contents->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TAB); +} diff --git a/chrome/browser/media/audio_stream_indicator.h b/chrome/browser/media/audio_stream_indicator.h new file mode 100644 index 0000000..03596b5 --- /dev/null +++ b/chrome/browser/media/audio_stream_indicator.h @@ -0,0 +1,56 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_MEDIA_AUDIO_STREAM_INDICATOR_H_ +#define CHROME_BROWSER_MEDIA_AUDIO_STREAM_INDICATOR_H_ + +#include <map> +#include <set> + +#include "base/memory/ref_counted.h" + +namespace content { +class WebContents; +} + +class AudioStreamIndicator + : public base::RefCountedThreadSafe<AudioStreamIndicator> { + public: + AudioStreamIndicator(); + + // This method should be called on the IO thread. + void UpdateWebContentsStatus(int render_process_id, + int render_view_id, + int stream_id, + bool playing); + + // This method should be called on the IO thread. + bool IsPlayingAudio(content::WebContents* contents); + + private: + struct RenderViewId { + RenderViewId(int render_process_id, + int render_view_id); + + // Required to use this struct in the std::multiset below. + bool operator<(const RenderViewId& other) const; + + int render_process_id; + int render_view_id; + }; + + friend class base::RefCountedThreadSafe<AudioStreamIndicator>; + virtual ~AudioStreamIndicator(); + + void UpdateWebContentsStatusOnUIThread(int render_process_id, + int render_view_id, + int stream_id, + bool playing); + + // A map from RenderViews to sets of streams playing in them (each RenderView + // might have more than one stream). + std::map<RenderViewId, std::set<int> > audio_streams_; +}; + +#endif // CHROME_BROWSER_MEDIA_AUDIO_STREAM_INDICATOR_H_ diff --git a/chrome/browser/media/media_capture_devices_dispatcher.cc b/chrome/browser/media/media_capture_devices_dispatcher.cc index f1d6165..7b2e693 100644 --- a/chrome/browser/media/media_capture_devices_dispatcher.cc +++ b/chrome/browser/media/media_capture_devices_dispatcher.cc @@ -5,6 +5,7 @@ #include "chrome/browser/media/media_capture_devices_dispatcher.h" #include "base/prefs/pref_service.h" +#include "chrome/browser/media/audio_stream_indicator.h" #include "chrome/browser/media/media_stream_capture_indicator.h" #include "chrome/browser/prefs/pref_registry_syncable.h" #include "chrome/browser/prefs/scoped_user_pref_update.h" @@ -44,7 +45,8 @@ MediaCaptureDevicesDispatcher* MediaCaptureDevicesDispatcher::GetInstance() { MediaCaptureDevicesDispatcher::MediaCaptureDevicesDispatcher() : devices_enumerated_(false), - media_stream_capture_indicator_(new MediaStreamCaptureIndicator()) {} + media_stream_capture_indicator_(new MediaStreamCaptureIndicator()), + audio_stream_indicator_(new AudioStreamIndicator()) {} MediaCaptureDevicesDispatcher::~MediaCaptureDevicesDispatcher() {} @@ -149,6 +151,11 @@ scoped_refptr<MediaStreamCaptureIndicator> return media_stream_capture_indicator_; } +scoped_refptr<AudioStreamIndicator> +MediaCaptureDevicesDispatcher::GetAudioStreamIndicator() { + return audio_stream_indicator_; +} + void MediaCaptureDevicesDispatcher::OnCaptureDevicesOpened( int render_process_id, int render_view_id, @@ -202,6 +209,14 @@ void MediaCaptureDevicesDispatcher::OnMediaRequestStateChanged( } +void MediaCaptureDevicesDispatcher::OnAudioStreamPlayingChanged( + int render_process_id, int render_view_id, int stream_id, bool playing) { + audio_stream_indicator_->UpdateWebContentsStatus(render_process_id, + render_view_id, + stream_id, + playing); +} + void MediaCaptureDevicesDispatcher::UpdateAudioDevicesOnUIThread( const content::MediaStreamDevices& devices) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); diff --git a/chrome/browser/media/media_capture_devices_dispatcher.h b/chrome/browser/media/media_capture_devices_dispatcher.h index 8c35331..bd6a013 100644 --- a/chrome/browser/media/media_capture_devices_dispatcher.h +++ b/chrome/browser/media/media_capture_devices_dispatcher.h @@ -12,6 +12,7 @@ #include "content/public/browser/media_observer.h" #include "content/public/common/media_stream_request.h" +class AudioStreamIndicator; class MediaStreamCaptureIndicator; class PrefRegistrySyncable; class PrefService; @@ -93,9 +94,16 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver { int render_view_id, const content::MediaStreamDevice& device, content::MediaRequestState state) OVERRIDE; + virtual void OnAudioStreamPlayingChanged( + int render_process_id, + int render_view_id, + int stream_id, + bool playing) OVERRIDE; scoped_refptr<MediaStreamCaptureIndicator> GetMediaStreamCaptureIndicator(); + scoped_refptr<AudioStreamIndicator> GetAudioStreamIndicator(); + private: friend struct DefaultSingletonTraits<MediaCaptureDevicesDispatcher>; @@ -125,6 +133,8 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver { bool devices_enumerated_; scoped_refptr<MediaStreamCaptureIndicator> media_stream_capture_indicator_; + + scoped_refptr<AudioStreamIndicator> audio_stream_indicator_; }; #endif // CHROME_BROWSER_MEDIA_MEDIA_CAPTURE_DEVICES_DISPATCHER_H_ diff --git a/chrome/browser/ui/tabs/tab_utils.cc b/chrome/browser/ui/tabs/tab_utils.cc index 541de63..a6d5ad6 100644 --- a/chrome/browser/ui/tabs/tab_utils.cc +++ b/chrome/browser/ui/tabs/tab_utils.cc @@ -4,6 +4,7 @@ #include "chrome/browser/ui/tabs/tab_utils.h" +#include "chrome/browser/media/audio_stream_indicator.h" #include "chrome/browser/media/media_capture_devices_dispatcher.h" #include "chrome/browser/media/media_stream_capture_indicator.h" #include "content/public/browser/render_process_host.h" @@ -34,4 +35,10 @@ bool ShouldShowRecordingIndicator(content::WebContents* contents) { indicator->IsBeingMirrored(render_process_id, render_view_id); } +bool ShouldShowAudioIndicator(content::WebContents* contents) { + AudioStreamIndicator* audio_indicator = + MediaCaptureDevicesDispatcher::GetInstance()->GetAudioStreamIndicator(); + return audio_indicator->IsPlayingAudio(contents); +} + } // namespace chrome diff --git a/chrome/browser/ui/tabs/tab_utils.h b/chrome/browser/ui/tabs/tab_utils.h index aef6c4e..aca9cfc 100644 --- a/chrome/browser/ui/tabs/tab_utils.h +++ b/chrome/browser/ui/tabs/tab_utils.h @@ -17,6 +17,9 @@ bool ShouldShowProjectingIndicator(content::WebContents* contents); // Returns whether we should show a recording favicon indicator for this tab. bool ShouldShowRecordingIndicator(content::WebContents* contents); +// Returns whether we should show an audio favicon indicator for this tab. +bool ShouldShowAudioIndicator(content::WebContents* contents); + } // namespace chrome #endif // CHROME_BROWSER_UI_TABS_TAB_UTILS_H_ diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index c180a05..9bc58db6 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1013,6 +1013,8 @@ 'browser/managed_mode/managed_user_service.h', 'browser/managed_mode/managed_user_service_factory.cc', 'browser/managed_mode/managed_user_service_factory.h', + 'browser/media/audio_stream_indicator.cc', + 'browser/media/audio_stream_indicator.h', 'browser/media/media_capture_devices_dispatcher.cc', 'browser/media/media_capture_devices_dispatcher.h', 'browser/media/media_stream_capture_indicator.cc', diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc index 6c028bb..f57d182 100644 --- a/content/browser/renderer_host/media/audio_renderer_host.cc +++ b/content/browser/renderer_host/media/audio_renderer_host.cc @@ -13,6 +13,8 @@ #include "content/browser/renderer_host/media/audio_mirroring_manager.h" #include "content/browser/renderer_host/media/audio_sync_reader.h" #include "content/common/media/audio_messages.h" +#include "content/public/browser/content_browser_client.h" +#include "content/public/browser/media_observer.h" #include "media/audio/shared_memory_util.h" #include "media/base/audio_bus.h" #include "media/base/limits.h" @@ -332,6 +334,9 @@ void AudioRendererHost::OnAssociateStreamWithProducer(int stream_id, if (entry->render_view_id == render_view_id) return; + // TODO(miu): Merge "AssociateWithProducer" message into "CreateStream" + // message so AudioRendererHost can assume a simpler "render_view_id is set + // once" scheme. http://crbug.com/166779 if (mirroring_manager_) { mirroring_manager_->RemoveDiverter( render_process_id_, entry->render_view_id, entry->controller); @@ -355,6 +360,13 @@ void AudioRendererHost::OnPlayStream(int stream_id) { entry->controller->Play(); if (media_internals_) media_internals_->OnSetAudioStreamPlaying(this, stream_id, true); + + MediaObserver* media_observer = + GetContentClient()->browser()->GetMediaObserver(); + if (media_observer) { + media_observer->OnAudioStreamPlayingChanged( + render_process_id_, entry->render_view_id, stream_id, true); + } } void AudioRendererHost::OnPauseStream(int stream_id) { @@ -369,6 +381,13 @@ void AudioRendererHost::OnPauseStream(int stream_id) { entry->controller->Pause(); if (media_internals_) media_internals_->OnSetAudioStreamPlaying(this, stream_id, false); + + MediaObserver* media_observer = + GetContentClient()->browser()->GetMediaObserver(); + if (media_observer) { + media_observer->OnAudioStreamPlayingChanged( + render_process_id_, entry->render_view_id, stream_id, false); + } } void AudioRendererHost::OnFlushStream(int stream_id) { @@ -393,8 +412,10 @@ void AudioRendererHost::OnCloseStream(int stream_id) { AudioEntry* entry = LookupById(stream_id); - if (entry) - CloseAndDeleteStream(entry); + if (!entry) + return; + + CloseAndDeleteStream(entry); } void AudioRendererHost::OnSetVolume(int stream_id, double volume) { @@ -412,6 +433,14 @@ void AudioRendererHost::OnSetVolume(int stream_id, double volume) { entry->controller->SetVolume(volume); if (media_internals_) media_internals_->OnSetAudioStreamVolume(this, stream_id, volume); + + MediaObserver* media_observer = + GetContentClient()->browser()->GetMediaObserver(); + if (media_observer) { + bool playing = volume > 0; + media_observer->OnAudioStreamPlayingChanged( + render_process_id_, entry->render_view_id, stream_id, playing); + } } void AudioRendererHost::SendErrorMessage(int32 stream_id) { @@ -431,6 +460,12 @@ void AudioRendererHost::DeleteEntries() { void AudioRendererHost::CloseAndDeleteStream(AudioEntry* entry) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + MediaObserver* media_observer = + GetContentClient()->browser()->GetMediaObserver(); + if (media_observer) { + media_observer->OnAudioStreamPlayingChanged( + render_process_id_, entry->render_view_id, entry->stream_id, false); + } if (!entry->pending_close) { if (mirroring_manager_) { mirroring_manager_->RemoveDiverter( diff --git a/content/browser/renderer_host/media/mock_media_observer.h b/content/browser/renderer_host/media/mock_media_observer.h index 3c97f0a..f2a7bd7 100644 --- a/content/browser/renderer_host/media/mock_media_observer.h +++ b/content/browser/renderer_host/media/mock_media_observer.h @@ -34,6 +34,11 @@ class MockMediaObserver : public MediaObserver { void(int render_process_id, int render_view_id, const MediaStreamDevice& device, const MediaRequestState state)); + MOCK_METHOD4(OnAudioStreamPlayingChanged, + void(int render_process_id, + int render_view_id, + int stream_id, + bool playing)); }; class MockMediaInternals : public MediaInternals { diff --git a/content/public/browser/media_observer.h b/content/public/browser/media_observer.h index 4bf7c00..c1727df 100644 --- a/content/public/browser/media_observer.h +++ b/content/public/browser/media_observer.h @@ -41,6 +41,13 @@ class MediaObserver { const MediaStreamDevice& device, MediaRequestState state) = 0; + // Called when an audio stream is played or paused. + virtual void OnAudioStreamPlayingChanged( + int render_process_id, + int render_view_id, + int stream_id, + bool playing) = 0; + protected: virtual ~MediaObserver() {} }; |