1/*
2 * libjingle
3 * Copyright 2004--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#include "talk/session/phone/devicemanager.h"
29
30#import <QTKit/QTKit.h>
31
32#include "talk/base/logging.h"
33
34@interface DeviceWatcherImpl : NSObject {
35@private
36  cricket::DeviceManager* manager_;
37}
38- (id)init:(cricket::DeviceManager*) dm;
39- (void)onDevicesChanged:(NSNotification *)notification;
40@end
41
42@implementation DeviceWatcherImpl
43- (id)init:(cricket::DeviceManager*) dm {
44  if ((self = [super init])) {
45    manager_ = dm;
46    [[NSNotificationCenter defaultCenter] addObserver:self
47        selector:@selector(onDevicesChanged:)
48        name:QTCaptureDeviceWasConnectedNotification
49        object:nil];
50    [[NSNotificationCenter defaultCenter] addObserver:self
51        selector:@selector(onDevicesChanged:)
52        name:QTCaptureDeviceWasDisconnectedNotification
53        object:nil];
54  }
55  return self;
56}
57- (void)dealloc {
58  [[NSNotificationCenter defaultCenter] removeObserver:self];
59  [super dealloc];
60}
61- (void)onDevicesChanged:(NSNotification *)notification {
62  manager_->OnDevicesChange();
63}
64@end
65
66namespace cricket {
67
68void* CreateDeviceWatcherCallback(DeviceManager* dm) {
69  return [[DeviceWatcherImpl alloc] init:dm];
70}
71void ReleaseDeviceWatcherCallback(void* watcher) {
72  DeviceWatcherImpl* watcher_impl = static_cast<DeviceWatcherImpl*>(watcher);
73  [watcher_impl release];
74}
75
76bool GetQTKitVideoDevices(std::vector<Device>* devices) {
77  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
78
79  NSArray* qt_capture_devices =
80      [QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo];
81  NSUInteger count = [qt_capture_devices count];
82  LOG(LS_INFO) << count << " capture device(s) found:";
83  for (NSUInteger i = 0; i < count; ++i) {
84    QTCaptureDevice* qt_capture_device = [qt_capture_devices objectAtIndex:i];
85
86    static const NSString* kFormat = @"localizedDisplayName: \"%@\", "
87        "modelUniqueID: \"%@\", uniqueID \"%@\", isConnected: %d, isOpen: %d, "
88        "isInUseByAnotherApplication: %d";
89    NSString* info = [NSString stringWithFormat:kFormat,
90        [qt_capture_device localizedDisplayName],
91        [qt_capture_device modelUniqueID],
92        [qt_capture_device uniqueID],
93        [qt_capture_device isConnected],
94        [qt_capture_device isOpen],
95        [qt_capture_device isInUseByAnotherApplication]];
96    LOG(LS_INFO) << [info cStringUsingEncoding:NSUTF8StringEncoding];
97
98    std::string name([[qt_capture_device localizedDisplayName]
99                         cStringUsingEncoding:NSUTF8StringEncoding]);
100    devices->push_back(Device(name,
101       [[qt_capture_device uniqueID]
102           cStringUsingEncoding:NSUTF8StringEncoding]));
103  }
104
105  [pool drain];
106  return true;
107}
108
109}  // namespace cricket
110