Home | History | Annotate | Download | only in devices
      1 /*
      2  * libjingle
      3  * Copyright 2010 Google Inc.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *
      8  *  1. Redistributions of source code must retain the above copyright notice,
      9  *     this list of conditions and the following disclaimer.
     10  *  2. Redistributions in binary form must reproduce the above copyright notice,
     11  *     this list of conditions and the following disclaimer in the documentation
     12  *     and/or other materials provided with the distribution.
     13  *  3. The name of the author may not be used to endorse or promote products
     14  *     derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
     19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 // support GCC compiler
     29 #ifndef __has_feature
     30 #define __has_feature(x) 0
     31 #endif
     32 
     33 #include "talk/media/devices/devicemanager.h"
     34 
     35 #import <assert.h>
     36 #ifdef __MAC_OS_X_VERSION_MAX_ALLOWED
     37 #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
     38   #import <AVFoundation/AVFoundation.h>
     39 #endif
     40 #endif
     41 #import <QTKit/QTKit.h>
     42 
     43 #include "webrtc/base/logging.h"
     44 
     45 @interface DeviceWatcherImpl : NSObject {
     46  @private
     47   cricket::DeviceManagerInterface* manager_;
     48 }
     49 - (id)init:(cricket::DeviceManagerInterface*)manager;
     50 - (void)onDevicesChanged:(NSNotification*)notification;
     51 @end
     52 
     53 @implementation DeviceWatcherImpl
     54 - (id)init:(cricket::DeviceManagerInterface*)manager {
     55   if ((self = [super init])) {
     56     assert(manager != NULL);
     57     manager_ = manager;
     58     [[NSNotificationCenter defaultCenter]
     59         addObserver:self
     60            selector:@selector(onDevicesChanged:)
     61                name:QTCaptureDeviceWasConnectedNotification
     62              object:nil];
     63     [[NSNotificationCenter defaultCenter]
     64         addObserver:self
     65            selector:@selector(onDevicesChanged:)
     66                name:QTCaptureDeviceWasDisconnectedNotification
     67              object:nil];
     68   }
     69   return self;
     70 }
     71 
     72 - (void)dealloc {
     73   [[NSNotificationCenter defaultCenter] removeObserver:self];
     74 #if !__has_feature(objc_arc)
     75   [super dealloc];
     76 #endif
     77 }
     78 - (void)onDevicesChanged:(NSNotification*)notification {
     79   manager_->SignalDevicesChange();
     80 }
     81 @end
     82 
     83 namespace cricket {
     84 
     85 DeviceWatcherImpl* CreateDeviceWatcherCallback(
     86     DeviceManagerInterface* manager) {
     87   DeviceWatcherImpl* impl;
     88 #if !__has_feature(objc_arc)
     89   NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
     90 #else
     91   @autoreleasepool
     92 #endif
     93   { impl = [[DeviceWatcherImpl alloc] init:manager]; }
     94 #if !__has_feature(objc_arc)
     95   [pool drain];
     96 #endif
     97   return impl;
     98 }
     99 
    100 void ReleaseDeviceWatcherCallback(DeviceWatcherImpl* watcher) {
    101 #if !__has_feature(objc_arc)
    102   NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    103   [watcher release];
    104   [pool drain];
    105 #endif
    106 }
    107 
    108 bool GetQTKitVideoDevices(std::vector<Device>* devices) {
    109 #if !__has_feature(objc_arc)
    110   NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    111 #else
    112   @autoreleasepool
    113 #endif
    114   {
    115     NSArray* qt_capture_devices =
    116         [QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo];
    117     NSUInteger count = [qt_capture_devices count];
    118     LOG(LS_INFO) << count << " capture device(s) found:";
    119     for (QTCaptureDevice* qt_capture_device in qt_capture_devices) {
    120       static NSString* const kFormat = @"localizedDisplayName: \"%@\", "
    121           @"modelUniqueID: \"%@\", uniqueID \"%@\", isConnected: %d, "
    122           @"isOpen: %d, isInUseByAnotherApplication: %d";
    123       NSString* info = [NSString
    124           stringWithFormat:kFormat,
    125                            [qt_capture_device localizedDisplayName],
    126                            [qt_capture_device modelUniqueID],
    127                            [qt_capture_device uniqueID],
    128                            [qt_capture_device isConnected],
    129                            [qt_capture_device isOpen],
    130                            [qt_capture_device isInUseByAnotherApplication]];
    131       LOG(LS_INFO) << [info UTF8String];
    132 
    133       std::string name([[qt_capture_device localizedDisplayName] UTF8String]);
    134       devices->push_back(
    135           Device(name, [[qt_capture_device uniqueID] UTF8String]));
    136     }
    137   }
    138 #if !__has_feature(objc_arc)
    139   [pool drain];
    140 #endif
    141   return true;
    142 }
    143 
    144 bool GetAVFoundationVideoDevices(std::vector<Device>* devices) {
    145 #ifdef __MAC_OS_X_VERSION_MAX_ALLOWED
    146 #if __MAC_OS_X_VERSION_MAX_ALLOWED >=1070
    147   if (![AVCaptureDevice class]) {
    148     // Fallback to using QTKit if AVFoundation is not available
    149     return GetQTKitVideoDevices(devices);
    150   }
    151 #if !__has_feature(objc_arc)
    152   NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    153 #else
    154   @autoreleasepool
    155 #endif
    156   {
    157     NSArray* capture_devices = [AVCaptureDevice devices];
    158     LOG(LS_INFO) << [capture_devices count] << " capture device(s) found:";
    159     for (AVCaptureDevice* capture_device in capture_devices) {
    160       if ([capture_device hasMediaType:AVMediaTypeVideo] ||
    161           [capture_device hasMediaType:AVMediaTypeMuxed]) {
    162         static NSString* const kFormat = @"localizedName: \"%@\", "
    163             @"modelID: \"%@\", uniqueID \"%@\", isConnected: %d, "
    164             @"isInUseByAnotherApplication: %d";
    165         NSString* info = [NSString
    166             stringWithFormat:kFormat,
    167                              [capture_device localizedName],
    168                              [capture_device modelID],
    169                              [capture_device uniqueID],
    170                              [capture_device isConnected],
    171                              [capture_device isInUseByAnotherApplication]];
    172         LOG(LS_INFO) << [info UTF8String];
    173 
    174         std::string name([[capture_device localizedName] UTF8String]);
    175         devices->push_back(
    176             Device(name, [[capture_device uniqueID] UTF8String]));
    177       }
    178     }
    179   }
    180 #if !__has_feature(objc_arc)
    181   [pool drain];
    182 #endif
    183   return true;
    184 #else  // __MAC_OS_X_VERSION_MAX_ALLOWED >=1070
    185   return GetQTKitVideoDevices(devices);
    186 #endif  // __MAC_OS_X_VERSION_MAX_ALLOWED >=1070
    187 #else  // __MAC_OS_X_VERSION_MAX_ALLOWED
    188   return GetQTKitVideoDevices(devices);
    189 #endif  // __MAC_OS_X_VERSION_MAX_ALLOWED
    190 }
    191 
    192 }  // namespace cricket
    193