Commit aa44546e authored by jam@chromium.org's avatar jam@chromium.org

Minor cleanup to remove the static thread-safe methods on BrowserMainLoop....

Minor cleanup to remove the static thread-safe methods on BrowserMainLoop. Initially I thought this would be one getter so it seemed fine, but now it has 3 and more are on the way. Switch to one static getter for this class, and then getters for the member variables. I used dependency injection to allow access to these objects from other threads, which also cleaned up tests a bit.

R=scherkus@chromium.org

Review URL: https://codereview.chromium.org/17508005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207871 0039d316-1c4b-4281-b951-d872f2087c98
parent 9a61fe16
...@@ -137,9 +137,7 @@ const MediaStreamDevices& ...@@ -137,9 +137,7 @@ const MediaStreamDevices&
MediaCaptureDevicesDispatcher::GetAudioCaptureDevices() { MediaCaptureDevicesDispatcher::GetAudioCaptureDevices() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!is_device_enumeration_disabled_ && !devices_enumerated_) { if (!is_device_enumeration_disabled_ && !devices_enumerated_) {
BrowserThread::PostTask( content::EnsureMonitorCaptureDevices();
BrowserThread::IO, FROM_HERE,
base::Bind(&content::EnsureMonitorCaptureDevices));
devices_enumerated_ = true; devices_enumerated_ = true;
} }
return audio_devices_; return audio_devices_;
...@@ -149,9 +147,7 @@ const MediaStreamDevices& ...@@ -149,9 +147,7 @@ const MediaStreamDevices&
MediaCaptureDevicesDispatcher::GetVideoCaptureDevices() { MediaCaptureDevicesDispatcher::GetVideoCaptureDevices() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!is_device_enumeration_disabled_ && !devices_enumerated_) { if (!is_device_enumeration_disabled_ && !devices_enumerated_) {
BrowserThread::PostTask( content::EnsureMonitorCaptureDevices();
BrowserThread::IO, FROM_HERE,
base::Bind(&content::EnsureMonitorCaptureDevices));
devices_enumerated_ = true; devices_enumerated_ = true;
} }
return video_devices_; return video_devices_;
......
...@@ -276,21 +276,12 @@ class BrowserMainLoop::MemoryObserver : public base::MessageLoop::TaskObserver { ...@@ -276,21 +276,12 @@ class BrowserMainLoop::MemoryObserver : public base::MessageLoop::TaskObserver {
}; };
// static // BrowserMainLoop construction / destruction =============================
media::AudioManager* BrowserMainLoop::GetAudioManager() {
return g_current_browser_main_loop->audio_manager_.get();
}
// static
AudioMirroringManager* BrowserMainLoop::GetAudioMirroringManager() {
return g_current_browser_main_loop->audio_mirroring_manager_.get();
}
// static BrowserMainLoop* BrowserMainLoop::GetInstance() {
MediaStreamManager* BrowserMainLoop::GetMediaStreamManager() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return g_current_browser_main_loop->media_stream_manager_.get(); return g_current_browser_main_loop;
} }
// BrowserMainLoop construction / destruction =============================
BrowserMainLoop::BrowserMainLoop(const MainFunctionParams& parameters) BrowserMainLoop::BrowserMainLoop(const MainFunctionParams& parameters)
: parameters_(parameters), : parameters_(parameters),
...@@ -828,7 +819,8 @@ void BrowserMainLoop::BrowserThreadsStarted() { ...@@ -828,7 +819,8 @@ void BrowserMainLoop::BrowserThreadsStarted() {
{ {
TRACE_EVENT0("startup", TRACE_EVENT0("startup",
"BrowserMainLoop::BrowserThreadsStarted:InitSpeechRecognition"); "BrowserMainLoop::BrowserThreadsStarted:InitSpeechRecognition");
speech_recognition_manager_.reset(new SpeechRecognitionManagerImpl()); speech_recognition_manager_.reset(new SpeechRecognitionManagerImpl(
audio_manager_.get(), media_stream_manager_.get()));
} }
// Alert the clipboard class to which threads are allowed to access the // Alert the clipboard class to which threads are allowed to access the
......
...@@ -47,10 +47,12 @@ class DeviceMonitorMac; ...@@ -47,10 +47,12 @@ class DeviceMonitorMac;
// Implements the main browser loop stages called from BrowserMainRunner. // Implements the main browser loop stages called from BrowserMainRunner.
// See comments in browser_main_parts.h for additional info. // See comments in browser_main_parts.h for additional info.
// All functions are to be called only on the UI thread unless otherwise noted.
class BrowserMainLoop { class BrowserMainLoop {
public: public:
class MemoryObserver; // Returns the current instance. This is used to get access to the getters
// that return objects which are owned by this class.
static BrowserMainLoop* GetInstance();
explicit BrowserMainLoop(const MainFunctionParams& parameters); explicit BrowserMainLoop(const MainFunctionParams& parameters);
virtual ~BrowserMainLoop(); virtual ~BrowserMainLoop();
...@@ -72,12 +74,16 @@ class BrowserMainLoop { ...@@ -72,12 +74,16 @@ class BrowserMainLoop {
int GetResultCode() const { return result_code_; } int GetResultCode() const { return result_code_; }
// Can be called on any thread. media::AudioManager* audio_manager() const { return audio_manager_.get(); }
static media::AudioManager* GetAudioManager(); AudioMirroringManager* audio_mirroring_manager() const {
static AudioMirroringManager* GetAudioMirroringManager(); return audio_mirroring_manager_.get();
static MediaStreamManager* GetMediaStreamManager(); }
MediaStreamManager* media_stream_manager() const {
return media_stream_manager_.get();
}
private: private:
class MemoryObserver;
// For ShutdownThreadsAndCleanUp. // For ShutdownThreadsAndCleanUp.
friend class BrowserShutdownImpl; friend class BrowserShutdownImpl;
......
...@@ -9,12 +9,21 @@ ...@@ -9,12 +9,21 @@
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
namespace content { namespace content {
namespace {
void EnsureMonitorCaptureDevicesInternal(
MediaStreamManager* media_stream_manager) {
media_stream_manager->EnumerateDevices(
NULL, -1, -1, MEDIA_DEVICE_AUDIO_CAPTURE, GURL());
}
}
void EnsureMonitorCaptureDevices() { void EnsureMonitorCaptureDevices() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// Post a EnumerateDevices() API to MSM to start the monitoring.
BrowserMainLoop::GetMediaStreamManager()->EnumerateDevices( BrowserThread::PostTask(
NULL, -1, -1, MEDIA_DEVICE_AUDIO_CAPTURE, GURL()); BrowserThread::IO, FROM_HERE,
base::Bind(&EnsureMonitorCaptureDevicesInternal,
BrowserMainLoop::GetInstance()->media_stream_manager()));
} }
} // namespace content } // namespace content
...@@ -50,9 +50,11 @@ AudioInputRendererHost::AudioEntry::~AudioEntry() {} ...@@ -50,9 +50,11 @@ AudioInputRendererHost::AudioEntry::~AudioEntry() {}
AudioInputRendererHost::AudioInputRendererHost( AudioInputRendererHost::AudioInputRendererHost(
media::AudioManager* audio_manager, media::AudioManager* audio_manager,
MediaStreamManager* media_stream_manager) MediaStreamManager* media_stream_manager,
AudioMirroringManager* audio_mirroring_manager)
: audio_manager_(audio_manager), : audio_manager_(audio_manager),
media_stream_manager_(media_stream_manager) { media_stream_manager_(media_stream_manager),
audio_mirroring_manager_(audio_mirroring_manager) {
} }
AudioInputRendererHost::~AudioInputRendererHost() { AudioInputRendererHost::~AudioInputRendererHost() {
...@@ -271,7 +273,8 @@ void AudioInputRendererHost::OnCreateStream( ...@@ -271,7 +273,8 @@ void AudioInputRendererHost::OnCreateStream(
audio_manager_->GetWorkerLoop(), audio_manager_->GetWorkerLoop(),
this, this,
WebContentsAudioInputStream::Create( WebContentsAudioInputStream::Create(
device_id, audio_params, audio_manager_->GetWorkerLoop()), device_id, audio_params, audio_manager_->GetWorkerLoop(),
audio_mirroring_manager_),
entry->writer.get()); entry->writer.get());
} else { } else {
// TODO(henrika): replace CreateLowLatency() with Create() as soon // TODO(henrika): replace CreateLowLatency() with Create() as soon
......
...@@ -47,6 +47,7 @@ class AudioParameters; ...@@ -47,6 +47,7 @@ class AudioParameters;
} }
namespace content { namespace content {
class AudioMirroringManager;
class MediaStreamManager; class MediaStreamManager;
class CONTENT_EXPORT AudioInputRendererHost class CONTENT_EXPORT AudioInputRendererHost
...@@ -56,7 +57,8 @@ class CONTENT_EXPORT AudioInputRendererHost ...@@ -56,7 +57,8 @@ class CONTENT_EXPORT AudioInputRendererHost
// Called from UI thread from the owner of this object. // Called from UI thread from the owner of this object.
AudioInputRendererHost( AudioInputRendererHost(
media::AudioManager* audio_manager, media::AudioManager* audio_manager,
MediaStreamManager* media_stream_manager); MediaStreamManager* media_stream_manager,
AudioMirroringManager* audio_mirroring_manager);
// BrowserMessageFilter implementation. // BrowserMessageFilter implementation.
virtual void OnChannelClosing() OVERRIDE; virtual void OnChannelClosing() OVERRIDE;
...@@ -147,6 +149,8 @@ class CONTENT_EXPORT AudioInputRendererHost ...@@ -147,6 +149,8 @@ class CONTENT_EXPORT AudioInputRendererHost
// Used to access to AudioInputDeviceManager. // Used to access to AudioInputDeviceManager.
MediaStreamManager* media_stream_manager_; MediaStreamManager* media_stream_manager_;
AudioMirroringManager* audio_mirroring_manager_;
// A map of stream IDs to audio sources. // A map of stream IDs to audio sources.
AudioEntryMap audio_entries_; AudioEntryMap audio_entries_;
......
...@@ -23,8 +23,11 @@ struct MediaStreamDispatcherHost::StreamRequest { ...@@ -23,8 +23,11 @@ struct MediaStreamDispatcherHost::StreamRequest {
int page_request_id; int page_request_id;
}; };
MediaStreamDispatcherHost::MediaStreamDispatcherHost(int render_process_id) MediaStreamDispatcherHost::MediaStreamDispatcherHost(
: render_process_id_(render_process_id) { int render_process_id,
MediaStreamManager* media_stream_manager)
: render_process_id_(render_process_id),
media_stream_manager_(media_stream_manager) {
} }
void MediaStreamDispatcherHost::StreamGenerated( void MediaStreamDispatcherHost::StreamGenerated(
...@@ -116,7 +119,7 @@ void MediaStreamDispatcherHost::OnChannelClosing() { ...@@ -116,7 +119,7 @@ void MediaStreamDispatcherHost::OnChannelClosing() {
it != streams_.end(); it != streams_.end();
++it) { ++it) {
std::string label = it->first; std::string label = it->first;
GetManager()->StopGeneratedStream(label); media_stream_manager_->StopGeneratedStream(label);
} }
// Clear the map after we have stopped all the streams. // Clear the map after we have stopped all the streams.
streams_.clear(); streams_.clear();
...@@ -139,7 +142,7 @@ void MediaStreamDispatcherHost::OnGenerateStream( ...@@ -139,7 +142,7 @@ void MediaStreamDispatcherHost::OnGenerateStream(
<< " ], " << " ], "
<< security_origin.spec() << ")"; << security_origin.spec() << ")";
const std::string& label = GetManager()->GenerateStream( const std::string& label = media_stream_manager_->GenerateStream(
this, render_process_id_, render_view_id, components, security_origin); this, render_process_id_, render_view_id, components, security_origin);
if (label.empty()) { if (label.empty()) {
Send(new MediaStreamMsg_StreamGenerationFailed(render_view_id, Send(new MediaStreamMsg_StreamGenerationFailed(render_view_id,
...@@ -158,7 +161,7 @@ void MediaStreamDispatcherHost::OnCancelGenerateStream(int render_view_id, ...@@ -158,7 +161,7 @@ void MediaStreamDispatcherHost::OnCancelGenerateStream(int render_view_id,
for (StreamMap::iterator it = streams_.begin(); it != streams_.end(); ++it) { for (StreamMap::iterator it = streams_.begin(); it != streams_.end(); ++it) {
if (it->second.render_view_id == render_view_id && if (it->second.render_view_id == render_view_id &&
it->second.page_request_id == page_request_id) { it->second.page_request_id == page_request_id) {
GetManager()->CancelRequest(it->first); media_stream_manager_->CancelRequest(it->first);
} }
} }
} }
...@@ -172,7 +175,7 @@ void MediaStreamDispatcherHost::OnStopGeneratedStream( ...@@ -172,7 +175,7 @@ void MediaStreamDispatcherHost::OnStopGeneratedStream(
if (it == streams_.end()) if (it == streams_.end())
return; return;
GetManager()->StopGeneratedStream(label); media_stream_manager_->StopGeneratedStream(label);
streams_.erase(it); streams_.erase(it);
} }
...@@ -187,7 +190,7 @@ void MediaStreamDispatcherHost::OnEnumerateDevices( ...@@ -187,7 +190,7 @@ void MediaStreamDispatcherHost::OnEnumerateDevices(
<< type << ", " << type << ", "
<< security_origin.spec() << ")"; << security_origin.spec() << ")";
const std::string& label = GetManager()->EnumerateDevices( const std::string& label = media_stream_manager_->EnumerateDevices(
this, render_process_id_, render_view_id, type, security_origin); this, render_process_id_, render_view_id, type, security_origin);
DCHECK(!label.empty()); DCHECK(!label.empty());
streams_[label] = StreamRequest(render_view_id, page_request_id); streams_[label] = StreamRequest(render_view_id, page_request_id);
...@@ -206,15 +209,11 @@ void MediaStreamDispatcherHost::OnOpenDevice( ...@@ -206,15 +209,11 @@ void MediaStreamDispatcherHost::OnOpenDevice(
<< type << ", " << type << ", "
<< security_origin.spec() << ")"; << security_origin.spec() << ")";
const std::string& label = GetManager()->OpenDevice( const std::string& label = media_stream_manager_->OpenDevice(
this, render_process_id_, render_view_id, this, render_process_id_, render_view_id,
device_id, type, security_origin); device_id, type, security_origin);
DCHECK(!label.empty()); DCHECK(!label.empty());
streams_[label] = StreamRequest(render_view_id, page_request_id); streams_[label] = StreamRequest(render_view_id, page_request_id);
} }
MediaStreamManager* MediaStreamDispatcherHost::GetManager() {
return BrowserMainLoop::GetMediaStreamManager();
}
} // namespace content } // namespace content
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "content/public/browser/browser_message_filter.h" #include "content/public/browser/browser_message_filter.h"
namespace content { namespace content {
class MediaStreamManager;
// MediaStreamDispatcherHost is a delegate for Media Stream API messages used by // MediaStreamDispatcherHost is a delegate for Media Stream API messages used by
// MediaStreamImpl. It's the complement of MediaStreamDispatcher // MediaStreamImpl. It's the complement of MediaStreamDispatcher
...@@ -23,7 +24,8 @@ namespace content { ...@@ -23,7 +24,8 @@ namespace content {
class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter, class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter,
public MediaStreamRequester { public MediaStreamRequester {
public: public:
explicit MediaStreamDispatcherHost(int render_process_id); MediaStreamDispatcherHost(int render_process_id,
MediaStreamManager* media_stream_manager);
// MediaStreamRequester implementation. // MediaStreamRequester implementation.
virtual void StreamGenerated( virtual void StreamGenerated(
...@@ -66,12 +68,8 @@ class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter, ...@@ -66,12 +68,8 @@ class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter,
MediaStreamType type, MediaStreamType type,
const GURL& security_origin); const GURL& security_origin);
// Returns the media stream manager to forward events to,
// creating one if needed. It is a virtual function so that the unit tests
// can inject their own MediaStreamManager.
virtual MediaStreamManager* GetManager();
int render_process_id_; int render_process_id_;
MediaStreamManager* media_stream_manager_;
struct StreamRequest; struct StreamRequest;
typedef std::map<std::string, StreamRequest> StreamMap; typedef std::map<std::string, StreamRequest> StreamMap;
......
...@@ -41,9 +41,8 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, ...@@ -41,9 +41,8 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
public: public:
MockMediaStreamDispatcherHost(base::MessageLoop* message_loop, MockMediaStreamDispatcherHost(base::MessageLoop* message_loop,
MediaStreamManager* manager) MediaStreamManager* manager)
: MediaStreamDispatcherHost(kProcessId), : MediaStreamDispatcherHost(kProcessId, manager),
message_loop_(message_loop), message_loop_(message_loop) {}
manager_(manager) {}
// A list of mock methods. // A list of mock methods.
MOCK_METHOD4(OnStreamGenerated, MOCK_METHOD4(OnStreamGenerated,
...@@ -95,11 +94,6 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, ...@@ -95,11 +94,6 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
return true; return true;
} }
// Use our own MediaStreamManager.
virtual MediaStreamManager* GetManager() OVERRIDE {
return manager_;
}
// These handler methods do minimal things and delegate to the mock methods. // These handler methods do minimal things and delegate to the mock methods.
void OnStreamGenerated( void OnStreamGenerated(
const IPC::Message& msg, const IPC::Message& msg,
...@@ -123,7 +117,6 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, ...@@ -123,7 +117,6 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
} }
base::MessageLoop* message_loop_; base::MessageLoop* message_loop_;
MediaStreamManager* manager_;
}; };
class MockMediaStreamUIProxy : public FakeMediaStreamUIProxy { class MockMediaStreamUIProxy : public FakeMediaStreamUIProxy {
......
...@@ -23,7 +23,9 @@ struct VideoCaptureHost::Entry { ...@@ -23,7 +23,9 @@ struct VideoCaptureHost::Entry {
scoped_refptr<VideoCaptureController> controller; scoped_refptr<VideoCaptureController> controller;
}; };
VideoCaptureHost::VideoCaptureHost() {} VideoCaptureHost::VideoCaptureHost(MediaStreamManager* media_stream_manager)
: media_stream_manager_(media_stream_manager) {
}
VideoCaptureHost::~VideoCaptureHost() {} VideoCaptureHost::~VideoCaptureHost() {}
...@@ -36,7 +38,8 @@ void VideoCaptureHost::OnChannelClosing() { ...@@ -36,7 +38,8 @@ void VideoCaptureHost::OnChannelClosing() {
if (controller) { if (controller) {
VideoCaptureControllerID controller_id(it->first); VideoCaptureControllerID controller_id(it->first);
controller->StopCapture(controller_id, this); controller->StopCapture(controller_id, this);
GetVideoCaptureManager()->RemoveController(controller, this); media_stream_manager_->video_capture_manager()->RemoveController(
controller, this);
} }
} }
STLDeleteValues(&entries_); STLDeleteValues(&entries_);
...@@ -192,7 +195,7 @@ void VideoCaptureHost::OnStartCapture(int device_id, ...@@ -192,7 +195,7 @@ void VideoCaptureHost::OnStartCapture(int device_id,
DCHECK(entries_.find(controller_id) == entries_.end()); DCHECK(entries_.find(controller_id) == entries_.end());
entries_[controller_id] = new Entry(NULL); entries_[controller_id] = new Entry(NULL);
GetVideoCaptureManager()->AddController( media_stream_manager_->video_capture_manager()->AddController(
params, this, base::Bind(&VideoCaptureHost::OnControllerAdded, this, params, this, base::Bind(&VideoCaptureHost::OnControllerAdded, this,
device_id, params)); device_id, params));
} }
...@@ -213,8 +216,10 @@ void VideoCaptureHost::DoControllerAddedOnIOThread( ...@@ -213,8 +216,10 @@ void VideoCaptureHost::DoControllerAddedOnIOThread(
VideoCaptureControllerID controller_id(device_id); VideoCaptureControllerID controller_id(device_id);
EntryMap::iterator it = entries_.find(controller_id); EntryMap::iterator it = entries_.find(controller_id);
if (it == entries_.end()) { if (it == entries_.end()) {
if (controller) if (controller) {
GetVideoCaptureManager()->RemoveController(controller, this); media_stream_manager_->video_capture_manager()->RemoveController(
controller, this);
}
return; return;
} }
...@@ -271,15 +276,11 @@ void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread( ...@@ -271,15 +276,11 @@ void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread(
VideoCaptureController* controller = it->second->controller.get(); VideoCaptureController* controller = it->second->controller.get();
if (controller) { if (controller) {
controller->StopCapture(controller_id, this); controller->StopCapture(controller_id, this);
GetVideoCaptureManager()->RemoveController(controller, this); media_stream_manager_->video_capture_manager()->RemoveController(
controller, this);
} }
delete it->second; delete it->second;
entries_.erase(controller_id); entries_.erase(controller_id);
} }
VideoCaptureManager* VideoCaptureHost::GetVideoCaptureManager() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
return BrowserMainLoop::GetMediaStreamManager()->video_capture_manager();
}
} // namespace content } // namespace content
...@@ -46,12 +46,13 @@ ...@@ -46,12 +46,13 @@
#include "ipc/ipc_message.h" #include "ipc/ipc_message.h"
namespace content { namespace content {
class MediaStreamManager;
class CONTENT_EXPORT VideoCaptureHost class CONTENT_EXPORT VideoCaptureHost
: public BrowserMessageFilter, : public BrowserMessageFilter,
public VideoCaptureControllerEventHandler { public VideoCaptureControllerEventHandler {
public: public:
VideoCaptureHost(); explicit VideoCaptureHost(MediaStreamManager* media_stream_manager);
// BrowserMessageFilter implementation. // BrowserMessageFilter implementation.
virtual void OnChannelClosing() OVERRIDE; virtual void OnChannelClosing() OVERRIDE;
...@@ -133,9 +134,7 @@ class CONTENT_EXPORT VideoCaptureHost ...@@ -133,9 +134,7 @@ class CONTENT_EXPORT VideoCaptureHost
void DeleteVideoCaptureControllerOnIOThread( void DeleteVideoCaptureControllerOnIOThread(
const VideoCaptureControllerID& controller_id); const VideoCaptureControllerID& controller_id);
// Returns the video capture manager. This is a virtual function so that MediaStreamManager* media_stream_manager_;
// the unit tests can inject their own MediaStreamManager.
virtual VideoCaptureManager* GetVideoCaptureManager();
struct Entry; struct Entry;
typedef std::map<VideoCaptureControllerID, Entry*> EntryMap; typedef std::map<VideoCaptureControllerID, Entry*> EntryMap;
......
...@@ -72,10 +72,9 @@ class DumpVideo { ...@@ -72,10 +72,9 @@ class DumpVideo {
class MockVideoCaptureHost : public VideoCaptureHost { class MockVideoCaptureHost : public VideoCaptureHost {
public: public:
MockVideoCaptureHost(MediaStreamManager* manager) MockVideoCaptureHost(MediaStreamManager* manager)
: VideoCaptureHost(), : VideoCaptureHost(manager),
return_buffers_(false), return_buffers_(false),
dump_video_(false), dump_video_(false) {}
manager_(manager) {}
// A list of mock methods. // A list of mock methods.
MOCK_METHOD4(OnNewBufferCreated, MOCK_METHOD4(OnNewBufferCreated,
...@@ -143,10 +142,6 @@ class MockVideoCaptureHost : public VideoCaptureHost { ...@@ -143,10 +142,6 @@ class MockVideoCaptureHost : public VideoCaptureHost {
return true; return true;
} }
virtual VideoCaptureManager* GetVideoCaptureManager() OVERRIDE {
return manager_->video_capture_manager();
}
// These handler methods do minimal things and delegate to the mock methods. // These handler methods do minimal things and delegate to the mock methods.
void OnNewBufferCreatedDispatch(int device_id, void OnNewBufferCreatedDispatch(int device_id,
base::SharedMemoryHandle handle, base::SharedMemoryHandle handle,
...@@ -187,7 +182,6 @@ class MockVideoCaptureHost : public VideoCaptureHost { ...@@ -187,7 +182,6 @@ class MockVideoCaptureHost : public VideoCaptureHost {
bool return_buffers_; bool return_buffers_;
bool dump_video_; bool dump_video_;
DumpVideo dumper_; DumpVideo dumper_;
MediaStreamManager* manager_;
}; };
ACTION_P(ExitMessageLoop, message_loop) { ACTION_P(ExitMessageLoop, message_loop) {
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop_proxy.h" #include "base/message_loop/message_loop_proxy.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/renderer_host/media/audio_mirroring_manager.h" #include "content/browser/renderer_host/media/audio_mirroring_manager.h"
#include "content/browser/renderer_host/media/web_contents_capture_util.h" #include "content/browser/renderer_host/media/web_contents_capture_util.h"
#include "content/browser/renderer_host/media/web_contents_tracker.h" #include "content/browser/renderer_host/media/web_contents_tracker.h"
...@@ -281,7 +280,8 @@ void WebContentsAudioInputStream::Impl::OnTargetChanged(int render_process_id, ...@@ -281,7 +280,8 @@ void WebContentsAudioInputStream::Impl::OnTargetChanged(int render_process_id,
WebContentsAudioInputStream* WebContentsAudioInputStream::Create( WebContentsAudioInputStream* WebContentsAudioInputStream::Create(
const std::string& device_id, const std::string& device_id,
const media::AudioParameters& params, const media::AudioParameters& params,
const scoped_refptr<base::MessageLoopProxy>& message_loop) { const scoped_refptr<base::MessageLoopProxy>& message_loop,
AudioMirroringManager* audio_mirroring_manager) {
int render_process_id; int render_process_id;
int render_view_id; int render_view_id;
if (!WebContentsCaptureUtil::ExtractTabCaptureTarget( if (!WebContentsCaptureUtil::ExtractTabCaptureTarget(
...@@ -291,7 +291,7 @@ WebContentsAudioInputStream* WebContentsAudioInputStream::Create( ...@@ -291,7 +291,7 @@ WebContentsAudioInputStream* WebContentsAudioInputStream::Create(
return new WebContentsAudioInputStream( return new WebContentsAudioInputStream(
render_process_id, render_view_id, message_loop, render_process_id, render_view_id, message_loop,
BrowserMainLoop::GetAudioMirroringManager(), audio_mirroring_manager,
new WebContentsTracker(), new WebContentsTracker(),
new media::VirtualAudioInputStream( new media::VirtualAudioInputStream(
params, message_loop, params, message_loop,
......
...@@ -58,7 +58,8 @@ class CONTENT_EXPORT WebContentsAudioInputStream ...@@ -58,7 +58,8 @@ class CONTENT_EXPORT WebContentsAudioInputStream
static WebContentsAudioInputStream* Create( static WebContentsAudioInputStream* Create(
const std::string& device_id, const std::string& device_id,
const media::AudioParameters& params, const media::AudioParameters& params,
const scoped_refptr<base::MessageLoopProxy>& message_loop); const scoped_refptr<base::MessageLoopProxy>& message_loop,
AudioMirroringManager* audio_mirroring_manager);
private: private:
friend class WebContentsAudioInputStreamTest; friend class WebContentsAudioInputStreamTest;
......
...@@ -297,6 +297,7 @@ RenderMessageFilter::RenderMessageFilter( ...@@ -297,6 +297,7 @@ RenderMessageFilter::RenderMessageFilter(
BrowserContext* browser_context, BrowserContext* browser_context,
net::URLRequestContextGetter* request_context, net::URLRequestContextGetter* request_context,
RenderWidgetHelper* render_widget_helper, RenderWidgetHelper* render_widget_helper,
media::AudioManager* audio_manager,
MediaInternals* media_internals, MediaInternals* media_internals,
DOMStorageContextImpl* dom_storage_context) DOMStorageContextImpl* dom_storage_context)
: resource_dispatcher_host_(ResourceDispatcherHostImpl::Get()), : resource_dispatcher_host_(ResourceDispatcherHostImpl::Get()),
...@@ -309,6 +310,7 @@ RenderMessageFilter::RenderMessageFilter( ...@@ -309,6 +310,7 @@ RenderMessageFilter::RenderMessageFilter(
dom_storage_context_(dom_storage_context), dom_storage_context_(dom_storage_context),
render_process_id_(render_process_id), render_process_id_(render_process_id),
cpu_usage_(0), cpu_usage_(0),
audio_manager_(audio_manager),
media_internals_(media_internals) { media_internals_(media_internals) {
DCHECK(request_context_.get()); DCHECK(request_context_.get());
...@@ -439,7 +441,7 @@ base::TaskRunner* RenderMessageFilter::OverrideTaskRunnerForMessage( ...@@ -439,7 +441,7 @@ base::TaskRunner* RenderMessageFilter::OverrideTaskRunnerForMessage(
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
// OSX CoreAudio calls must all happen on the main thread. // OSX CoreAudio calls must all happen on the main thread.
if (message.type() == ViewHostMsg_GetAudioHardwareConfig::ID) if (message.type() == ViewHostMsg_GetAudioHardwareConfig::ID)
return BrowserMainLoop::GetAudioManager()->GetMessageLoop(); return audio_manager_->GetMessageLoop();
#endif #endif
return NULL; return NULL;
} }
...@@ -802,13 +804,11 @@ void RenderMessageFilter::OnGetAudioHardwareConfig( ...@@ -802,13 +804,11 @@ void RenderMessageFilter::OnGetAudioHardwareConfig(
media::AudioParameters* output_params) { media::AudioParameters* output_params) {
DCHECK(input_params); DCHECK(input_params);
DCHECK(output_params); DCHECK(output_params);
media::AudioManager* audio_manager = BrowserMainLoop::GetAudioManager(); *output_params = audio_manager_->GetDefaultOutputStreamParameters();
*output_params = audio_manager->GetDefaultOutputStreamParameters();
// TODO(henrika): add support for all available input devices. // TODO(henrika): add support for all available input devices.
*input_params = *input_params = audio_manager_->GetInputStreamParameters(
audio_manager->GetInputStreamParameters( media::AudioManagerBase::kDefaultDeviceId);
media::AudioManagerBase::kDefaultDeviceId);
} }
void RenderMessageFilter::OnGetMonitorColorProfile(std::vector<char>* profile) { void RenderMessageFilter::OnGetMonitorColorProfile(std::vector<char>* profile) {
......
...@@ -55,6 +55,7 @@ class Rect; ...@@ -55,6 +55,7 @@ class Rect;
} }
namespace media { namespace media {
class AudioManager;
struct MediaLogEvent; struct MediaLogEvent;
} }
...@@ -87,6 +88,7 @@ class RenderMessageFilter : public BrowserMessageFilter { ...@@ -87,6 +88,7 @@ class RenderMessageFilter : public BrowserMessageFilter {
BrowserContext* browser_context, BrowserContext* browser_context,
net::URLRequestContextGetter* request_context, net::URLRequestContextGetter* request_context,
RenderWidgetHelper* render_widget_helper, RenderWidgetHelper* render_widget_helper,
media::AudioManager* audio_manager,
MediaInternals* media_internals, MediaInternals* media_internals,
DOMStorageContextImpl* dom_storage_context); DOMStorageContextImpl* dom_storage_context);
...@@ -302,6 +304,7 @@ class RenderMessageFilter : public BrowserMessageFilter { ...@@ -302,6 +304,7 @@ class RenderMessageFilter : public BrowserMessageFilter {
// Used for sampling CPU usage of the renderer process. // Used for sampling CPU usage of the renderer process.
scoped_ptr<base::ProcessMetrics> process_metrics_; scoped_ptr<base::ProcessMetrics> process_metrics_;
media::AudioManager* audio_manager_;
MediaInternals* media_internals_; MediaInternals* media_internals_;
DISALLOW_COPY_AND_ASSIGN(RenderMessageFilter); DISALLOW_COPY_AND_ASSIGN(RenderMessageFilter);
......
...@@ -557,6 +557,8 @@ void RenderProcessHostImpl::CreateMessageFilters() { ...@@ -557,6 +557,8 @@ void RenderProcessHostImpl::CreateMessageFilters() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
channel_->AddFilter(new ResourceSchedulerFilter(GetID())); channel_->AddFilter(new ResourceSchedulerFilter(GetID()));
MediaInternals* media_internals = MediaInternals::GetInstance();; MediaInternals* media_internals = MediaInternals::GetInstance();;
media::AudioManager* audio_manager =
BrowserMainLoop::GetInstance()->audio_manager();
// Add BrowserPluginMessageFilter to ensure it gets the first stab at messages // Add BrowserPluginMessageFilter to ensure it gets the first stab at messages
// from guests. // from guests.
if (supports_browser_plugin_) { if (supports_browser_plugin_) {
...@@ -576,6 +578,7 @@ void RenderProcessHostImpl::CreateMessageFilters() { ...@@ -576,6 +578,7 @@ void RenderProcessHostImpl::CreateMessageFilters() {
GetBrowserContext(), GetBrowserContext(),
GetBrowserContext()->GetRequestContextForRenderProcess(GetID()), GetBrowserContext()->GetRequestContextForRenderProcess(GetID()),
widget_helper_.get(), widget_helper_.get(),
audio_manager,
media_internals, media_internals,
storage_partition_impl_->GetDOMStorageContext())); storage_partition_impl_->GetDOMStorageContext()));
channel_->AddFilter(render_message_filter.get()); channel_->AddFilter(render_message_filter.get());
...@@ -590,27 +593,27 @@ void RenderProcessHostImpl::CreateMessageFilters() { ...@@ -590,27 +593,27 @@ void RenderProcessHostImpl::CreateMessageFilters() {
new RendererURLRequestContextSelector(browser_context, GetID())); new RendererURLRequestContextSelector(browser_context, GetID()));
channel_->AddFilter(resource_message_filter); channel_->AddFilter(resource_message_filter);
media::AudioManager* audio_manager = BrowserMainLoop::GetAudioManager();
MediaStreamManager* media_stream_manager = MediaStreamManager* media_stream_manager =
BrowserMainLoop::GetMediaStreamManager(); BrowserMainLoop::GetInstance()->media_stream_manager();
channel_->AddFilter(new AudioInputRendererHost(audio_manager, channel_->AddFilter(new AudioInputRendererHost(
media_stream_manager)); audio_manager,
media_stream_manager,
BrowserMainLoop::GetInstance()->audio_mirroring_manager()));
channel_->AddFilter(new AudioRendererHost( channel_->AddFilter(new AudioRendererHost(
GetID(), audio_manager, BrowserMainLoop::GetAudioMirroringManager(), GetID(), audio_manager,
BrowserMainLoop::GetInstance()->audio_mirroring_manager(),
media_internals, media_stream_manager)); media_internals, media_stream_manager));
channel_->AddFilter(new VideoCaptureHost()); channel_->AddFilter(new VideoCaptureHost(media_stream_manager));
channel_->AddFilter(new AppCacheDispatcherHost( channel_->AddFilter(new AppCacheDispatcherHost(
storage_partition_impl_->GetAppCacheService(), storage_partition_impl_->GetAppCacheService(),
GetID())); GetID()));
channel_->AddFilter(new ClipboardMessageFilter); channel_->AddFilter(new ClipboardMessageFilter);
channel_->AddFilter( channel_->AddFilter(new DOMStorageMessageFilter(
new DOMStorageMessageFilter( GetID(),
GetID(), storage_partition_impl_->GetDOMStorageContext()));
storage_partition_impl_->GetDOMStorageContext())); channel_->AddFilter(new IndexedDBDispatcherHost(
channel_->AddFilter( GetID(),
new IndexedDBDispatcherHost( storage_partition_impl_->GetIndexedDBContext()));
GetID(),
storage_partition_impl_->GetIndexedDBContext()));
if (IsGuest()) { if (IsGuest()) {
if (!g_browser_plugin_geolocation_context.Get().get()) { if (!g_browser_plugin_geolocation_context.Get().get()) {
g_browser_plugin_geolocation_context.Get() = g_browser_plugin_geolocation_context.Get() =
...@@ -627,7 +630,8 @@ void RenderProcessHostImpl::CreateMessageFilters() { ...@@ -627,7 +630,8 @@ void RenderProcessHostImpl::CreateMessageFilters() {
#if defined(ENABLE_WEBRTC) #if defined(ENABLE_WEBRTC)
peer_connection_tracker_host_ = new PeerConnectionTrackerHost(GetID()); peer_connection_tracker_host_ = new PeerConnectionTrackerHost(GetID());
channel_->AddFilter(peer_connection_tracker_host_.get()); channel_->AddFilter(peer_connection_tracker_host_.get());
channel_->AddFilter(new MediaStreamDispatcherHost(GetID())); channel_->AddFilter(new MediaStreamDispatcherHost(
GetID(), media_stream_manager));
#endif #endif
#if defined(ENABLE_PLUGINS) #if defined(ENABLE_PLUGINS)
// TODO(raymes): PepperMessageFilter should be removed from here. // TODO(raymes): PepperMessageFilter should be removed from here.
...@@ -664,20 +668,19 @@ void RenderProcessHostImpl::CreateMessageFilters() { ...@@ -664,20 +668,19 @@ void RenderProcessHostImpl::CreateMessageFilters() {
resource_context); resource_context);
channel_->AddFilter(socket_stream_dispatcher_host); channel_->AddFilter(socket_stream_dispatcher_host);
channel_->AddFilter( channel_->AddFilter(new WorkerMessageFilter(
new WorkerMessageFilter( GetID(),
GetID(), resource_context,
resource_context, WorkerStoragePartition(
WorkerStoragePartition( storage_partition_impl_->GetURLRequestContext(),
storage_partition_impl_->GetURLRequestContext(), storage_partition_impl_->GetMediaURLRequestContext(),
storage_partition_impl_->GetMediaURLRequestContext(), storage_partition_impl_->GetAppCacheService(),
storage_partition_impl_->GetAppCacheService(), storage_partition_impl_->GetQuotaManager(),
storage_partition_impl_->GetQuotaManager(), storage_partition_impl_->GetFileSystemContext(),
storage_partition_impl_->GetFileSystemContext(), storage_partition_impl_->GetDatabaseTracker(),
storage_partition_impl_->GetDatabaseTracker(), storage_partition_impl_->GetIndexedDBContext()),
storage_partition_impl_->GetIndexedDBContext()), base::Bind(&RenderWidgetHelper::GetNextRoutingID,
base::Bind(&RenderWidgetHelper::GetNextRoutingID, base::Unretained(widget_helper_.get()))));
base::Unretained(widget_helper_.get()))));
#if defined(ENABLE_WEBRTC) #if defined(ENABLE_WEBRTC)
channel_->AddFilter(new P2PSocketDispatcherHost(resource_context)); channel_->AddFilter(new P2PSocketDispatcherHost(resource_context));
......
...@@ -37,9 +37,9 @@ namespace { ...@@ -37,9 +37,9 @@ namespace {
SpeechRecognitionManagerImpl* g_speech_recognition_manager_impl; SpeechRecognitionManagerImpl* g_speech_recognition_manager_impl;
void ShowAudioInputSettingsOnFileThread() { void ShowAudioInputSettingsOnFileThread(media::AudioManager* audio_manager) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
BrowserMainLoop::GetAudioManager()->ShowAudioInputSettings(); audio_manager->ShowAudioInputSettings();
} }
} // namespace } // namespace
...@@ -59,8 +59,12 @@ SpeechRecognitionManagerImpl* SpeechRecognitionManagerImpl::GetInstance() { ...@@ -59,8 +59,12 @@ SpeechRecognitionManagerImpl* SpeechRecognitionManagerImpl::GetInstance() {
return g_speech_recognition_manager_impl; return g_speech_recognition_manager_impl;
} }
SpeechRecognitionManagerImpl::SpeechRecognitionManagerImpl() SpeechRecognitionManagerImpl::SpeechRecognitionManagerImpl(
: primary_session_id_(kSessionIDInvalid), media::AudioManager* audio_manager,
MediaStreamManager* media_stream_manager)
: audio_manager_(audio_manager),
media_stream_manager_(media_stream_manager),
primary_session_id_(kSessionIDInvalid),
last_session_id_(kSessionIDInvalid), last_session_id_(kSessionIDInvalid),
is_dispatching_event_(false), is_dispatching_event_(false),
delegate_(GetContentClient()->browser()-> delegate_(GetContentClient()->browser()->
...@@ -183,15 +187,14 @@ void SpeechRecognitionManagerImpl::RecognitionAllowedCallback(int session_id, ...@@ -183,15 +187,14 @@ void SpeechRecognitionManagerImpl::RecognitionAllowedCallback(int session_id,
SessionsTable::iterator iter = sessions_.find(session_id); SessionsTable::iterator iter = sessions_.find(session_id);
DCHECK(iter != sessions_.end()); DCHECK(iter != sessions_.end());
SpeechRecognitionSessionContext& context = iter->second->context; SpeechRecognitionSessionContext& context = iter->second->context;
context.label = context.label = media_stream_manager_->MakeMediaAccessRequest(
BrowserMainLoop::GetMediaStreamManager()->MakeMediaAccessRequest( context.render_process_id,
context.render_process_id, context.render_view_id,
context.render_view_id, StreamOptions(MEDIA_DEVICE_AUDIO_CAPTURE, MEDIA_NO_SERVICE),
StreamOptions(MEDIA_DEVICE_AUDIO_CAPTURE, MEDIA_NO_SERVICE), GURL(context.context_name),
GURL(context.context_name), base::Bind(
base::Bind( &SpeechRecognitionManagerImpl::MediaRequestPermissionCallback,
&SpeechRecognitionManagerImpl::MediaRequestPermissionCallback, weak_factory_.GetWeakPtr(), session_id));
weak_factory_.GetWeakPtr(), session_id));
return; return;
} }
...@@ -642,18 +645,19 @@ SpeechRecognitionManagerImpl::GetSessionConfig(int session_id) const { ...@@ -642,18 +645,19 @@ SpeechRecognitionManagerImpl::GetSessionConfig(int session_id) const {
} }
bool SpeechRecognitionManagerImpl::HasAudioInputDevices() { bool SpeechRecognitionManagerImpl::HasAudioInputDevices() {
return BrowserMainLoop::GetAudioManager()->HasAudioInputDevices(); return audio_manager_->HasAudioInputDevices();
} }
string16 SpeechRecognitionManagerImpl::GetAudioInputDeviceModel() { string16 SpeechRecognitionManagerImpl::GetAudioInputDeviceModel() {
return BrowserMainLoop::GetAudioManager()->GetAudioInputDeviceModel(); return audio_manager_->GetAudioInputDeviceModel();
} }
void SpeechRecognitionManagerImpl::ShowAudioInputSettings() { void SpeechRecognitionManagerImpl::ShowAudioInputSettings() {
// Since AudioManager::ShowAudioInputSettings can potentially launch external // Since AudioManager::ShowAudioInputSettings can potentially launch external
// processes, do that in the FILE thread to not block the calling threads. // processes, do that in the FILE thread to not block the calling threads.
BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
base::Bind(&ShowAudioInputSettingsOnFileThread)); base::Bind(&ShowAudioInputSettingsOnFileThread,
audio_manager_));
} }
SpeechRecognitionManagerImpl::Session::Session() SpeechRecognitionManagerImpl::Session::Session()
......
...@@ -19,8 +19,13 @@ ...@@ -19,8 +19,13 @@
#include "content/public/browser/speech_recognition_session_context.h" #include "content/public/browser/speech_recognition_session_context.h"
#include "content/public/common/speech_recognition_error.h" #include "content/public/common/speech_recognition_error.h"
namespace media {
class AudioManager;
}
namespace content { namespace content {
class BrowserMainLoop; class BrowserMainLoop;
class MediaStreamManager;
class MediaStreamUIProxy; class MediaStreamUIProxy;
class SpeechRecognitionManagerDelegate; class SpeechRecognitionManagerDelegate;
class SpeechRecognizer; class SpeechRecognizer;
...@@ -93,7 +98,8 @@ class CONTENT_EXPORT SpeechRecognitionManagerImpl : ...@@ -93,7 +98,8 @@ class CONTENT_EXPORT SpeechRecognitionManagerImpl :
friend class BrowserMainLoop; friend class BrowserMainLoop;
// Needed for dtor. // Needed for dtor.
friend struct base::DefaultDeleter<SpeechRecognitionManagerImpl>; friend struct base::DefaultDeleter<SpeechRecognitionManagerImpl>;
SpeechRecognitionManagerImpl(); SpeechRecognitionManagerImpl(media::AudioManager* audio_manager,
MediaStreamManager* media_stream_manager);
virtual ~SpeechRecognitionManagerImpl(); virtual ~SpeechRecognitionManagerImpl();
private: private:
...@@ -165,6 +171,8 @@ class CONTENT_EXPORT SpeechRecognitionManagerImpl : ...@@ -165,6 +171,8 @@ class CONTENT_EXPORT SpeechRecognitionManagerImpl :
SpeechRecognitionEventListener* GetDelegateListener() const; SpeechRecognitionEventListener* GetDelegateListener() const;
int GetNextSessionID(); int GetNextSessionID();
media::AudioManager* audio_manager_;
MediaStreamManager* media_stream_manager_;
typedef std::map<int, Session*> SessionsTable; typedef std::map<int, Session*> SessionsTable;
SessionsTable sessions_; SessionsTable sessions_;
int primary_session_id_; int primary_session_id_;
......
...@@ -12,7 +12,6 @@ namespace content { ...@@ -12,7 +12,6 @@ namespace content {
// Called to ensure the MediaStreamManager has started monitoring the capture // Called to ensure the MediaStreamManager has started monitoring the capture
// devices, this will trigger OnAudioCaptureDevicesChanged() and // devices, this will trigger OnAudioCaptureDevicesChanged() and
// OnVideoCaptureDevicesChanged() callbacks. // OnVideoCaptureDevicesChanged() callbacks.
// This must be called on the IO thread.
CONTENT_EXPORT void EnsureMonitorCaptureDevices(); CONTENT_EXPORT void EnsureMonitorCaptureDevices();
} // namespace content } // namespace content
......
...@@ -245,7 +245,8 @@ void WebRTCAudioDeviceTest::CreateChannel(const char* name) { ...@@ -245,7 +245,8 @@ void WebRTCAudioDeviceTest::CreateChannel(const char* name) {
audio_render_host_->OnChannelConnected(base::GetCurrentProcId()); audio_render_host_->OnChannelConnected(base::GetCurrentProcId());
audio_input_renderer_host_ = new AudioInputRendererHost( audio_input_renderer_host_ = new AudioInputRendererHost(
audio_manager_.get(), media_stream_manager_.get()); audio_manager_.get(), media_stream_manager_.get(),
mirroring_manager_.get());
audio_input_renderer_host_->OnChannelConnected(base::GetCurrentProcId()); audio_input_renderer_host_->OnChannelConnected(base::GetCurrentProcId());
channel_.reset(new IPC::Channel(name, IPC::Channel::MODE_SERVER, this)); channel_.reset(new IPC::Channel(name, IPC::Channel::MODE_SERVER, this));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment