| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/device_monitor_mac.h" | 5 #include "content/browser/device_monitor_mac.h" |
| 6 | 6 |
| 7 #import <QTKit/QTKit.h> | 7 #import <QTKit/QTKit.h> |
| 8 | 8 |
| 9 #include <set> | 9 #include <set> |
| 10 | 10 |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 // |avfoundation_monitor_impl_|. Assumes that |devices| has been retained | 276 // |avfoundation_monitor_impl_|. Assumes that |devices| has been retained |
| 277 // prior to being called, and releases it internally. | 277 // prior to being called, and releases it internally. |
| 278 void DoOnDeviceChanged(NSArray* devices); | 278 void DoOnDeviceChanged(NSArray* devices); |
| 279 | 279 |
| 280 base::scoped_nsobject<CrAVFoundationDeviceObserver> suspend_observer_; | 280 base::scoped_nsobject<CrAVFoundationDeviceObserver> suspend_observer_; |
| 281 DeviceMonitorMacImpl* avfoundation_monitor_impl_; | 281 DeviceMonitorMacImpl* avfoundation_monitor_impl_; |
| 282 }; | 282 }; |
| 283 | 283 |
| 284 SuspendObserverDelegate::SuspendObserverDelegate(DeviceMonitorMacImpl* monitor) | 284 SuspendObserverDelegate::SuspendObserverDelegate(DeviceMonitorMacImpl* monitor) |
| 285 : avfoundation_monitor_impl_(monitor) { | 285 : avfoundation_monitor_impl_(monitor) { |
| 286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 286 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 287 } | 287 } |
| 288 | 288 |
| 289 void SuspendObserverDelegate::StartObserver( | 289 void SuspendObserverDelegate::StartObserver( |
| 290 const scoped_refptr<base::SingleThreadTaskRunner>& device_thread) { | 290 const scoped_refptr<base::SingleThreadTaskRunner>& device_thread) { |
| 291 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 291 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 292 | 292 |
| 293 base::Closure on_device_changed_callback = | 293 base::Closure on_device_changed_callback = |
| 294 base::Bind(&SuspendObserverDelegate::OnDeviceChanged, | 294 base::Bind(&SuspendObserverDelegate::OnDeviceChanged, |
| 295 this, device_thread); | 295 this, device_thread); |
| 296 suspend_observer_.reset([[CrAVFoundationDeviceObserver alloc] | 296 suspend_observer_.reset([[CrAVFoundationDeviceObserver alloc] |
| 297 initWithOnChangedCallback:on_device_changed_callback]); | 297 initWithOnChangedCallback:on_device_changed_callback]); |
| 298 | 298 |
| 299 // Enumerate the devices in Device thread and post the observers start to be | 299 // Enumerate the devices in Device thread and post the observers start to be |
| 300 // done on UI thread. The devices array is retained in |device_thread| and | 300 // done on UI thread. The devices array is retained in |device_thread| and |
| 301 // released in DoStartObserver(). | 301 // released in DoStartObserver(). |
| 302 base::PostTaskAndReplyWithResult( | 302 base::PostTaskAndReplyWithResult( |
| 303 device_thread.get(), | 303 device_thread.get(), |
| 304 FROM_HERE, | 304 FROM_HERE, |
| 305 base::BindBlock(^{ return [[AVCaptureDeviceGlue devices] retain]; }), | 305 base::BindBlock(^{ return [[AVCaptureDeviceGlue devices] retain]; }), |
| 306 base::Bind(&SuspendObserverDelegate::DoStartObserver, this)); | 306 base::Bind(&SuspendObserverDelegate::DoStartObserver, this)); |
| 307 } | 307 } |
| 308 | 308 |
| 309 void SuspendObserverDelegate::OnDeviceChanged( | 309 void SuspendObserverDelegate::OnDeviceChanged( |
| 310 const scoped_refptr<base::SingleThreadTaskRunner>& device_thread) { | 310 const scoped_refptr<base::SingleThreadTaskRunner>& device_thread) { |
| 311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 311 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 312 // Enumerate the devices in Device thread and post the consolidation of the | 312 // Enumerate the devices in Device thread and post the consolidation of the |
| 313 // new devices and the old ones to be done on UI thread. The devices array | 313 // new devices and the old ones to be done on UI thread. The devices array |
| 314 // is retained in |device_thread| and released in DoOnDeviceChanged(). | 314 // is retained in |device_thread| and released in DoOnDeviceChanged(). |
| 315 PostTaskAndReplyWithResult( | 315 PostTaskAndReplyWithResult( |
| 316 device_thread.get(), | 316 device_thread.get(), |
| 317 FROM_HERE, | 317 FROM_HERE, |
| 318 base::BindBlock(^{ return [[AVCaptureDeviceGlue devices] retain]; }), | 318 base::BindBlock(^{ return [[AVCaptureDeviceGlue devices] retain]; }), |
| 319 base::Bind(&SuspendObserverDelegate::DoOnDeviceChanged, this)); | 319 base::Bind(&SuspendObserverDelegate::DoOnDeviceChanged, this)); |
| 320 } | 320 } |
| 321 | 321 |
| 322 void SuspendObserverDelegate::ResetDeviceMonitor() { | 322 void SuspendObserverDelegate::ResetDeviceMonitor() { |
| 323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 323 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 324 avfoundation_monitor_impl_ = NULL; | 324 avfoundation_monitor_impl_ = NULL; |
| 325 [suspend_observer_ clearOnDeviceChangedCallback]; | 325 [suspend_observer_ clearOnDeviceChangedCallback]; |
| 326 } | 326 } |
| 327 | 327 |
| 328 SuspendObserverDelegate::~SuspendObserverDelegate() { | 328 SuspendObserverDelegate::~SuspendObserverDelegate() { |
| 329 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 329 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 330 } | 330 } |
| 331 | 331 |
| 332 void SuspendObserverDelegate::DoStartObserver(NSArray* devices) { | 332 void SuspendObserverDelegate::DoStartObserver(NSArray* devices) { |
| 333 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 333 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 334 base::scoped_nsobject<NSArray> auto_release(devices); | 334 base::scoped_nsobject<NSArray> auto_release(devices); |
| 335 for (CrAVCaptureDevice* device in devices) { | 335 for (CrAVCaptureDevice* device in devices) { |
| 336 base::scoped_nsobject<CrAVCaptureDevice> device_ptr([device retain]); | 336 base::scoped_nsobject<CrAVCaptureDevice> device_ptr([device retain]); |
| 337 [suspend_observer_ startObserving:device_ptr]; | 337 [suspend_observer_ startObserving:device_ptr]; |
| 338 } | 338 } |
| 339 } | 339 } |
| 340 | 340 |
| 341 void SuspendObserverDelegate::DoOnDeviceChanged(NSArray* devices) { | 341 void SuspendObserverDelegate::DoOnDeviceChanged(NSArray* devices) { |
| 342 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 342 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 343 base::scoped_nsobject<NSArray> auto_release(devices); | 343 base::scoped_nsobject<NSArray> auto_release(devices); |
| 344 std::vector<DeviceInfo> snapshot_devices; | 344 std::vector<DeviceInfo> snapshot_devices; |
| 345 for (CrAVCaptureDevice* device in devices) { | 345 for (CrAVCaptureDevice* device in devices) { |
| 346 base::scoped_nsobject<CrAVCaptureDevice> device_ptr([device retain]); | 346 base::scoped_nsobject<CrAVCaptureDevice> device_ptr([device retain]); |
| 347 [suspend_observer_ startObserving:device_ptr]; | 347 [suspend_observer_ startObserving:device_ptr]; |
| 348 | 348 |
| 349 BOOL suspended = [device respondsToSelector:@selector(isSuspended)] && | 349 BOOL suspended = [device respondsToSelector:@selector(isSuspended)] && |
| 350 [device isSuspended]; | 350 [device isSuspended]; |
| 351 DeviceInfo::DeviceType device_type = DeviceInfo::kUnknown; | 351 DeviceInfo::DeviceType device_type = DeviceInfo::kUnknown; |
| 352 if ([device hasMediaType:AVFoundationGlue::AVMediaTypeVideo()]) { | 352 if ([device hasMediaType:AVFoundationGlue::AVMediaTypeVideo()]) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 | 397 |
| 398 DISALLOW_COPY_AND_ASSIGN(AVFoundationMonitorImpl); | 398 DISALLOW_COPY_AND_ASSIGN(AVFoundationMonitorImpl); |
| 399 }; | 399 }; |
| 400 | 400 |
| 401 AVFoundationMonitorImpl::AVFoundationMonitorImpl( | 401 AVFoundationMonitorImpl::AVFoundationMonitorImpl( |
| 402 content::DeviceMonitorMac* monitor, | 402 content::DeviceMonitorMac* monitor, |
| 403 const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) | 403 const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) |
| 404 : DeviceMonitorMacImpl(monitor), | 404 : DeviceMonitorMacImpl(monitor), |
| 405 device_task_runner_(device_task_runner), | 405 device_task_runner_(device_task_runner), |
| 406 suspend_observer_delegate_(new SuspendObserverDelegate(this)) { | 406 suspend_observer_delegate_(new SuspendObserverDelegate(this)) { |
| 407 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 407 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 408 NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; | 408 NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; |
| 409 device_arrival_ = | 409 device_arrival_ = |
| 410 [nc addObserverForName:AVFoundationGlue:: | 410 [nc addObserverForName:AVFoundationGlue:: |
| 411 AVCaptureDeviceWasConnectedNotification() | 411 AVCaptureDeviceWasConnectedNotification() |
| 412 object:nil | 412 object:nil |
| 413 queue:nil | 413 queue:nil |
| 414 usingBlock:^(NSNotification* notification) { | 414 usingBlock:^(NSNotification* notification) { |
| 415 OnDeviceChanged();}]; | 415 OnDeviceChanged();}]; |
| 416 device_removal_ = | 416 device_removal_ = |
| 417 [nc addObserverForName:AVFoundationGlue:: | 417 [nc addObserverForName:AVFoundationGlue:: |
| 418 AVCaptureDeviceWasDisconnectedNotification() | 418 AVCaptureDeviceWasDisconnectedNotification() |
| 419 object:nil | 419 object:nil |
| 420 queue:nil | 420 queue:nil |
| 421 usingBlock:^(NSNotification* notification) { | 421 usingBlock:^(NSNotification* notification) { |
| 422 OnDeviceChanged();}]; | 422 OnDeviceChanged();}]; |
| 423 suspend_observer_delegate_->StartObserver(device_task_runner_); | 423 suspend_observer_delegate_->StartObserver(device_task_runner_); |
| 424 } | 424 } |
| 425 | 425 |
| 426 AVFoundationMonitorImpl::~AVFoundationMonitorImpl() { | 426 AVFoundationMonitorImpl::~AVFoundationMonitorImpl() { |
| 427 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 427 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 428 suspend_observer_delegate_->ResetDeviceMonitor(); | 428 suspend_observer_delegate_->ResetDeviceMonitor(); |
| 429 NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; | 429 NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; |
| 430 [nc removeObserver:device_arrival_]; | 430 [nc removeObserver:device_arrival_]; |
| 431 [nc removeObserver:device_removal_]; | 431 [nc removeObserver:device_removal_]; |
| 432 } | 432 } |
| 433 | 433 |
| 434 void AVFoundationMonitorImpl::OnDeviceChanged() { | 434 void AVFoundationMonitorImpl::OnDeviceChanged() { |
| 435 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 435 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 436 suspend_observer_delegate_->OnDeviceChanged(device_task_runner_); | 436 suspend_observer_delegate_->OnDeviceChanged(device_task_runner_); |
| 437 } | 437 } |
| 438 | 438 |
| 439 } // namespace | 439 } // namespace |
| 440 | 440 |
| 441 @implementation CrAVFoundationDeviceObserver | 441 @implementation CrAVFoundationDeviceObserver |
| 442 | 442 |
| 443 - (id)initWithOnChangedCallback:(const base::Closure&)callback { | 443 - (id)initWithOnChangedCallback:(const base::Closure&)callback { |
| 444 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 444 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 445 if ((self = [super init])) { | 445 if ((self = [super init])) { |
| 446 DCHECK(!callback.is_null()); | 446 DCHECK(!callback.is_null()); |
| 447 onDeviceChangedCallback_ = callback; | 447 onDeviceChangedCallback_ = callback; |
| 448 } | 448 } |
| 449 return self; | 449 return self; |
| 450 } | 450 } |
| 451 | 451 |
| 452 - (void)dealloc { | 452 - (void)dealloc { |
| 453 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 453 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 454 std::set<base::scoped_nsobject<CrAVCaptureDevice> >::iterator it = | 454 std::set<base::scoped_nsobject<CrAVCaptureDevice> >::iterator it = |
| 455 monitoredDevices_.begin(); | 455 monitoredDevices_.begin(); |
| 456 while (it != monitoredDevices_.end()) | 456 while (it != monitoredDevices_.end()) |
| 457 [self removeObservers:*(it++)]; | 457 [self removeObservers:*(it++)]; |
| 458 [super dealloc]; | 458 [super dealloc]; |
| 459 } | 459 } |
| 460 | 460 |
| 461 - (void)startObserving:(base::scoped_nsobject<CrAVCaptureDevice>)device { | 461 - (void)startObserving:(base::scoped_nsobject<CrAVCaptureDevice>)device { |
| 462 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 462 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 463 DCHECK(device != nil); | 463 DCHECK(device != nil); |
| 464 // Skip this device if there are already observers connected to it. | 464 // Skip this device if there are already observers connected to it. |
| 465 if (std::find(monitoredDevices_.begin(), monitoredDevices_.end(), device) != | 465 if (std::find(monitoredDevices_.begin(), monitoredDevices_.end(), device) != |
| 466 monitoredDevices_.end()) { | 466 monitoredDevices_.end()) { |
| 467 return; | 467 return; |
| 468 } | 468 } |
| 469 [device addObserver:self | 469 [device addObserver:self |
| 470 forKeyPath:@"suspended" | 470 forKeyPath:@"suspended" |
| 471 options:0 | 471 options:0 |
| 472 context:device.get()]; | 472 context:device.get()]; |
| 473 [device addObserver:self | 473 [device addObserver:self |
| 474 forKeyPath:@"connected" | 474 forKeyPath:@"connected" |
| 475 options:0 | 475 options:0 |
| 476 context:device.get()]; | 476 context:device.get()]; |
| 477 monitoredDevices_.insert(device); | 477 monitoredDevices_.insert(device); |
| 478 } | 478 } |
| 479 | 479 |
| 480 - (void)stopObserving:(CrAVCaptureDevice*)device { | 480 - (void)stopObserving:(CrAVCaptureDevice*)device { |
| 481 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 481 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 482 DCHECK(device != nil); | 482 DCHECK(device != nil); |
| 483 | 483 |
| 484 std::set<base::scoped_nsobject<CrAVCaptureDevice> >::iterator found = | 484 std::set<base::scoped_nsobject<CrAVCaptureDevice> >::iterator found = |
| 485 std::find(monitoredDevices_.begin(), monitoredDevices_.end(), device); | 485 std::find(monitoredDevices_.begin(), monitoredDevices_.end(), device); |
| 486 DCHECK(found != monitoredDevices_.end()); | 486 DCHECK(found != monitoredDevices_.end()); |
| 487 [self removeObservers:*found]; | 487 [self removeObservers:*found]; |
| 488 monitoredDevices_.erase(found); | 488 monitoredDevices_.erase(found); |
| 489 } | 489 } |
| 490 | 490 |
| 491 - (void)clearOnDeviceChangedCallback { | 491 - (void)clearOnDeviceChangedCallback { |
| 492 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 492 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 493 onDeviceChangedCallback_.Reset(); | 493 onDeviceChangedCallback_.Reset(); |
| 494 } | 494 } |
| 495 | 495 |
| 496 - (void)removeObservers:(CrAVCaptureDevice*)device { | 496 - (void)removeObservers:(CrAVCaptureDevice*)device { |
| 497 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 497 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 498 // Check sanity of |device| via its -observationInfo. http://crbug.com/371271. | 498 // Check sanity of |device| via its -observationInfo. http://crbug.com/371271. |
| 499 if ([device observationInfo]) { | 499 if ([device observationInfo]) { |
| 500 [device removeObserver:self | 500 [device removeObserver:self |
| 501 forKeyPath:@"suspended"]; | 501 forKeyPath:@"suspended"]; |
| 502 [device removeObserver:self | 502 [device removeObserver:self |
| 503 forKeyPath:@"connected"]; | 503 forKeyPath:@"connected"]; |
| 504 } | 504 } |
| 505 } | 505 } |
| 506 | 506 |
| 507 - (void)observeValueForKeyPath:(NSString*)keyPath | 507 - (void)observeValueForKeyPath:(NSString*)keyPath |
| 508 ofObject:(id)object | 508 ofObject:(id)object |
| 509 change:(NSDictionary*)change | 509 change:(NSDictionary*)change |
| 510 context:(void*)context { | 510 context:(void*)context { |
| 511 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 511 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 512 if ([keyPath isEqual:@"suspended"]) | 512 if ([keyPath isEqual:@"suspended"]) |
| 513 onDeviceChangedCallback_.Run(); | 513 onDeviceChangedCallback_.Run(); |
| 514 if ([keyPath isEqual:@"connected"]) | 514 if ([keyPath isEqual:@"connected"]) |
| 515 [self stopObserving:static_cast<CrAVCaptureDevice*>(context)]; | 515 [self stopObserving:static_cast<CrAVCaptureDevice*>(context)]; |
| 516 } | 516 } |
| 517 | 517 |
| 518 @end // @implementation CrAVFoundationDeviceObserver | 518 @end // @implementation CrAVFoundationDeviceObserver |
| 519 | 519 |
| 520 namespace content { | 520 namespace content { |
| 521 | 521 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 552 } | 552 } |
| 553 | 553 |
| 554 void DeviceMonitorMac::NotifyDeviceChanged( | 554 void DeviceMonitorMac::NotifyDeviceChanged( |
| 555 base::SystemMonitor::DeviceType type) { | 555 base::SystemMonitor::DeviceType type) { |
| 556 DCHECK(thread_checker_.CalledOnValidThread()); | 556 DCHECK(thread_checker_.CalledOnValidThread()); |
| 557 // TODO(xians): Remove the global variable for SystemMonitor. | 557 // TODO(xians): Remove the global variable for SystemMonitor. |
| 558 base::SystemMonitor::Get()->ProcessDevicesChanged(type); | 558 base::SystemMonitor::Get()->ProcessDevicesChanged(type); |
| 559 } | 559 } |
| 560 | 560 |
| 561 } // namespace content | 561 } // namespace content |
| OLD | NEW |