├── Cartfile
├── Cartfile.resolved
├── StreamIt
├── Assets.xcassets
│ ├── Contents.json
│ ├── led_gray.imageset
│ │ ├── led_gray.png
│ │ └── Contents.json
│ ├── led_red.imageset
│ │ ├── led_red.png
│ │ └── Contents.json
│ ├── AppIcon.appiconset
│ │ ├── Icon-App-20x20@1x.png
│ │ ├── Icon-App-20x20@2x.png
│ │ ├── Icon-App-20x20@3x.png
│ │ ├── Icon-App-29x29@1x.png
│ │ ├── Icon-App-29x29@2x.png
│ │ ├── Icon-App-29x29@3x.png
│ │ ├── Icon-App-40x40@1x.png
│ │ ├── Icon-App-40x40@2x.png
│ │ ├── Icon-App-40x40@3x.png
│ │ ├── Icon-App-57x57@1x.png
│ │ ├── Icon-App-57x57@2x.png
│ │ ├── Icon-App-60x60@2x.png
│ │ ├── Icon-App-60x60@3x.png
│ │ ├── Icon-App-72x72@1x.png
│ │ ├── Icon-App-72x72@2x.png
│ │ ├── Icon-App-76x76@1x.png
│ │ ├── Icon-App-76x76@2x.png
│ │ ├── ItunesArtwork@2x.png
│ │ ├── Icon-Small-50x50@1x.png
│ │ ├── Icon-Small-50x50@2x.png
│ │ ├── Icon-App-83.5x83.5@2x.png
│ │ └── Contents.json
│ └── information.imageset
│ │ ├── Dialog-Box-About-128.png
│ │ └── Contents.json
├── StreamIt-Bridging-Header.h
├── IPChecker
│ ├── IPChecker.h
│ └── IPChecker.m
├── AppDelegate.swift
├── Queue.swift
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── Info.plist
├── StreamingSession.swift
└── CameraViewController.swift
├── StreamIt.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── project.pbxproj
├── README.md
├── LICENSE
└── .gitignore
/Cartfile:
--------------------------------------------------------------------------------
1 | github "robbiehanson/CocoaAsyncSocket" "master"
--------------------------------------------------------------------------------
/Cartfile.resolved:
--------------------------------------------------------------------------------
1 | github "robbiehanson/CocoaAsyncSocket" "53a1298f4bbb735a1e7ab235f6e74cf099a1583b"
2 |
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/led_gray.imageset/led_gray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/led_gray.imageset/led_gray.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/led_red.imageset/led_red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/led_red.imageset/led_red.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png
--------------------------------------------------------------------------------
/StreamIt/StreamIt-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Use this file to import your target's public headers that you would like to expose to Swift.
3 | //
4 |
5 | #import "IPChecker.h"
6 |
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-Small-50x50@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-Small-50x50@1x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-Small-50x50@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-Small-50x50@2x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/information.imageset/Dialog-Box-About-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twittemb/StreamIt/HEAD/StreamIt/Assets.xcassets/information.imageset/Dialog-Box-About-128.png
--------------------------------------------------------------------------------
/StreamIt.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # StreamIt
2 | This iOS app turns your iOS device into a streaming camera.
3 |
4 | Simply launch the app and tap the screen to display your streaming URL. Copy this URL in a web browser and that's it.
5 |
6 | Beware, this works only on a local network (not over the Internet).
7 |
--------------------------------------------------------------------------------
/StreamIt.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/StreamIt/IPChecker/IPChecker.h:
--------------------------------------------------------------------------------
1 | //
2 | // IPChecker.h
3 | // anus
4 | //
5 | // Created by Thibault Wittemberg on 05/04/2016.
6 | // Copyright © 2016 Thibault Wittemberg. All rights reserved.
7 | //
8 |
9 | #ifndef IPChecker_h
10 | #define IPChecker_h
11 |
12 |
13 | #endif /* IPChecker_h */
14 |
15 | #import
16 |
17 | @interface IPChecker : NSObject
18 |
19 | + (NSString *)getIP;
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/led_gray.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "led_gray.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/led_red.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "led_red.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/information.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Dialog-Box-About-128.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/StreamIt/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // StreamIt
4 | //
5 | // Created by Thibault Wittemberg on 14/04/2016.
6 | // Copyright © 2016 Thibault Wittemberg. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import CocoaAsyncSocket
11 |
12 | @UIApplicationMain
13 | class AppDelegate: UIResponder, UIApplicationDelegate {
14 |
15 | var window: UIWindow?
16 |
17 | // MARK: -
18 |
19 | internal func application(_ application: UIApplication,
20 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
21 | return true
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/StreamIt/IPChecker/IPChecker.m:
--------------------------------------------------------------------------------
1 | //
2 | // IPChecker.m
3 | // anus
4 | //
5 | // Created by Thibault Wittemberg on 05/04/2016.
6 | // Copyright © 2016 Thibault Wittemberg. All rights reserved.
7 | //
8 |
9 | #import
10 | #include
11 | #include
12 | #include "IPChecker.h"
13 |
14 | @implementation IPChecker
15 |
16 | + (NSString *)getIP
17 | {
18 | NSString *address = @"ip_address_error";
19 | struct ifaddrs *interfaces = NULL;
20 | struct ifaddrs *addr = NULL;
21 | int got = getifaddrs(&interfaces);
22 | if (got == 0) {
23 | addr = interfaces;
24 | while (addr != NULL) {
25 | if( addr->ifa_addr->sa_family == AF_INET) {
26 | if ([[NSString stringWithUTF8String:addr->ifa_name] isEqualToString:@"en0"]) {
27 | address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)addr->ifa_addr)->sin_addr)];
28 | }
29 | }
30 |
31 | addr = addr->ifa_next;
32 | }
33 | }
34 |
35 | freeifaddrs(interfaces);
36 |
37 | return address;
38 | }
39 | @end
40 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Thibault Wittemberg
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/StreamIt/Queue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Queue.swift
3 | // StreamIt
4 | //
5 | // Created by Thibault Wittemberg on 14/04/2016.
6 | // Copyright © 2016 Thibault Wittemberg. All rights reserved.
7 | //
8 |
9 | private class QueueItem {
10 |
11 | fileprivate let value: T!
12 | fileprivate var next: QueueItem?
13 |
14 | init(_ newvalue: T?) {
15 | self.value = newvalue
16 | }
17 | }
18 |
19 | open class Queue {
20 |
21 | fileprivate var _front: QueueItem
22 | fileprivate var _back: QueueItem
23 | fileprivate var maxCapacity: Int
24 | fileprivate var currentSize = 0
25 |
26 | public init(maxCapacity: Int) {
27 | // Insert dummy item. Will disappear when the first item is added.
28 | _back = QueueItem(nil)
29 | _front = _back
30 | self.maxCapacity = maxCapacity
31 | }
32 |
33 | /// Add a new item to the back of the queue.
34 | open func enqueue(_ value: T) {
35 | if self.currentSize >= maxCapacity {
36 | _back = QueueItem(value)
37 | } else {
38 | _back.next = QueueItem(value)
39 | _back = _back.next!
40 | self.currentSize += 1
41 | }
42 | }
43 |
44 | /// Return and remove the item at the front of the queue.
45 | open func dequeue() -> T? {
46 | if let newhead = _front.next {
47 | _front = newhead
48 | self.currentSize -= 1
49 | return newhead.value
50 | } else {
51 | self.currentSize = 0
52 | return nil
53 | }
54 | }
55 |
56 | open func isEmpty() -> Bool {
57 | return _front === _back
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/StreamIt/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/StreamIt/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | NSAppTransportSecurity
26 |
27 | NSAllowsArbitraryLoads
28 |
29 |
30 | NSCameraUsageDescription
31 | $(PRODUCT_NAME) photo use
32 | UILaunchStoryboardName
33 | LaunchScreen
34 | UIMainStoryboardFile
35 | Main
36 | UIRequiredDeviceCapabilities
37 |
38 | armv7
39 |
40 | UIRequiresFullScreen
41 |
42 | UIStatusBarHidden
43 |
44 | UIStatusBarStyle
45 | UIStatusBarStyleLightContent
46 | UISupportedInterfaceOrientations
47 |
48 | UIInterfaceOrientationPortrait
49 |
50 | UISupportedInterfaceOrientations~ipad
51 |
52 | UIInterfaceOrientationPortrait
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 | RxFlow.framework.zip
9 | undocumented.json
10 |
11 | ## macos
12 | .DS_Store
13 |
14 | ## Various settings
15 | *.pbxuser
16 | !default.pbxuser
17 | *.mode1v3
18 | !default.mode1v3
19 | *.mode2v3
20 | !default.mode2v3
21 | *.perspectivev3
22 | !default.perspectivev3
23 | xcuserdata/
24 |
25 | ## Other
26 | *.moved-aside
27 | *.xccheckout
28 | *.xcscmblueprint
29 |
30 | ## Obj-C/Swift specific
31 | *.hmap
32 | *.ipa
33 | *.dSYM.zip
34 | *.dSYM
35 |
36 | ## Playgrounds
37 | timeline.xctimeline
38 | playground.xcworkspace
39 |
40 | # Swift Package Manager
41 | #
42 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
43 | # Packages/
44 | # Package.pins
45 | .build/
46 |
47 | # CocoaPods
48 | #
49 | # We recommend against adding the Pods directory to your .gitignore. However
50 | # you should judge for yourself, the pros and cons are mentioned at:
51 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
52 | #
53 | # Pods/
54 |
55 | # Carthage
56 | #
57 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
58 | Carthage
59 | Carthage/Checkouts
60 | Carthage/Build
61 |
62 | # fastlane
63 | #
64 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
65 | # screenshots whenever they are needed.
66 | # For more information about the recommended setup visit:
67 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
68 |
69 | fastlane/report.xml
70 | fastlane/Preview.html
71 | fastlane/screenshots
72 | fastlane/test_output
73 |
74 | .idea
75 | Package.resolved
76 | .swiftpm
77 |
--------------------------------------------------------------------------------
/StreamIt/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "57x57",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-57x57@1x.png",
49 | "scale" : "1x"
50 | },
51 | {
52 | "size" : "57x57",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-57x57@2x.png",
55 | "scale" : "2x"
56 | },
57 | {
58 | "size" : "60x60",
59 | "idiom" : "iphone",
60 | "filename" : "Icon-App-60x60@2x.png",
61 | "scale" : "2x"
62 | },
63 | {
64 | "size" : "60x60",
65 | "idiom" : "iphone",
66 | "filename" : "Icon-App-60x60@3x.png",
67 | "scale" : "3x"
68 | },
69 | {
70 | "size" : "20x20",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-20x20@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "20x20",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-20x20@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "29x29",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-29x29@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "29x29",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-29x29@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "40x40",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-40x40@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "40x40",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-40x40@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "50x50",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-Small-50x50@1x.png",
109 | "scale" : "1x"
110 | },
111 | {
112 | "size" : "50x50",
113 | "idiom" : "ipad",
114 | "filename" : "Icon-Small-50x50@2x.png",
115 | "scale" : "2x"
116 | },
117 | {
118 | "size" : "72x72",
119 | "idiom" : "ipad",
120 | "filename" : "Icon-App-72x72@1x.png",
121 | "scale" : "1x"
122 | },
123 | {
124 | "size" : "72x72",
125 | "idiom" : "ipad",
126 | "filename" : "Icon-App-72x72@2x.png",
127 | "scale" : "2x"
128 | },
129 | {
130 | "size" : "76x76",
131 | "idiom" : "ipad",
132 | "filename" : "Icon-App-76x76@1x.png",
133 | "scale" : "1x"
134 | },
135 | {
136 | "size" : "76x76",
137 | "idiom" : "ipad",
138 | "filename" : "Icon-App-76x76@2x.png",
139 | "scale" : "2x"
140 | },
141 | {
142 | "size" : "83.5x83.5",
143 | "idiom" : "ipad",
144 | "filename" : "Icon-App-83.5x83.5@2x.png",
145 | "scale" : "2x"
146 | },
147 | {
148 | "size" : "1024x1024",
149 | "idiom" : "ios-marketing",
150 | "filename" : "ItunesArtwork@2x.png",
151 | "scale" : "1x"
152 | }
153 | ],
154 | "info" : {
155 | "version" : 1,
156 | "author" : "xcode"
157 | }
158 | }
--------------------------------------------------------------------------------
/StreamIt/StreamingSession.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StreamingSession.swift
3 | // StreamIt
4 | //
5 | // Created by Thibault Wittemberg on 14/04/2016.
6 | // Copyright © 2016 Thibault Wittemberg. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import CocoaAsyncSocket
11 |
12 | class StreamingSession {
13 |
14 | fileprivate var client: GCDAsyncSocket
15 | fileprivate var headersSent = false
16 | fileprivate var dataStack = Queue(maxCapacity: 1)
17 | fileprivate var queue: DispatchQueue
18 | fileprivate let footersData = ["", ""].joined(separator: "\r\n").data(using: String.Encoding.utf8)
19 |
20 | var id: Int
21 | var connected = true
22 | var dataToSend: Data? {
23 | didSet {
24 | guard let dataToSend = self.dataToSend else { return }
25 |
26 | self.dataStack.enqueue(dataToSend)
27 | }
28 | }
29 |
30 | // MARK: - Lifecycle
31 |
32 | init (id: Int, client: GCDAsyncSocket, queue: DispatchQueue) {
33 | print("Creating client [#\(id)]")
34 |
35 | self.id = id
36 | self.client = client
37 | self.queue = queue
38 | }
39 |
40 | // MARK: - Methods
41 |
42 | func close() {
43 | print("Closing client [#\(self.id)]")
44 |
45 | self.connected = false
46 | }
47 |
48 | func startStreaming() {
49 | self.queue.async(execute: { [unowned self] in
50 | while self.connected {
51 |
52 | if !self.headersSent {
53 | print("Sending headers [#\(self.id)]")
54 |
55 | let headers = [
56 | "HTTP/1.0 200 OK",
57 | "Connection: keep-alive",
58 | "Ma-age: 0",
59 | "Expires: 0",
60 | "Cache-Control: no-store,must-revalidate",
61 | "Access-Control-Allow-Origin: *",
62 | "Access-Control-Allow-Headers: accept,content-type",
63 | "Access-Control-Allow-Methods: GET",
64 | "Access-Control-expose-headers: Cache-Control,Content-Encoding",
65 | "Pragma: no-cache",
66 | "Content-type: multipart/x-mixed-replace; boundary=0123456789876543210",
67 | ""
68 | ]
69 |
70 | guard let headersData = headers.joined(separator: "\r\n").data(using: String.Encoding.utf8) else {
71 | print("Could not make headers data [#\(self.id)]")
72 | return
73 | }
74 |
75 | self.headersSent = true
76 | self.client.write(headersData, withTimeout: -1, tag: 0)
77 | } else {
78 | if (self.client.connectedPort.hashValue == 0 || !self.client.isConnected) {
79 | // y a personne en face ... on arrête d'envoyer des données
80 | self.close()
81 | print("Dropping client [#\(self.id)]")
82 | }
83 |
84 | if let data = self.dataStack.dequeue() {
85 | let frameHeaders = [
86 | "",
87 | "--0123456789876543210",
88 | "Content-Type: image/jpeg",
89 | "Content-Length: \(data.count)",
90 | "",
91 | ""
92 | ]
93 |
94 | guard let frameHeadersData = frameHeaders.joined(separator: "\r\n").data(using: String.Encoding.utf8) else {
95 | print("Could not make frame headers data [#\(self.id)]")
96 | return
97 | }
98 |
99 | self.client.write(frameHeadersData, withTimeout: -1, tag: 0)
100 | self.client.write(data, withTimeout: -1, tag: 0)
101 | self.client.write(self.footersData!, withTimeout: -1, tag: self.id)
102 | }
103 | }
104 | }
105 | })
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/StreamIt/CameraViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CameraViewController.swift
3 | // StreamIt
4 | //
5 | // Created by Thibault Wittemberg on 14/04/2016.
6 | // Copyright © 2016 Thibault Wittemberg. All rights reserved.
7 | //
8 |
9 | import AVFoundation
10 | import CocoaAsyncSocket
11 | import UIKit
12 |
13 | final class CameraViewController: UIViewController {
14 |
15 | @IBOutlet fileprivate weak var cameraView: UIView!
16 | @IBOutlet fileprivate weak var plusLabel: UILabel!
17 | @IBOutlet fileprivate weak var minusLabel: UILabel!
18 | @IBOutlet fileprivate weak var zoomSlider: UISlider!
19 | @IBOutlet fileprivate weak var ledImage: UIImageView!
20 | @IBOutlet fileprivate weak var informationLabel: UILabel!
21 |
22 | fileprivate let ip = IPChecker.getIP()
23 | fileprivate let captureSession = AVCaptureSession()
24 | fileprivate var previewLayer: AVCaptureVideoPreviewLayer?
25 | fileprivate var captureDevice: AVCaptureDevice?
26 | fileprivate let videoOutput = AVCaptureVideoDataOutput()
27 | fileprivate var clients = [Int: StreamingSession]()
28 | fileprivate var serverSocket: GCDAsyncSocket?
29 | fileprivate var previousOrientation = UIDeviceOrientation.unknown
30 | fileprivate var ipIsDisplayed = false
31 | fileprivate var ipAddress = ""
32 |
33 | fileprivate let serverQueue = DispatchQueue(label: "ServerQueue", attributes: [])
34 | fileprivate let clientQueue = DispatchQueue(label: "ClientQueue", attributes: .concurrent)
35 | fileprivate let socketWriteQueue = DispatchQueue(label: "SocketWriteQueue", attributes: .concurrent)
36 |
37 | // MARK: - Lifecycle
38 |
39 | override func viewDidLoad() {
40 | super.viewDidLoad()
41 |
42 | // on crée la socket de service
43 | // Le serveur tourne dans sa propre queue (les méthodes de délégate seront exécutées dans cette queue)
44 | // Les clients possèdent également leur propre queue dexécution
45 | print("Création du serveur sur l'IP \(String(describing: self.ip))")
46 | self.serverSocket = GCDAsyncSocket(delegate: self, delegateQueue: self.serverQueue, socketQueue: self.socketWriteQueue)
47 |
48 | do {
49 | try self.serverSocket?.accept(onInterface: self.ip, port: 10001)
50 | } catch {
51 | print("Could not start listening on port 10001 (\(error))")
52 | }
53 |
54 | // Do any additional setup after loading the view.
55 | self.captureSession.sessionPreset = .medium
56 | let devices = AVCaptureDevice.devices()
57 |
58 | for device in devices {
59 | if device.hasMediaType(.video) {
60 | self.captureDevice = device
61 | if captureDevice != nil {
62 | print("Capture device found")
63 | beginSession()
64 | break
65 | }
66 | }
67 | }
68 |
69 | if let ip = self.ip {
70 | ipAddress = "http://\(ip):10001"
71 | } else {
72 | ipAddress = "IP address not available"
73 | }
74 |
75 | self.cameraView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(CameraViewController.tapOnCameraView)))
76 | }
77 |
78 | // MARK: - Actions
79 |
80 | @objc fileprivate func tapOnCameraView() {
81 |
82 | UIView.animate(withDuration: 1, animations: { [unowned self] in
83 | if self.ipIsDisplayed {
84 | self.informationLabel.alpha = 0
85 | } else {
86 | self.informationLabel.alpha = 1
87 | self.informationLabel.text = self.ipAddress
88 | }
89 |
90 | self.ipIsDisplayed = !self.ipIsDisplayed
91 | })
92 | }
93 |
94 | @IBAction fileprivate func zoomChanged(_ sender: UISlider, forEvent event: UIEvent) {
95 | do {
96 | try self.captureDevice?.lockForConfiguration()
97 | self.captureDevice?.videoZoomFactor = CGFloat(sender.value)
98 | self.captureDevice?.unlockForConfiguration()
99 | } catch {
100 | print("Could not lock configuration for capture device (\(error))")
101 | }
102 | }
103 |
104 | // MARK: - Helpers
105 |
106 | fileprivate func beginSession() {
107 | do {
108 | guard let captureDevice = self.captureDevice else {
109 | print("Could not find a capture device")
110 | return
111 | }
112 |
113 | try captureDevice.lockForConfiguration()
114 | captureDevice.focusMode = .continuousAutoFocus
115 | captureDevice.unlockForConfiguration()
116 |
117 | let maxZoom = captureDevice.activeFormat.videoMaxZoomFactor
118 | self.zoomSlider.maximumValue = Float(maxZoom) / 2
119 |
120 | try self.captureSession.addInput(AVCaptureDeviceInput(device: captureDevice))
121 | self.previewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession)
122 | guard let previewLayer = self.previewLayer else {
123 | print("Could not create a preview layer for session")
124 | return
125 | }
126 |
127 | let bounds = self.view.bounds
128 |
129 | previewLayer.bounds = CGRect(origin: CGPoint.zero, size: CGSize(width: bounds.width, height: bounds.height))
130 | previewLayer.videoGravity = .resize
131 | previewLayer.position = CGPoint(x: bounds.midX, y: bounds.midY)
132 |
133 | videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "AVSessionQueue", attributes: []))
134 | self.captureSession.addOutput(videoOutput)
135 | self.cameraView.layer.addSublayer(previewLayer)
136 |
137 | //self.previewLayer?.frame = self.view.layer.frame
138 | self.captureSession.startRunning()
139 | } catch {
140 | print("Could not begin a capture session (\(error))")
141 | }
142 | }
143 |
144 | let context = CIContext(options: nil)
145 |
146 | fileprivate func rotateLabels(_ angle: CGFloat) {
147 | DispatchQueue.main.async(execute: {
148 | UIView.animate(withDuration: 0.5, animations: {
149 | self.minusLabel.transform = CGAffineTransform.identity.rotated(by: angle)
150 | self.plusLabel.transform = CGAffineTransform.identity.rotated(by: angle)
151 | self.zoomSlider.transform = CGAffineTransform.identity.rotated(by: CGFloat(0))
152 | self.informationLabel.transform = CGAffineTransform.identity.rotated(by: angle)
153 | })
154 | })
155 | }
156 |
157 | fileprivate func switchLabels() {
158 | DispatchQueue.main.async(execute: {
159 | UIView.animate(withDuration: 0.5, animations: {
160 | let c1 = self.minusLabel.center
161 | let c2 = self.plusLabel.center
162 |
163 | let dx = c2.x - c1.x
164 | let dy = c2.y - c1.y
165 |
166 | self.minusLabel.transform = CGAffineTransform.identity.translatedBy(x: dx, y: dy)
167 | self.plusLabel.transform = CGAffineTransform.identity.translatedBy(x: -dx, y: -dy)
168 |
169 | self.minusLabel.transform = self.minusLabel.transform.rotated(by: CGFloat(-1/2 * Double.pi))
170 | self.plusLabel.transform = self.plusLabel.transform.rotated(by: CGFloat(-1/2 * Double.pi))
171 |
172 | self.zoomSlider.transform = CGAffineTransform.identity.rotated(by: CGFloat(Double.pi))
173 |
174 | self.informationLabel.transform = CGAffineTransform.identity.rotated(by: CGFloat(-1/2 * Double.pi))
175 |
176 | })
177 | })
178 | }
179 |
180 | fileprivate func updateOrientation() {
181 | let currentOrientation = UIDevice.current.orientation
182 | if currentOrientation != self.previousOrientation {
183 | switch currentOrientation {
184 | case .portrait:
185 | self.videoOutput.connection(with: .video)?.videoOrientation = .portrait
186 | self.rotateLabels(0)
187 | case .landscapeRight:
188 | self.videoOutput.connection(with: .video)?.videoOrientation = .landscapeLeft
189 | self.switchLabels()
190 | case .landscapeLeft:
191 | self.videoOutput.connection(with: .video)?.videoOrientation = .landscapeRight
192 | self.rotateLabels(CGFloat(1/2 * Double.pi))
193 | case .portraitUpsideDown:
194 | self.videoOutput.connection(with: .video)?.videoOrientation = .portraitUpsideDown
195 | self.rotateLabels(0)
196 | default:
197 | self.videoOutput.connection(with: .video)?.videoOrientation = .portrait
198 | self.rotateLabels(0)
199 | }
200 |
201 | self.previousOrientation = currentOrientation
202 | }
203 | }
204 | }
205 |
206 | // MARK: - AVCaptureVideoDataOutputSampleBufferDelegate
207 |
208 | extension CameraViewController: AVCaptureVideoDataOutputSampleBufferDelegate {
209 |
210 | func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
211 | self.updateOrientation()
212 |
213 | if !self.clients.isEmpty {
214 | guard let capture: CVImageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
215 | let sourceImage = CIImage(cvImageBuffer: capture, options: nil)
216 | guard let tempImage = self.context.createCGImage(sourceImage, from: sourceImage.extent) else { return }
217 | let image = UIImage(cgImage: tempImage)
218 | let imageToSend = image.jpegData(compressionQuality: 0)
219 |
220 | for (key, client) in self.clients {
221 | if client.connected {
222 | client.dataToSend = (imageToSend as NSData?)?.copy() as? Data
223 | } else {
224 | self.clients.removeValue(forKey: key)
225 | }
226 | }
227 |
228 | if self.clients.isEmpty {
229 | DispatchQueue.main.async(execute: {
230 | self.ledImage.image = UIImage(named: "led_gray")
231 | })
232 | }
233 | }
234 | }
235 | }
236 |
237 | // MARK: - GCDAsyncSocketDelegate
238 |
239 | extension CameraViewController: GCDAsyncSocketDelegate {
240 |
241 | func socket(_ sock: GCDAsyncSocket, didAcceptNewSocket newSocket: GCDAsyncSocket) {
242 | print("New client from IP \(newSocket.connectedHost ?? "unknown")")
243 | guard let clientId = newSocket.connectedAddress?.hashValue else { return }
244 |
245 | let newClient = StreamingSession(id: clientId, client: newSocket, queue: self.clientQueue)
246 | self.clients[clientId] = newClient
247 | newClient.startStreaming()
248 |
249 | DispatchQueue.main.async(execute: {
250 | self.ledImage.image = UIImage(named: "led_red")
251 | })
252 | }
253 | }
254 |
--------------------------------------------------------------------------------
/StreamIt/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
54 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/StreamIt.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1A25D45D1EA27636002431F2 /* CocoaAsyncSocket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A7E8C4A1CBFFE3F00EFE574 /* CocoaAsyncSocket.framework */; };
11 | 1A7E8C391CBFFC7400EFE574 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A7E8C381CBFFC7400EFE574 /* AppDelegate.swift */; };
12 | 1A7E8C3E1CBFFC7400EFE574 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1A7E8C3C1CBFFC7400EFE574 /* Main.storyboard */; };
13 | 1A7E8C401CBFFC7400EFE574 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A7E8C3F1CBFFC7400EFE574 /* Assets.xcassets */; };
14 | 1A7E8C431CBFFC7400EFE574 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1A7E8C411CBFFC7400EFE574 /* LaunchScreen.storyboard */; };
15 | 1A7E8C541CBFFF9A00EFE574 /* CameraViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A7E8C531CBFFF9A00EFE574 /* CameraViewController.swift */; };
16 | 1A7E8C561CC0005800EFE574 /* StreamingSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A7E8C551CC0005800EFE574 /* StreamingSession.swift */; };
17 | 1A7E8C5B1CC0009500EFE574 /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A7E8C571CC0009500EFE574 /* Queue.swift */; };
18 | 93DE98311FDEB62A0048600F /* IPChecker.m in Sources */ = {isa = PBXBuildFile; fileRef = 93DE98301FDEB62A0048600F /* IPChecker.m */; };
19 | /* End PBXBuildFile section */
20 |
21 | /* Begin PBXFileReference section */
22 | 1A7E8C351CBFFC7400EFE574 /* StreamIt.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = StreamIt.app; sourceTree = BUILT_PRODUCTS_DIR; };
23 | 1A7E8C381CBFFC7400EFE574 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
24 | 1A7E8C3D1CBFFC7400EFE574 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
25 | 1A7E8C3F1CBFFC7400EFE574 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
26 | 1A7E8C421CBFFC7400EFE574 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
27 | 1A7E8C441CBFFC7400EFE574 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
28 | 1A7E8C4A1CBFFE3F00EFE574 /* CocoaAsyncSocket.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CocoaAsyncSocket.framework; path = Carthage/Build/iOS/CocoaAsyncSocket.framework; sourceTree = ""; };
29 | 1A7E8C4E1CBFFEE900EFE574 /* StreamIt-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "StreamIt-Bridging-Header.h"; sourceTree = ""; };
30 | 1A7E8C531CBFFF9A00EFE574 /* CameraViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CameraViewController.swift; sourceTree = ""; };
31 | 1A7E8C551CC0005800EFE574 /* StreamingSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StreamingSession.swift; sourceTree = ""; };
32 | 1A7E8C571CC0009500EFE574 /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Queue.swift; sourceTree = ""; };
33 | 93DE982F1FDEB62A0048600F /* IPChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IPChecker.h; sourceTree = ""; };
34 | 93DE98301FDEB62A0048600F /* IPChecker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IPChecker.m; sourceTree = ""; };
35 | /* End PBXFileReference section */
36 |
37 | /* Begin PBXFrameworksBuildPhase section */
38 | 1A7E8C321CBFFC7400EFE574 /* Frameworks */ = {
39 | isa = PBXFrameworksBuildPhase;
40 | buildActionMask = 2147483647;
41 | files = (
42 | 1A25D45D1EA27636002431F2 /* CocoaAsyncSocket.framework in Frameworks */,
43 | );
44 | runOnlyForDeploymentPostprocessing = 0;
45 | };
46 | /* End PBXFrameworksBuildPhase section */
47 |
48 | /* Begin PBXGroup section */
49 | 1A7E8C2C1CBFFC7400EFE574 = {
50 | isa = PBXGroup;
51 | children = (
52 | 1A7E8C4A1CBFFE3F00EFE574 /* CocoaAsyncSocket.framework */,
53 | 1A7E8C371CBFFC7400EFE574 /* StreamIt */,
54 | 1A7E8C361CBFFC7400EFE574 /* Products */,
55 | );
56 | sourceTree = "";
57 | };
58 | 1A7E8C361CBFFC7400EFE574 /* Products */ = {
59 | isa = PBXGroup;
60 | children = (
61 | 1A7E8C351CBFFC7400EFE574 /* StreamIt.app */,
62 | );
63 | name = Products;
64 | sourceTree = "";
65 | };
66 | 1A7E8C371CBFFC7400EFE574 /* StreamIt */ = {
67 | isa = PBXGroup;
68 | children = (
69 | 1A7E8C381CBFFC7400EFE574 /* AppDelegate.swift */,
70 | 1A7E8C531CBFFF9A00EFE574 /* CameraViewController.swift */,
71 | 1A7E8C551CC0005800EFE574 /* StreamingSession.swift */,
72 | 1A7E8C571CC0009500EFE574 /* Queue.swift */,
73 | 1A7E8C3C1CBFFC7400EFE574 /* Main.storyboard */,
74 | 1A7E8C3F1CBFFC7400EFE574 /* Assets.xcassets */,
75 | 1A7E8C411CBFFC7400EFE574 /* LaunchScreen.storyboard */,
76 | 1A7E8C441CBFFC7400EFE574 /* Info.plist */,
77 | 93DE982E1FDEB62A0048600F /* IPChecker */,
78 | 1A7E8C4E1CBFFEE900EFE574 /* StreamIt-Bridging-Header.h */,
79 | );
80 | path = StreamIt;
81 | sourceTree = "";
82 | };
83 | 93DE982E1FDEB62A0048600F /* IPChecker */ = {
84 | isa = PBXGroup;
85 | children = (
86 | 93DE982F1FDEB62A0048600F /* IPChecker.h */,
87 | 93DE98301FDEB62A0048600F /* IPChecker.m */,
88 | );
89 | path = IPChecker;
90 | sourceTree = "";
91 | };
92 | /* End PBXGroup section */
93 |
94 | /* Begin PBXNativeTarget section */
95 | 1A7E8C341CBFFC7400EFE574 /* StreamIt */ = {
96 | isa = PBXNativeTarget;
97 | buildConfigurationList = 1A7E8C471CBFFC7400EFE574 /* Build configuration list for PBXNativeTarget "StreamIt" */;
98 | buildPhases = (
99 | 1A7E8C311CBFFC7400EFE574 /* Sources */,
100 | 1A7E8C321CBFFC7400EFE574 /* Frameworks */,
101 | 1A7E8C331CBFFC7400EFE574 /* Resources */,
102 | 1A7E8C4C1CBFFE5400EFE574 /* ShellScript */,
103 | );
104 | buildRules = (
105 | );
106 | dependencies = (
107 | );
108 | name = StreamIt;
109 | productName = StreamIt;
110 | productReference = 1A7E8C351CBFFC7400EFE574 /* StreamIt.app */;
111 | productType = "com.apple.product-type.application";
112 | };
113 | /* End PBXNativeTarget section */
114 |
115 | /* Begin PBXProject section */
116 | 1A7E8C2D1CBFFC7400EFE574 /* Project object */ = {
117 | isa = PBXProject;
118 | attributes = {
119 | LastSwiftUpdateCheck = 0730;
120 | LastUpgradeCheck = 1130;
121 | ORGANIZATIONNAME = "Thibault Wittemberg";
122 | TargetAttributes = {
123 | 1A7E8C341CBFFC7400EFE574 = {
124 | CreatedOnToolsVersion = 7.3;
125 | DevelopmentTeam = 3V5265LQM9;
126 | LastSwiftMigration = 0920;
127 | };
128 | };
129 | };
130 | buildConfigurationList = 1A7E8C301CBFFC7400EFE574 /* Build configuration list for PBXProject "StreamIt" */;
131 | compatibilityVersion = "Xcode 3.2";
132 | developmentRegion = en;
133 | hasScannedForEncodings = 0;
134 | knownRegions = (
135 | en,
136 | Base,
137 | );
138 | mainGroup = 1A7E8C2C1CBFFC7400EFE574;
139 | productRefGroup = 1A7E8C361CBFFC7400EFE574 /* Products */;
140 | projectDirPath = "";
141 | projectRoot = "";
142 | targets = (
143 | 1A7E8C341CBFFC7400EFE574 /* StreamIt */,
144 | );
145 | };
146 | /* End PBXProject section */
147 |
148 | /* Begin PBXResourcesBuildPhase section */
149 | 1A7E8C331CBFFC7400EFE574 /* Resources */ = {
150 | isa = PBXResourcesBuildPhase;
151 | buildActionMask = 2147483647;
152 | files = (
153 | 1A7E8C431CBFFC7400EFE574 /* LaunchScreen.storyboard in Resources */,
154 | 1A7E8C401CBFFC7400EFE574 /* Assets.xcassets in Resources */,
155 | 1A7E8C3E1CBFFC7400EFE574 /* Main.storyboard in Resources */,
156 | );
157 | runOnlyForDeploymentPostprocessing = 0;
158 | };
159 | /* End PBXResourcesBuildPhase section */
160 |
161 | /* Begin PBXShellScriptBuildPhase section */
162 | 1A7E8C4C1CBFFE5400EFE574 /* ShellScript */ = {
163 | isa = PBXShellScriptBuildPhase;
164 | buildActionMask = 2147483647;
165 | files = (
166 | );
167 | inputPaths = (
168 | "$(SRCROOT)/Carthage/Build/iOS/CocoaAsyncSocket.framework",
169 | );
170 | outputPaths = (
171 | );
172 | runOnlyForDeploymentPostprocessing = 0;
173 | shellPath = /bin/sh;
174 | shellScript = "/usr/local/bin/carthage copy-frameworks";
175 | };
176 | /* End PBXShellScriptBuildPhase section */
177 |
178 | /* Begin PBXSourcesBuildPhase section */
179 | 1A7E8C311CBFFC7400EFE574 /* Sources */ = {
180 | isa = PBXSourcesBuildPhase;
181 | buildActionMask = 2147483647;
182 | files = (
183 | 1A7E8C5B1CC0009500EFE574 /* Queue.swift in Sources */,
184 | 93DE98311FDEB62A0048600F /* IPChecker.m in Sources */,
185 | 1A7E8C391CBFFC7400EFE574 /* AppDelegate.swift in Sources */,
186 | 1A7E8C541CBFFF9A00EFE574 /* CameraViewController.swift in Sources */,
187 | 1A7E8C561CC0005800EFE574 /* StreamingSession.swift in Sources */,
188 | );
189 | runOnlyForDeploymentPostprocessing = 0;
190 | };
191 | /* End PBXSourcesBuildPhase section */
192 |
193 | /* Begin PBXVariantGroup section */
194 | 1A7E8C3C1CBFFC7400EFE574 /* Main.storyboard */ = {
195 | isa = PBXVariantGroup;
196 | children = (
197 | 1A7E8C3D1CBFFC7400EFE574 /* Base */,
198 | );
199 | name = Main.storyboard;
200 | sourceTree = "";
201 | };
202 | 1A7E8C411CBFFC7400EFE574 /* LaunchScreen.storyboard */ = {
203 | isa = PBXVariantGroup;
204 | children = (
205 | 1A7E8C421CBFFC7400EFE574 /* Base */,
206 | );
207 | name = LaunchScreen.storyboard;
208 | sourceTree = "";
209 | };
210 | /* End PBXVariantGroup section */
211 |
212 | /* Begin XCBuildConfiguration section */
213 | 1A7E8C451CBFFC7400EFE574 /* Debug */ = {
214 | isa = XCBuildConfiguration;
215 | buildSettings = {
216 | ALWAYS_SEARCH_USER_PATHS = NO;
217 | CLANG_ANALYZER_NONNULL = YES;
218 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
219 | CLANG_CXX_LIBRARY = "libc++";
220 | CLANG_ENABLE_MODULES = YES;
221 | CLANG_ENABLE_OBJC_ARC = YES;
222 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
223 | CLANG_WARN_BOOL_CONVERSION = YES;
224 | CLANG_WARN_COMMA = YES;
225 | CLANG_WARN_CONSTANT_CONVERSION = YES;
226 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
227 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
228 | CLANG_WARN_EMPTY_BODY = YES;
229 | CLANG_WARN_ENUM_CONVERSION = YES;
230 | CLANG_WARN_INFINITE_RECURSION = YES;
231 | CLANG_WARN_INT_CONVERSION = YES;
232 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
233 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
234 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
235 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
236 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
237 | CLANG_WARN_STRICT_PROTOTYPES = YES;
238 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
239 | CLANG_WARN_UNREACHABLE_CODE = YES;
240 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
241 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
242 | COPY_PHASE_STRIP = NO;
243 | DEBUG_INFORMATION_FORMAT = dwarf;
244 | ENABLE_STRICT_OBJC_MSGSEND = YES;
245 | ENABLE_TESTABILITY = YES;
246 | GCC_C_LANGUAGE_STANDARD = gnu99;
247 | GCC_DYNAMIC_NO_PIC = NO;
248 | GCC_NO_COMMON_BLOCKS = YES;
249 | GCC_OPTIMIZATION_LEVEL = 0;
250 | GCC_PREPROCESSOR_DEFINITIONS = (
251 | "DEBUG=1",
252 | "$(inherited)",
253 | );
254 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
255 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
256 | GCC_WARN_UNDECLARED_SELECTOR = YES;
257 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
258 | GCC_WARN_UNUSED_FUNCTION = YES;
259 | GCC_WARN_UNUSED_VARIABLE = YES;
260 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
261 | MTL_ENABLE_DEBUG_INFO = YES;
262 | ONLY_ACTIVE_ARCH = YES;
263 | SDKROOT = iphoneos;
264 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
265 | TARGETED_DEVICE_FAMILY = "1,2";
266 | };
267 | name = Debug;
268 | };
269 | 1A7E8C461CBFFC7400EFE574 /* Release */ = {
270 | isa = XCBuildConfiguration;
271 | buildSettings = {
272 | ALWAYS_SEARCH_USER_PATHS = NO;
273 | CLANG_ANALYZER_NONNULL = YES;
274 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
275 | CLANG_CXX_LIBRARY = "libc++";
276 | CLANG_ENABLE_MODULES = YES;
277 | CLANG_ENABLE_OBJC_ARC = YES;
278 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
279 | CLANG_WARN_BOOL_CONVERSION = YES;
280 | CLANG_WARN_COMMA = YES;
281 | CLANG_WARN_CONSTANT_CONVERSION = YES;
282 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
283 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
284 | CLANG_WARN_EMPTY_BODY = YES;
285 | CLANG_WARN_ENUM_CONVERSION = YES;
286 | CLANG_WARN_INFINITE_RECURSION = YES;
287 | CLANG_WARN_INT_CONVERSION = YES;
288 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
289 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
290 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
291 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
292 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
293 | CLANG_WARN_STRICT_PROTOTYPES = YES;
294 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
295 | CLANG_WARN_UNREACHABLE_CODE = YES;
296 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
297 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
298 | COPY_PHASE_STRIP = NO;
299 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
300 | ENABLE_NS_ASSERTIONS = NO;
301 | ENABLE_STRICT_OBJC_MSGSEND = YES;
302 | GCC_C_LANGUAGE_STANDARD = gnu99;
303 | GCC_NO_COMMON_BLOCKS = YES;
304 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
305 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
306 | GCC_WARN_UNDECLARED_SELECTOR = YES;
307 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
308 | GCC_WARN_UNUSED_FUNCTION = YES;
309 | GCC_WARN_UNUSED_VARIABLE = YES;
310 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
311 | MTL_ENABLE_DEBUG_INFO = NO;
312 | SDKROOT = iphoneos;
313 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
314 | TARGETED_DEVICE_FAMILY = "1,2";
315 | VALIDATE_PRODUCT = YES;
316 | };
317 | name = Release;
318 | };
319 | 1A7E8C481CBFFC7400EFE574 /* Debug */ = {
320 | isa = XCBuildConfiguration;
321 | buildSettings = {
322 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
323 | CLANG_ENABLE_MODULES = YES;
324 | DEVELOPMENT_TEAM = 3V5265LQM9;
325 | FRAMEWORK_SEARCH_PATHS = (
326 | "$(inherited)",
327 | "$(PROJECT_DIR)/Carthage/Build/iOS",
328 | );
329 | INFOPLIST_FILE = StreamIt/Info.plist;
330 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
331 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
332 | PRODUCT_BUNDLE_IDENTIFIER = com.warpcore.StreamIt;
333 | PRODUCT_NAME = "$(TARGET_NAME)";
334 | SWIFT_OBJC_BRIDGING_HEADER = "StreamIt/StreamIt-Bridging-Header.h";
335 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
336 | SWIFT_VERSION = 5.0;
337 | TARGETED_DEVICE_FAMILY = "1,2";
338 | };
339 | name = Debug;
340 | };
341 | 1A7E8C491CBFFC7400EFE574 /* Release */ = {
342 | isa = XCBuildConfiguration;
343 | buildSettings = {
344 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
345 | CLANG_ENABLE_MODULES = YES;
346 | DEVELOPMENT_TEAM = 3V5265LQM9;
347 | FRAMEWORK_SEARCH_PATHS = (
348 | "$(inherited)",
349 | "$(PROJECT_DIR)/Carthage/Build/iOS",
350 | );
351 | INFOPLIST_FILE = StreamIt/Info.plist;
352 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
353 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
354 | PRODUCT_BUNDLE_IDENTIFIER = com.warpcore.StreamIt;
355 | PRODUCT_NAME = "$(TARGET_NAME)";
356 | SWIFT_OBJC_BRIDGING_HEADER = "StreamIt/StreamIt-Bridging-Header.h";
357 | SWIFT_VERSION = 5.0;
358 | TARGETED_DEVICE_FAMILY = "1,2";
359 | };
360 | name = Release;
361 | };
362 | /* End XCBuildConfiguration section */
363 |
364 | /* Begin XCConfigurationList section */
365 | 1A7E8C301CBFFC7400EFE574 /* Build configuration list for PBXProject "StreamIt" */ = {
366 | isa = XCConfigurationList;
367 | buildConfigurations = (
368 | 1A7E8C451CBFFC7400EFE574 /* Debug */,
369 | 1A7E8C461CBFFC7400EFE574 /* Release */,
370 | );
371 | defaultConfigurationIsVisible = 0;
372 | defaultConfigurationName = Release;
373 | };
374 | 1A7E8C471CBFFC7400EFE574 /* Build configuration list for PBXNativeTarget "StreamIt" */ = {
375 | isa = XCConfigurationList;
376 | buildConfigurations = (
377 | 1A7E8C481CBFFC7400EFE574 /* Debug */,
378 | 1A7E8C491CBFFC7400EFE574 /* Release */,
379 | );
380 | defaultConfigurationIsVisible = 0;
381 | defaultConfigurationName = Release;
382 | };
383 | /* End XCConfigurationList section */
384 | };
385 | rootObject = 1A7E8C2D1CBFFC7400EFE574 /* Project object */;
386 | }
387 |
--------------------------------------------------------------------------------