├── Brainwaves
├── Brainwaves.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ │ └── Nikhil.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcuserdata
│ │ └── Nikhil.xcuserdatad
│ │ ├── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ ├── Brainwaves.xcscheme
│ │ └── xcschememanagement.plist
├── Brainwaves.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ │ └── Nikhil.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── Brainwaves
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── HomeViewController.swift
│ └── Info.plist
├── Podfile
├── Podfile.lock
└── Pods
│ ├── Alamofire
│ ├── LICENSE
│ ├── README.md
│ └── Source
│ │ ├── Alamofire.swift
│ │ ├── Download.swift
│ │ ├── Error.swift
│ │ ├── Manager.swift
│ │ ├── MultipartFormData.swift
│ │ ├── NetworkReachabilityManager.swift
│ │ ├── Notifications.swift
│ │ ├── ParameterEncoding.swift
│ │ ├── Request.swift
│ │ ├── Response.swift
│ │ ├── ResponseSerialization.swift
│ │ ├── Result.swift
│ │ ├── ServerTrustPolicy.swift
│ │ ├── Stream.swift
│ │ ├── Timeline.swift
│ │ ├── Upload.swift
│ │ └── Validation.swift
│ ├── Manifest.lock
│ ├── Pods.xcodeproj
│ ├── project.pbxproj
│ └── xcuserdata
│ │ └── Nikhil.xcuserdatad
│ │ └── xcschemes
│ │ ├── Alamofire.xcscheme
│ │ ├── Pods-Brainwaves.xcscheme
│ │ └── xcschememanagement.plist
│ └── Target Support Files
│ ├── Alamofire
│ ├── Alamofire-Private.xcconfig
│ ├── Alamofire-dummy.m
│ ├── Alamofire-prefix.pch
│ ├── Alamofire-umbrella.h
│ ├── Alamofire.modulemap
│ ├── Alamofire.xcconfig
│ └── Info.plist
│ └── Pods-Brainwaves
│ ├── Info.plist
│ ├── Pods-Brainwaves-acknowledgements.markdown
│ ├── Pods-Brainwaves-acknowledgements.plist
│ ├── Pods-Brainwaves-dummy.m
│ ├── Pods-Brainwaves-frameworks.sh
│ ├── Pods-Brainwaves-resources.sh
│ ├── Pods-Brainwaves-umbrella.h
│ ├── Pods-Brainwaves.debug.xcconfig
│ ├── Pods-Brainwaves.modulemap
│ └── Pods-Brainwaves.release.xcconfig
├── README.md
├── emokit
├── .gitignore
├── CMakeLists.txt
├── FAQ.md
├── INSTALL
├── LICENSE
├── README.md
├── cmake_modules
│ ├── FindHIDAPI.cmake
│ ├── FindMcrypt.cmake
│ └── Findlibusb-1.0.cmake
├── doc
│ ├── Announcement.md
│ ├── emotiv_protocol.asciidoc
│ └── usbinfo.txt
├── examples
│ ├── contact
│ │ ├── CMakeLists.txt
│ │ └── contact.c
│ ├── emokit_osc
│ │ ├── CMakeLists.txt
│ │ ├── Findoscpack.cmake
│ │ ├── emokit_osc.cpp
│ │ └── pd
│ │ │ └── emokit-osc.pd
│ └── emokitd
│ │ ├── CMakeLists.txt
│ │ ├── emokitd.c
│ │ └── emokitd.h
├── include
│ └── emokit
│ │ └── emokit.h
├── linux
│ └── epoc.rules
├── python
│ ├── MANIFEST.in
│ ├── Makefile
│ ├── dist
│ │ └── emokit-0.0.1-py2.7.egg
│ ├── emokit.egg-info
│ │ ├── PKG-INFO
│ │ ├── SOURCES.txt
│ │ ├── dependency_links.txt
│ │ ├── not-zip-safe
│ │ ├── requires.txt
│ │ └── top_level.txt
│ ├── emokit
│ │ ├── Makefile-manual
│ │ ├── Makefile.am
│ │ ├── __init__.py
│ │ ├── cv.py
│ │ ├── cv2.so
│ │ ├── data.txt
│ │ ├── emotiv.py
│ │ ├── hid.c
│ │ ├── hid.o
│ │ ├── hidapi.h
│ │ └── src
│ │ │ └── pip-delete-this-directory.txt
│ ├── example.py
│ ├── mouse_control.py
│ ├── render.py
│ ├── requirements.txt
│ ├── setup.py
│ └── tests
│ │ └── test_emokit.py
└── src
│ ├── CMakeLists.txt
│ └── emokit.c
└── scripts
├── brainwaves-script
├── data.txt
└── ngrok
/Brainwaves/Brainwaves.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Brainwaves/Brainwaves.xcodeproj/project.xcworkspace/xcuserdata/Nikhil.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nikhiljay/brainwaves/42d96dccedf09504589fc9e14e3b470de7f5c0b2/Brainwaves/Brainwaves.xcodeproj/project.xcworkspace/xcuserdata/Nikhil.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Brainwaves/Brainwaves.xcodeproj/xcuserdata/Nikhil.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/Brainwaves/Brainwaves.xcodeproj/xcuserdata/Nikhil.xcuserdatad/xcschemes/Brainwaves.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/Brainwaves/Brainwaves.xcodeproj/xcuserdata/Nikhil.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Brainwaves.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 3152ED441CAEF0D3001BD663
16 |
17 | primary
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Brainwaves/Brainwaves.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Brainwaves/Brainwaves.xcworkspace/xcuserdata/Nikhil.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nikhiljay/brainwaves/42d96dccedf09504589fc9e14e3b470de7f5c0b2/Brainwaves/Brainwaves.xcworkspace/xcuserdata/Nikhil.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Brainwaves/Brainwaves/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Brainwaves
4 | //
5 | // Created by Nikhil D'Souza on 4/1/16.
6 | // Copyright © 2016 Nikhil. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(application: UIApplication) {
33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/Brainwaves/Brainwaves/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/Brainwaves/Brainwaves/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
30 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/Brainwaves/Brainwaves/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 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/Brainwaves/Brainwaves/HomeViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HomeViewController.swift
3 | // Brainwaves
4 | //
5 | // Created by Nikhil D'Souza on 4/1/16.
6 | // Copyright © 2016 Nikhil. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Alamofire
11 | import Foundation
12 |
13 | class HomeViewController: UIViewController, UITextFieldDelegate {
14 |
15 | @IBOutlet weak var outputText: UITextView!
16 | @IBOutlet weak var serverTextField: UITextField!
17 | @IBOutlet weak var loadIndicator: UIActivityIndicatorView!
18 |
19 | var serverURL: String!
20 |
21 | override func viewDidLoad() {
22 | super.viewDidLoad()
23 |
24 | loadIndicator.stopAnimating()
25 | serverTextField.delegate = self
26 | repeatRequest()
27 |
28 | }
29 |
30 | func repeatRequest() {
31 | if serverURL != nil {
32 | _ = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(HomeViewController.getRequest), userInfo: nil, repeats: true)
33 | } else {
34 | self.outputText.text = "Enter a server URL!"
35 | }
36 | }
37 |
38 | func getRequest() {
39 |
40 | loadIndicator.stopAnimating()
41 |
42 | Alamofire.request(.GET, serverURL!)
43 | .responseJSON { response in
44 | if let JSON = response.result.value {
45 |
46 | self.outputText.text = ""
47 |
48 | for node in JSON as! [String: AnyObject] {
49 | let nodeData = node.1["value"]!
50 | self.outputText.text! += node.0 + ": " + String(nodeData!) + "\n"
51 | }
52 |
53 | }
54 |
55 | switch response.result {
56 | case .Success:
57 | print("Validation Successful")
58 | case .Failure(let error):
59 | self.outputText.text = String(error)
60 | print(error)
61 | }
62 | }
63 | }
64 |
65 | func textFieldShouldReturn(textField: UITextField) -> Bool {
66 | textField.resignFirstResponder()
67 | serverURL = serverTextField.text
68 | repeatRequest()
69 | loadIndicator.startAnimating()
70 | return true
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/Brainwaves/Brainwaves/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 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Brainwaves/Podfile:
--------------------------------------------------------------------------------
1 | platform :ios, '8.0'
2 | use_frameworks!
3 |
4 | target 'Brainwaves' do
5 | pod 'Alamofire', '~> 3.0'
6 | end
7 |
8 |
--------------------------------------------------------------------------------
/Brainwaves/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Alamofire (3.3.0)
3 |
4 | DEPENDENCIES:
5 | - Alamofire (~> 3.0)
6 |
7 | SPEC CHECKSUMS:
8 | Alamofire: 9054db4a1b1ca9e363223183e01cea380159a27c
9 |
10 | COCOAPODS: 0.38.2
11 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Alamofire/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Alamofire/Source/Alamofire.swift:
--------------------------------------------------------------------------------
1 | // Alamofire.swift
2 | //
3 | // Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
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
13 | // all 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
21 | // THE SOFTWARE.
22 |
23 | import Foundation
24 |
25 | // MARK: - URLStringConvertible
26 |
27 | /**
28 | Types adopting the `URLStringConvertible` protocol can be used to construct URL strings, which are then used to
29 | construct URL requests.
30 | */
31 | public protocol URLStringConvertible {
32 | /**
33 | A URL that conforms to RFC 2396.
34 |
35 | Methods accepting a `URLStringConvertible` type parameter parse it according to RFCs 1738 and 1808.
36 |
37 | See https://tools.ietf.org/html/rfc2396
38 | See https://tools.ietf.org/html/rfc1738
39 | See https://tools.ietf.org/html/rfc1808
40 | */
41 | var URLString: String { get }
42 | }
43 |
44 | extension String: URLStringConvertible {
45 | public var URLString: String {
46 | return self
47 | }
48 | }
49 |
50 | extension NSURL: URLStringConvertible {
51 | public var URLString: String {
52 | return absoluteString
53 | }
54 | }
55 |
56 | extension NSURLComponents: URLStringConvertible {
57 | public var URLString: String {
58 | return URL!.URLString
59 | }
60 | }
61 |
62 | extension NSURLRequest: URLStringConvertible {
63 | public var URLString: String {
64 | return URL!.URLString
65 | }
66 | }
67 |
68 | // MARK: - URLRequestConvertible
69 |
70 | /**
71 | Types adopting the `URLRequestConvertible` protocol can be used to construct URL requests.
72 | */
73 | public protocol URLRequestConvertible {
74 | /// The URL request.
75 | var URLRequest: NSMutableURLRequest { get }
76 | }
77 |
78 | extension NSURLRequest: URLRequestConvertible {
79 | public var URLRequest: NSMutableURLRequest {
80 | return self.mutableCopy() as! NSMutableURLRequest
81 | }
82 | }
83 |
84 | // MARK: - Convenience
85 |
86 | func URLRequest(
87 | method: Method,
88 | _ URLString: URLStringConvertible,
89 | headers: [String: String]? = nil)
90 | -> NSMutableURLRequest
91 | {
92 | let mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: URLString.URLString)!)
93 | mutableURLRequest.HTTPMethod = method.rawValue
94 |
95 | if let headers = headers {
96 | for (headerField, headerValue) in headers {
97 | mutableURLRequest.setValue(headerValue, forHTTPHeaderField: headerField)
98 | }
99 | }
100 |
101 | return mutableURLRequest
102 | }
103 |
104 | // MARK: - Request Methods
105 |
106 | /**
107 | Creates a request using the shared manager instance for the specified method, URL string, parameters, and
108 | parameter encoding.
109 |
110 | - parameter method: The HTTP method.
111 | - parameter URLString: The URL string.
112 | - parameter parameters: The parameters. `nil` by default.
113 | - parameter encoding: The parameter encoding. `.URL` by default.
114 | - parameter headers: The HTTP headers. `nil` by default.
115 |
116 | - returns: The created request.
117 | */
118 | public func request(
119 | method: Method,
120 | _ URLString: URLStringConvertible,
121 | parameters: [String: AnyObject]? = nil,
122 | encoding: ParameterEncoding = .URL,
123 | headers: [String: String]? = nil)
124 | -> Request
125 | {
126 | return Manager.sharedInstance.request(
127 | method,
128 | URLString,
129 | parameters: parameters,
130 | encoding: encoding,
131 | headers: headers
132 | )
133 | }
134 |
135 | /**
136 | Creates a request using the shared manager instance for the specified URL request.
137 |
138 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
139 |
140 | - parameter URLRequest: The URL request
141 |
142 | - returns: The created request.
143 | */
144 | public func request(URLRequest: URLRequestConvertible) -> Request {
145 | return Manager.sharedInstance.request(URLRequest.URLRequest)
146 | }
147 |
148 | // MARK: - Upload Methods
149 |
150 | // MARK: File
151 |
152 | /**
153 | Creates an upload request using the shared manager instance for the specified method, URL string, and file.
154 |
155 | - parameter method: The HTTP method.
156 | - parameter URLString: The URL string.
157 | - parameter headers: The HTTP headers. `nil` by default.
158 | - parameter file: The file to upload.
159 |
160 | - returns: The created upload request.
161 | */
162 | public func upload(
163 | method: Method,
164 | _ URLString: URLStringConvertible,
165 | headers: [String: String]? = nil,
166 | file: NSURL)
167 | -> Request
168 | {
169 | return Manager.sharedInstance.upload(method, URLString, headers: headers, file: file)
170 | }
171 |
172 | /**
173 | Creates an upload request using the shared manager instance for the specified URL request and file.
174 |
175 | - parameter URLRequest: The URL request.
176 | - parameter file: The file to upload.
177 |
178 | - returns: The created upload request.
179 | */
180 | public func upload(URLRequest: URLRequestConvertible, file: NSURL) -> Request {
181 | return Manager.sharedInstance.upload(URLRequest, file: file)
182 | }
183 |
184 | // MARK: Data
185 |
186 | /**
187 | Creates an upload request using the shared manager instance for the specified method, URL string, and data.
188 |
189 | - parameter method: The HTTP method.
190 | - parameter URLString: The URL string.
191 | - parameter headers: The HTTP headers. `nil` by default.
192 | - parameter data: The data to upload.
193 |
194 | - returns: The created upload request.
195 | */
196 | public func upload(
197 | method: Method,
198 | _ URLString: URLStringConvertible,
199 | headers: [String: String]? = nil,
200 | data: NSData)
201 | -> Request
202 | {
203 | return Manager.sharedInstance.upload(method, URLString, headers: headers, data: data)
204 | }
205 |
206 | /**
207 | Creates an upload request using the shared manager instance for the specified URL request and data.
208 |
209 | - parameter URLRequest: The URL request.
210 | - parameter data: The data to upload.
211 |
212 | - returns: The created upload request.
213 | */
214 | public func upload(URLRequest: URLRequestConvertible, data: NSData) -> Request {
215 | return Manager.sharedInstance.upload(URLRequest, data: data)
216 | }
217 |
218 | // MARK: Stream
219 |
220 | /**
221 | Creates an upload request using the shared manager instance for the specified method, URL string, and stream.
222 |
223 | - parameter method: The HTTP method.
224 | - parameter URLString: The URL string.
225 | - parameter headers: The HTTP headers. `nil` by default.
226 | - parameter stream: The stream to upload.
227 |
228 | - returns: The created upload request.
229 | */
230 | public func upload(
231 | method: Method,
232 | _ URLString: URLStringConvertible,
233 | headers: [String: String]? = nil,
234 | stream: NSInputStream)
235 | -> Request
236 | {
237 | return Manager.sharedInstance.upload(method, URLString, headers: headers, stream: stream)
238 | }
239 |
240 | /**
241 | Creates an upload request using the shared manager instance for the specified URL request and stream.
242 |
243 | - parameter URLRequest: The URL request.
244 | - parameter stream: The stream to upload.
245 |
246 | - returns: The created upload request.
247 | */
248 | public func upload(URLRequest: URLRequestConvertible, stream: NSInputStream) -> Request {
249 | return Manager.sharedInstance.upload(URLRequest, stream: stream)
250 | }
251 |
252 | // MARK: MultipartFormData
253 |
254 | /**
255 | Creates an upload request using the shared manager instance for the specified method and URL string.
256 |
257 | - parameter method: The HTTP method.
258 | - parameter URLString: The URL string.
259 | - parameter headers: The HTTP headers. `nil` by default.
260 | - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`.
261 | - parameter encodingMemoryThreshold: The encoding memory threshold in bytes.
262 | `MultipartFormDataEncodingMemoryThreshold` by default.
263 | - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete.
264 | */
265 | public func upload(
266 | method: Method,
267 | _ URLString: URLStringConvertible,
268 | headers: [String: String]? = nil,
269 | multipartFormData: MultipartFormData -> Void,
270 | encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold,
271 | encodingCompletion: (Manager.MultipartFormDataEncodingResult -> Void)?)
272 | {
273 | return Manager.sharedInstance.upload(
274 | method,
275 | URLString,
276 | headers: headers,
277 | multipartFormData: multipartFormData,
278 | encodingMemoryThreshold: encodingMemoryThreshold,
279 | encodingCompletion: encodingCompletion
280 | )
281 | }
282 |
283 | /**
284 | Creates an upload request using the shared manager instance for the specified method and URL string.
285 |
286 | - parameter URLRequest: The URL request.
287 | - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`.
288 | - parameter encodingMemoryThreshold: The encoding memory threshold in bytes.
289 | `MultipartFormDataEncodingMemoryThreshold` by default.
290 | - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete.
291 | */
292 | public func upload(
293 | URLRequest: URLRequestConvertible,
294 | multipartFormData: MultipartFormData -> Void,
295 | encodingMemoryThreshold: UInt64 = Manager.MultipartFormDataEncodingMemoryThreshold,
296 | encodingCompletion: (Manager.MultipartFormDataEncodingResult -> Void)?)
297 | {
298 | return Manager.sharedInstance.upload(
299 | URLRequest,
300 | multipartFormData: multipartFormData,
301 | encodingMemoryThreshold: encodingMemoryThreshold,
302 | encodingCompletion: encodingCompletion
303 | )
304 | }
305 |
306 | // MARK: - Download Methods
307 |
308 | // MARK: URL Request
309 |
310 | /**
311 | Creates a download request using the shared manager instance for the specified method and URL string.
312 |
313 | - parameter method: The HTTP method.
314 | - parameter URLString: The URL string.
315 | - parameter parameters: The parameters. `nil` by default.
316 | - parameter encoding: The parameter encoding. `.URL` by default.
317 | - parameter headers: The HTTP headers. `nil` by default.
318 | - parameter destination: The closure used to determine the destination of the downloaded file.
319 |
320 | - returns: The created download request.
321 | */
322 | public func download(
323 | method: Method,
324 | _ URLString: URLStringConvertible,
325 | parameters: [String: AnyObject]? = nil,
326 | encoding: ParameterEncoding = .URL,
327 | headers: [String: String]? = nil,
328 | destination: Request.DownloadFileDestination)
329 | -> Request
330 | {
331 | return Manager.sharedInstance.download(
332 | method,
333 | URLString,
334 | parameters: parameters,
335 | encoding: encoding,
336 | headers: headers,
337 | destination: destination
338 | )
339 | }
340 |
341 | /**
342 | Creates a download request using the shared manager instance for the specified URL request.
343 |
344 | - parameter URLRequest: The URL request.
345 | - parameter destination: The closure used to determine the destination of the downloaded file.
346 |
347 | - returns: The created download request.
348 | */
349 | public func download(URLRequest: URLRequestConvertible, destination: Request.DownloadFileDestination) -> Request {
350 | return Manager.sharedInstance.download(URLRequest, destination: destination)
351 | }
352 |
353 | // MARK: Resume Data
354 |
355 | /**
356 | Creates a request using the shared manager instance for downloading from the resume data produced from a
357 | previous request cancellation.
358 |
359 | - parameter resumeData: The resume data. This is an opaque data blob produced by `NSURLSessionDownloadTask`
360 | when a task is cancelled. See `NSURLSession -downloadTaskWithResumeData:` for additional
361 | information.
362 | - parameter destination: The closure used to determine the destination of the downloaded file.
363 |
364 | - returns: The created download request.
365 | */
366 | public func download(resumeData data: NSData, destination: Request.DownloadFileDestination) -> Request {
367 | return Manager.sharedInstance.download(data, destination: destination)
368 | }
369 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Alamofire/Source/Download.swift:
--------------------------------------------------------------------------------
1 | // Download.swift
2 | //
3 | // Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
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
13 | // all 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
21 | // THE SOFTWARE.
22 |
23 | import Foundation
24 |
25 | extension Manager {
26 | private enum Downloadable {
27 | case Request(NSURLRequest)
28 | case ResumeData(NSData)
29 | }
30 |
31 | private func download(downloadable: Downloadable, destination: Request.DownloadFileDestination) -> Request {
32 | var downloadTask: NSURLSessionDownloadTask!
33 |
34 | switch downloadable {
35 | case .Request(let request):
36 | dispatch_sync(queue) {
37 | downloadTask = self.session.downloadTaskWithRequest(request)
38 | }
39 | case .ResumeData(let resumeData):
40 | dispatch_sync(queue) {
41 | downloadTask = self.session.downloadTaskWithResumeData(resumeData)
42 | }
43 | }
44 |
45 | let request = Request(session: session, task: downloadTask)
46 |
47 | if let downloadDelegate = request.delegate as? Request.DownloadTaskDelegate {
48 | downloadDelegate.downloadTaskDidFinishDownloadingToURL = { session, downloadTask, URL in
49 | return destination(URL, downloadTask.response as! NSHTTPURLResponse)
50 | }
51 | }
52 |
53 | delegate[request.delegate.task] = request.delegate
54 |
55 | if startRequestsImmediately {
56 | request.resume()
57 | }
58 |
59 | return request
60 | }
61 |
62 | // MARK: Request
63 |
64 | /**
65 | Creates a download request for the specified method, URL string, parameters, parameter encoding, headers
66 | and destination.
67 |
68 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
69 |
70 | - parameter method: The HTTP method.
71 | - parameter URLString: The URL string.
72 | - parameter parameters: The parameters. `nil` by default.
73 | - parameter encoding: The parameter encoding. `.URL` by default.
74 | - parameter headers: The HTTP headers. `nil` by default.
75 | - parameter destination: The closure used to determine the destination of the downloaded file.
76 |
77 | - returns: The created download request.
78 | */
79 | public func download(
80 | method: Method,
81 | _ URLString: URLStringConvertible,
82 | parameters: [String: AnyObject]? = nil,
83 | encoding: ParameterEncoding = .URL,
84 | headers: [String: String]? = nil,
85 | destination: Request.DownloadFileDestination)
86 | -> Request
87 | {
88 | let mutableURLRequest = URLRequest(method, URLString, headers: headers)
89 | let encodedURLRequest = encoding.encode(mutableURLRequest, parameters: parameters).0
90 |
91 | return download(encodedURLRequest, destination: destination)
92 | }
93 |
94 | /**
95 | Creates a request for downloading from the specified URL request.
96 |
97 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
98 |
99 | - parameter URLRequest: The URL request
100 | - parameter destination: The closure used to determine the destination of the downloaded file.
101 |
102 | - returns: The created download request.
103 | */
104 | public func download(URLRequest: URLRequestConvertible, destination: Request.DownloadFileDestination) -> Request {
105 | return download(.Request(URLRequest.URLRequest), destination: destination)
106 | }
107 |
108 | // MARK: Resume Data
109 |
110 | /**
111 | Creates a request for downloading from the resume data produced from a previous request cancellation.
112 |
113 | If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
114 |
115 | - parameter resumeData: The resume data. This is an opaque data blob produced by `NSURLSessionDownloadTask`
116 | when a task is cancelled. See `NSURLSession -downloadTaskWithResumeData:` for
117 | additional information.
118 | - parameter destination: The closure used to determine the destination of the downloaded file.
119 |
120 | - returns: The created download request.
121 | */
122 | public func download(resumeData: NSData, destination: Request.DownloadFileDestination) -> Request {
123 | return download(.ResumeData(resumeData), destination: destination)
124 | }
125 | }
126 |
127 | // MARK: -
128 |
129 | extension Request {
130 | /**
131 | A closure executed once a request has successfully completed in order to determine where to move the temporary
132 | file written to during the download process. The closure takes two arguments: the temporary file URL and the URL
133 | response, and returns a single argument: the file URL where the temporary file should be moved.
134 | */
135 | public typealias DownloadFileDestination = (NSURL, NSHTTPURLResponse) -> NSURL
136 |
137 | /**
138 | Creates a download file destination closure which uses the default file manager to move the temporary file to a
139 | file URL in the first available directory with the specified search path directory and search path domain mask.
140 |
141 | - parameter directory: The search path directory. `.DocumentDirectory` by default.
142 | - parameter domain: The search path domain mask. `.UserDomainMask` by default.
143 |
144 | - returns: A download file destination closure.
145 | */
146 | public class func suggestedDownloadDestination(
147 | directory directory: NSSearchPathDirectory = .DocumentDirectory,
148 | domain: NSSearchPathDomainMask = .UserDomainMask)
149 | -> DownloadFileDestination
150 | {
151 | return { temporaryURL, response -> NSURL in
152 | let directoryURLs = NSFileManager.defaultManager().URLsForDirectory(directory, inDomains: domain)
153 |
154 | if !directoryURLs.isEmpty {
155 | return directoryURLs[0].URLByAppendingPathComponent(response.suggestedFilename!)
156 | }
157 |
158 | return temporaryURL
159 | }
160 | }
161 |
162 | /// The resume data of the underlying download task if available after a failure.
163 | public var resumeData: NSData? {
164 | var data: NSData?
165 |
166 | if let delegate = delegate as? DownloadTaskDelegate {
167 | data = delegate.resumeData
168 | }
169 |
170 | return data
171 | }
172 |
173 | // MARK: - DownloadTaskDelegate
174 |
175 | class DownloadTaskDelegate: TaskDelegate, NSURLSessionDownloadDelegate {
176 | var downloadTask: NSURLSessionDownloadTask? { return task as? NSURLSessionDownloadTask }
177 | var downloadProgress: ((Int64, Int64, Int64) -> Void)?
178 |
179 | var resumeData: NSData?
180 | override var data: NSData? { return resumeData }
181 |
182 | // MARK: - NSURLSessionDownloadDelegate
183 |
184 | // MARK: Override Closures
185 |
186 | var downloadTaskDidFinishDownloadingToURL: ((NSURLSession, NSURLSessionDownloadTask, NSURL) -> NSURL)?
187 | var downloadTaskDidWriteData: ((NSURLSession, NSURLSessionDownloadTask, Int64, Int64, Int64) -> Void)?
188 | var downloadTaskDidResumeAtOffset: ((NSURLSession, NSURLSessionDownloadTask, Int64, Int64) -> Void)?
189 |
190 | // MARK: Delegate Methods
191 |
192 | func URLSession(
193 | session: NSURLSession,
194 | downloadTask: NSURLSessionDownloadTask,
195 | didFinishDownloadingToURL location: NSURL)
196 | {
197 | if let downloadTaskDidFinishDownloadingToURL = downloadTaskDidFinishDownloadingToURL {
198 | do {
199 | let destination = downloadTaskDidFinishDownloadingToURL(session, downloadTask, location)
200 | try NSFileManager.defaultManager().moveItemAtURL(location, toURL: destination)
201 | } catch {
202 | self.error = error as NSError
203 | }
204 | }
205 | }
206 |
207 | func URLSession(
208 | session: NSURLSession,
209 | downloadTask: NSURLSessionDownloadTask,
210 | didWriteData bytesWritten: Int64,
211 | totalBytesWritten: Int64,
212 | totalBytesExpectedToWrite: Int64)
213 | {
214 | if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() }
215 |
216 | if let downloadTaskDidWriteData = downloadTaskDidWriteData {
217 | downloadTaskDidWriteData(
218 | session,
219 | downloadTask,
220 | bytesWritten,
221 | totalBytesWritten,
222 | totalBytesExpectedToWrite
223 | )
224 | } else {
225 | progress.totalUnitCount = totalBytesExpectedToWrite
226 | progress.completedUnitCount = totalBytesWritten
227 |
228 | downloadProgress?(bytesWritten, totalBytesWritten, totalBytesExpectedToWrite)
229 | }
230 | }
231 |
232 | func URLSession(
233 | session: NSURLSession,
234 | downloadTask: NSURLSessionDownloadTask,
235 | didResumeAtOffset fileOffset: Int64,
236 | expectedTotalBytes: Int64)
237 | {
238 | if let downloadTaskDidResumeAtOffset = downloadTaskDidResumeAtOffset {
239 | downloadTaskDidResumeAtOffset(session, downloadTask, fileOffset, expectedTotalBytes)
240 | } else {
241 | progress.totalUnitCount = expectedTotalBytes
242 | progress.completedUnitCount = fileOffset
243 | }
244 | }
245 | }
246 | }
247 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Alamofire/Source/Error.swift:
--------------------------------------------------------------------------------
1 | // Error.swift
2 | //
3 | // Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
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
13 | // all 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
21 | // THE SOFTWARE.
22 |
23 | import Foundation
24 |
25 | /// The `Error` struct provides a convenience for creating custom Alamofire NSErrors.
26 | public struct Error {
27 | /// The domain used for creating all Alamofire errors.
28 | public static let Domain = "com.alamofire.error"
29 |
30 | /// The custom error codes generated by Alamofire.
31 | public enum Code: Int {
32 | case InputStreamReadFailed = -6000
33 | case OutputStreamWriteFailed = -6001
34 | case ContentTypeValidationFailed = -6002
35 | case StatusCodeValidationFailed = -6003
36 | case DataSerializationFailed = -6004
37 | case StringSerializationFailed = -6005
38 | case JSONSerializationFailed = -6006
39 | case PropertyListSerializationFailed = -6007
40 | }
41 |
42 | /**
43 | Creates an `NSError` with the given error code and failure reason.
44 |
45 | - parameter code: The error code.
46 | - parameter failureReason: The failure reason.
47 |
48 | - returns: An `NSError` with the given error code and failure reason.
49 | */
50 | public static func errorWithCode(code: Code, failureReason: String) -> NSError {
51 | return errorWithCode(code.rawValue, failureReason: failureReason)
52 | }
53 |
54 | /**
55 | Creates an `NSError` with the given error code and failure reason.
56 |
57 | - parameter code: The error code.
58 | - parameter failureReason: The failure reason.
59 |
60 | - returns: An `NSError` with the given error code and failure reason.
61 | */
62 | public static func errorWithCode(code: Int, failureReason: String) -> NSError {
63 | let userInfo = [NSLocalizedFailureReasonErrorKey: failureReason]
64 | return NSError(domain: Domain, code: code, userInfo: userInfo)
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Alamofire/Source/NetworkReachabilityManager.swift:
--------------------------------------------------------------------------------
1 | // NetworkReachabilityManager.swift
2 | //
3 | // Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
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
13 | // all 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
21 | // THE SOFTWARE.
22 |
23 | #if !os(watchOS)
24 |
25 | import Foundation
26 | import SystemConfiguration
27 |
28 | /**
29 | The `NetworkReachabilityManager` class listens for reachability changes of hosts and addresses for both WWAN and
30 | WiFi network interfaces.
31 |
32 | Reachability can be used to determine background information about why a network operation failed, or to retry
33 | network requests when a connection is established. It should not be used to prevent a user from initiating a network
34 | request, as it's possible that an initial request may be required to establish reachability.
35 | */
36 | public class NetworkReachabilityManager {
37 | /**
38 | Defines the various states of network reachability.
39 |
40 | - Unknown: It is unknown whether the network is reachable.
41 | - NotReachable: The network is not reachable.
42 | - ReachableOnWWAN: The network is reachable over the WWAN connection.
43 | - ReachableOnWiFi: The network is reachable over the WiFi connection.
44 | */
45 | public enum NetworkReachabilityStatus {
46 | case Unknown
47 | case NotReachable
48 | case Reachable(ConnectionType)
49 | }
50 |
51 | /**
52 | Defines the various connection types detected by reachability flags.
53 |
54 | - EthernetOrWiFi: The connection type is either over Ethernet or WiFi.
55 | - WWAN: The connection type is a WWAN connection.
56 | */
57 | public enum ConnectionType {
58 | case EthernetOrWiFi
59 | case WWAN
60 | }
61 |
62 | /// A closure executed when the network reachability status changes. The closure takes a single argument: the
63 | /// network reachability status.
64 | public typealias Listener = NetworkReachabilityStatus -> Void
65 |
66 | // MARK: - Properties
67 |
68 | /// Whether the network is currently reachable.
69 | public var isReachable: Bool { return isReachableOnWWAN || isReachableOnEthernetOrWiFi }
70 |
71 | /// Whether the network is currently reachable over the WWAN interface.
72 | public var isReachableOnWWAN: Bool { return networkReachabilityStatus == .Reachable(.WWAN) }
73 |
74 | /// Whether the network is currently reachable over Ethernet or WiFi interface.
75 | public var isReachableOnEthernetOrWiFi: Bool { return networkReachabilityStatus == .Reachable(.EthernetOrWiFi) }
76 |
77 | /// The current network reachability status.
78 | public var networkReachabilityStatus: NetworkReachabilityStatus {
79 | guard let flags = self.flags else { return .Unknown }
80 | return networkReachabilityStatusForFlags(flags)
81 | }
82 |
83 | /// The dispatch queue to execute the `listener` closure on.
84 | public var listenerQueue: dispatch_queue_t = dispatch_get_main_queue()
85 |
86 | /// A closure executed when the network reachability status changes.
87 | public var listener: Listener?
88 |
89 | private var flags: SCNetworkReachabilityFlags? {
90 | var flags = SCNetworkReachabilityFlags()
91 |
92 | if SCNetworkReachabilityGetFlags(reachability, &flags) {
93 | return flags
94 | }
95 |
96 | return nil
97 | }
98 |
99 | private let reachability: SCNetworkReachability
100 | private var previousFlags: SCNetworkReachabilityFlags
101 |
102 | // MARK: - Initialization
103 |
104 | /**
105 | Creates a `NetworkReachabilityManager` instance with the specified host.
106 |
107 | - parameter host: The host used to evaluate network reachability.
108 |
109 | - returns: The new `NetworkReachabilityManager` instance.
110 | */
111 | public convenience init?(host: String) {
112 | guard let reachability = SCNetworkReachabilityCreateWithName(nil, host) else { return nil }
113 | self.init(reachability: reachability)
114 | }
115 |
116 | /**
117 | Creates a `NetworkReachabilityManager` instance with the default socket IPv4 or IPv6 address.
118 |
119 | - returns: The new `NetworkReachabilityManager` instance.
120 | */
121 | public convenience init?() {
122 | if #available(iOS 9.0, OSX 10.10, *) {
123 | var address = sockaddr_in6()
124 | address.sin6_len = UInt8(sizeofValue(address))
125 | address.sin6_family = sa_family_t(AF_INET6)
126 |
127 | guard let reachability = withUnsafePointer(&address, {
128 | SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
129 | }) else { return nil }
130 |
131 | self.init(reachability: reachability)
132 | } else {
133 | var address = sockaddr_in()
134 | address.sin_len = UInt8(sizeofValue(address))
135 | address.sin_family = sa_family_t(AF_INET)
136 |
137 | guard let reachability = withUnsafePointer(&address, {
138 | SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
139 | }) else { return nil }
140 |
141 | self.init(reachability: reachability)
142 | }
143 | }
144 |
145 | private init(reachability: SCNetworkReachability) {
146 | self.reachability = reachability
147 | self.previousFlags = SCNetworkReachabilityFlags()
148 | }
149 |
150 | deinit {
151 | stopListening()
152 | }
153 |
154 | // MARK: - Listening
155 |
156 | /**
157 | Starts listening for changes in network reachability status.
158 |
159 | - returns: `true` if listening was started successfully, `false` otherwise.
160 | */
161 | public func startListening() -> Bool {
162 | var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
163 | context.info = UnsafeMutablePointer(Unmanaged.passUnretained(self).toOpaque())
164 |
165 | let callbackEnabled = SCNetworkReachabilitySetCallback(
166 | reachability,
167 | { (_, flags, info) in
168 | let reachability = Unmanaged.fromOpaque(COpaquePointer(info)).takeUnretainedValue()
169 | reachability.notifyListener(flags)
170 | },
171 | &context
172 | )
173 |
174 | let queueEnabled = SCNetworkReachabilitySetDispatchQueue(reachability, listenerQueue)
175 |
176 | dispatch_async(listenerQueue) {
177 | self.previousFlags = SCNetworkReachabilityFlags()
178 | self.notifyListener(self.flags ?? SCNetworkReachabilityFlags())
179 | }
180 |
181 | return callbackEnabled && queueEnabled
182 | }
183 |
184 | /**
185 | Stops listening for changes in network reachability status.
186 | */
187 | public func stopListening() {
188 | SCNetworkReachabilitySetCallback(reachability, nil, nil)
189 | SCNetworkReachabilitySetDispatchQueue(reachability, nil)
190 | }
191 |
192 | // MARK: - Internal - Listener Notification
193 |
194 | func notifyListener(flags: SCNetworkReachabilityFlags) {
195 | guard previousFlags != flags else { return }
196 | previousFlags = flags
197 |
198 | listener?(networkReachabilityStatusForFlags(flags))
199 | }
200 |
201 | // MARK: - Internal - Network Reachability Status
202 |
203 | func networkReachabilityStatusForFlags(flags: SCNetworkReachabilityFlags) -> NetworkReachabilityStatus {
204 | guard flags.contains(.Reachable) else { return .NotReachable }
205 |
206 | var networkStatus: NetworkReachabilityStatus = .NotReachable
207 |
208 | if !flags.contains(.ConnectionRequired) { networkStatus = .Reachable(.EthernetOrWiFi) }
209 |
210 | if flags.contains(.ConnectionOnDemand) || flags.contains(.ConnectionOnTraffic) {
211 | if !flags.contains(.InterventionRequired) { networkStatus = .Reachable(.EthernetOrWiFi) }
212 | }
213 |
214 | #if os(iOS)
215 | if flags.contains(.IsWWAN) { networkStatus = .Reachable(.WWAN) }
216 | #endif
217 |
218 | return networkStatus
219 | }
220 | }
221 |
222 | // MARK: -
223 |
224 | extension NetworkReachabilityManager.NetworkReachabilityStatus: Equatable {}
225 |
226 | /**
227 | Returns whether the two network reachability status values are equal.
228 |
229 | - parameter lhs: The left-hand side value to compare.
230 | - parameter rhs: The right-hand side value to compare.
231 |
232 | - returns: `true` if the two values are equal, `false` otherwise.
233 | */
234 | public func ==(
235 | lhs: NetworkReachabilityManager.NetworkReachabilityStatus,
236 | rhs: NetworkReachabilityManager.NetworkReachabilityStatus)
237 | -> Bool
238 | {
239 | switch (lhs, rhs) {
240 | case (.Unknown, .Unknown):
241 | return true
242 | case (.NotReachable, .NotReachable):
243 | return true
244 | case let (.Reachable(lhsConnectionType), .Reachable(rhsConnectionType)):
245 | return lhsConnectionType == rhsConnectionType
246 | default:
247 | return false
248 | }
249 | }
250 |
251 | #endif
252 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Alamofire/Source/Notifications.swift:
--------------------------------------------------------------------------------
1 | // Notifications.swift
2 | //
3 | // Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
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
13 | // all 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
21 | // THE SOFTWARE.
22 |
23 | import Foundation
24 |
25 | /// Contains all the `NSNotification` names posted by Alamofire with descriptions of each notification's payload.
26 | public struct Notifications {
27 | /// Used as a namespace for all `NSURLSessionTask` related notifications.
28 | public struct Task {
29 | /// Notification posted when an `NSURLSessionTask` is resumed. The notification `object` contains the resumed
30 | /// `NSURLSessionTask`.
31 | public static let DidResume = "com.alamofire.notifications.task.didResume"
32 |
33 | /// Notification posted when an `NSURLSessionTask` is suspended. The notification `object` contains the
34 | /// suspended `NSURLSessionTask`.
35 | public static let DidSuspend = "com.alamofire.notifications.task.didSuspend"
36 |
37 | /// Notification posted when an `NSURLSessionTask` is cancelled. The notification `object` contains the
38 | /// cancelled `NSURLSessionTask`.
39 | public static let DidCancel = "com.alamofire.notifications.task.didCancel"
40 |
41 | /// Notification posted when an `NSURLSessionTask` is completed. The notification `object` contains the
42 | /// completed `NSURLSessionTask`.
43 | public static let DidComplete = "com.alamofire.notifications.task.didComplete"
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Alamofire/Source/ParameterEncoding.swift:
--------------------------------------------------------------------------------
1 | // ParameterEncoding.swift
2 | //
3 | // Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
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
13 | // all 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
21 | // THE SOFTWARE.
22 |
23 | import Foundation
24 |
25 | /**
26 | HTTP method definitions.
27 |
28 | See https://tools.ietf.org/html/rfc7231#section-4.3
29 | */
30 | public enum Method: String {
31 | case OPTIONS, GET, HEAD, POST, PUT, PATCH, DELETE, TRACE, CONNECT
32 | }
33 |
34 | // MARK: ParameterEncoding
35 |
36 | /**
37 | Used to specify the way in which a set of parameters are applied to a URL request.
38 |
39 | - `URL`: Creates a query string to be set as or appended to any existing URL query for `GET`, `HEAD`,
40 | and `DELETE` requests, or set as the body for requests with any other HTTP method. The
41 | `Content-Type` HTTP header field of an encoded request with HTTP body is set to
42 | `application/x-www-form-urlencoded; charset=utf-8`. Since there is no published specification
43 | for how to encode collection types, the convention of appending `[]` to the key for array
44 | values (`foo[]=1&foo[]=2`), and appending the key surrounded by square brackets for nested
45 | dictionary values (`foo[bar]=baz`).
46 |
47 | - `URLEncodedInURL`: Creates query string to be set as or appended to any existing URL query. Uses the same
48 | implementation as the `.URL` case, but always applies the encoded result to the URL.
49 |
50 | - `JSON`: Uses `NSJSONSerialization` to create a JSON representation of the parameters object, which is
51 | set as the body of the request. The `Content-Type` HTTP header field of an encoded request is
52 | set to `application/json`.
53 |
54 | - `PropertyList`: Uses `NSPropertyListSerialization` to create a plist representation of the parameters object,
55 | according to the associated format and write options values, which is set as the body of the
56 | request. The `Content-Type` HTTP header field of an encoded request is set to
57 | `application/x-plist`.
58 |
59 | - `Custom`: Uses the associated closure value to construct a new request given an existing request and
60 | parameters.
61 | */
62 | public enum ParameterEncoding {
63 | case URL
64 | case URLEncodedInURL
65 | case JSON
66 | case PropertyList(NSPropertyListFormat, NSPropertyListWriteOptions)
67 | case Custom((URLRequestConvertible, [String: AnyObject]?) -> (NSMutableURLRequest, NSError?))
68 |
69 | /**
70 | Creates a URL request by encoding parameters and applying them onto an existing request.
71 |
72 | - parameter URLRequest: The request to have parameters applied.
73 | - parameter parameters: The parameters to apply.
74 |
75 | - returns: A tuple containing the constructed request and the error that occurred during parameter encoding,
76 | if any.
77 | */
78 | public func encode(
79 | URLRequest: URLRequestConvertible,
80 | parameters: [String: AnyObject]?)
81 | -> (NSMutableURLRequest, NSError?)
82 | {
83 | var mutableURLRequest = URLRequest.URLRequest
84 |
85 | guard let parameters = parameters else { return (mutableURLRequest, nil) }
86 |
87 | var encodingError: NSError? = nil
88 |
89 | switch self {
90 | case .URL, .URLEncodedInURL:
91 | func query(parameters: [String: AnyObject]) -> String {
92 | var components: [(String, String)] = []
93 |
94 | for key in parameters.keys.sort(<) {
95 | let value = parameters[key]!
96 | components += queryComponents(key, value)
97 | }
98 |
99 | return (components.map { "\($0)=\($1)" } as [String]).joinWithSeparator("&")
100 | }
101 |
102 | func encodesParametersInURL(method: Method) -> Bool {
103 | switch self {
104 | case .URLEncodedInURL:
105 | return true
106 | default:
107 | break
108 | }
109 |
110 | switch method {
111 | case .GET, .HEAD, .DELETE:
112 | return true
113 | default:
114 | return false
115 | }
116 | }
117 |
118 | if let method = Method(rawValue: mutableURLRequest.HTTPMethod) where encodesParametersInURL(method) {
119 | if let
120 | URLComponents = NSURLComponents(URL: mutableURLRequest.URL!, resolvingAgainstBaseURL: false)
121 | where !parameters.isEmpty
122 | {
123 | let percentEncodedQuery = (URLComponents.percentEncodedQuery.map { $0 + "&" } ?? "") + query(parameters)
124 | URLComponents.percentEncodedQuery = percentEncodedQuery
125 | mutableURLRequest.URL = URLComponents.URL
126 | }
127 | } else {
128 | if mutableURLRequest.valueForHTTPHeaderField("Content-Type") == nil {
129 | mutableURLRequest.setValue(
130 | "application/x-www-form-urlencoded; charset=utf-8",
131 | forHTTPHeaderField: "Content-Type"
132 | )
133 | }
134 |
135 | mutableURLRequest.HTTPBody = query(parameters).dataUsingEncoding(
136 | NSUTF8StringEncoding,
137 | allowLossyConversion: false
138 | )
139 | }
140 | case .JSON:
141 | do {
142 | let options = NSJSONWritingOptions()
143 | let data = try NSJSONSerialization.dataWithJSONObject(parameters, options: options)
144 |
145 | if mutableURLRequest.valueForHTTPHeaderField("Content-Type") == nil {
146 | mutableURLRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
147 | }
148 |
149 | mutableURLRequest.HTTPBody = data
150 | } catch {
151 | encodingError = error as NSError
152 | }
153 | case .PropertyList(let format, let options):
154 | do {
155 | let data = try NSPropertyListSerialization.dataWithPropertyList(
156 | parameters,
157 | format: format,
158 | options: options
159 | )
160 |
161 | if mutableURLRequest.valueForHTTPHeaderField("Content-Type") == nil {
162 | mutableURLRequest.setValue("application/x-plist", forHTTPHeaderField: "Content-Type")
163 | }
164 |
165 | mutableURLRequest.HTTPBody = data
166 | } catch {
167 | encodingError = error as NSError
168 | }
169 | case .Custom(let closure):
170 | (mutableURLRequest, encodingError) = closure(mutableURLRequest, parameters)
171 | }
172 |
173 | return (mutableURLRequest, encodingError)
174 | }
175 |
176 | /**
177 | Creates percent-escaped, URL encoded query string components from the given key-value pair using recursion.
178 |
179 | - parameter key: The key of the query component.
180 | - parameter value: The value of the query component.
181 |
182 | - returns: The percent-escaped, URL encoded query string components.
183 | */
184 | public func queryComponents(key: String, _ value: AnyObject) -> [(String, String)] {
185 | var components: [(String, String)] = []
186 |
187 | if let dictionary = value as? [String: AnyObject] {
188 | for (nestedKey, value) in dictionary {
189 | components += queryComponents("\(key)[\(nestedKey)]", value)
190 | }
191 | } else if let array = value as? [AnyObject] {
192 | for value in array {
193 | components += queryComponents("\(key)[]", value)
194 | }
195 | } else {
196 | components.append((escape(key), escape("\(value)")))
197 | }
198 |
199 | return components
200 | }
201 |
202 | /**
203 | Returns a percent-escaped string following RFC 3986 for a query string key or value.
204 |
205 | RFC 3986 states that the following characters are "reserved" characters.
206 |
207 | - General Delimiters: ":", "#", "[", "]", "@", "?", "/"
208 | - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "="
209 |
210 | In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow
211 | query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/"
212 | should be percent-escaped in the query string.
213 |
214 | - parameter string: The string to be percent-escaped.
215 |
216 | - returns: The percent-escaped string.
217 | */
218 | public func escape(string: String) -> String {
219 | let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
220 | let subDelimitersToEncode = "!$&'()*+,;="
221 |
222 | let allowedCharacterSet = NSCharacterSet.URLQueryAllowedCharacterSet().mutableCopy() as! NSMutableCharacterSet
223 | allowedCharacterSet.removeCharactersInString(generalDelimitersToEncode + subDelimitersToEncode)
224 |
225 | var escaped = ""
226 |
227 | //==========================================================================================================
228 | //
229 | // Batching is required for escaping due to an internal bug in iOS 8.1 and 8.2. Encoding more than a few
230 | // hundred Chinense characters causes various malloc error crashes. To avoid this issue until iOS 8 is no
231 | // longer supported, batching MUST be used for encoding. This introduces roughly a 20% overhead. For more
232 | // info, please refer to:
233 | //
234 | // - https://github.com/Alamofire/Alamofire/issues/206
235 | //
236 | //==========================================================================================================
237 |
238 | if #available(iOS 8.3, OSX 10.10, *) {
239 | escaped = string.stringByAddingPercentEncodingWithAllowedCharacters(allowedCharacterSet) ?? string
240 | } else {
241 | let batchSize = 50
242 | var index = string.startIndex
243 |
244 | while index != string.endIndex {
245 | let startIndex = index
246 | let endIndex = index.advancedBy(batchSize, limit: string.endIndex)
247 | let range = startIndex.. {
27 | /// The URL request sent to the server.
28 | public let request: NSURLRequest?
29 |
30 | /// The server's response to the URL request.
31 | public let response: NSHTTPURLResponse?
32 |
33 | /// The data returned by the server.
34 | public let data: NSData?
35 |
36 | /// The result of response serialization.
37 | public let result: Result
38 |
39 | /// The timeline of the complete lifecycle of the `Request`.
40 | public let timeline: Timeline
41 |
42 | /**
43 | Initializes the `Response` instance with the specified URL request, URL response, server data and response
44 | serialization result.
45 |
46 | - parameter request: The URL request sent to the server.
47 | - parameter response: The server's response to the URL request.
48 | - parameter data: The data returned by the server.
49 | - parameter result: The result of response serialization.
50 | - parameter timeline: The timeline of the complete lifecycle of the `Request`. Defaults to `Timeline()`.
51 |
52 | - returns: the new `Response` instance.
53 | */
54 | public init(
55 | request: NSURLRequest?,
56 | response: NSHTTPURLResponse?,
57 | data: NSData?,
58 | result: Result,
59 | timeline: Timeline = Timeline())
60 | {
61 | self.request = request
62 | self.response = response
63 | self.data = data
64 | self.result = result
65 | self.timeline = timeline
66 | }
67 | }
68 |
69 | // MARK: - CustomStringConvertible
70 |
71 | extension Response: CustomStringConvertible {
72 | /// The textual representation used when written to an output stream, which includes whether the result was a
73 | /// success or failure.
74 | public var description: String {
75 | return result.debugDescription
76 | }
77 | }
78 |
79 | // MARK: - CustomDebugStringConvertible
80 |
81 | extension Response: CustomDebugStringConvertible {
82 | /// The debug textual representation used when written to an output stream, which includes the URL request, the URL
83 | /// response, the server data and the response serialization result.
84 | public var debugDescription: String {
85 | var output: [String] = []
86 |
87 | output.append(request != nil ? "[Request]: \(request!)" : "[Request]: nil")
88 | output.append(response != nil ? "[Response]: \(response!)" : "[Response]: nil")
89 | output.append("[Data]: \(data?.length ?? 0) bytes")
90 | output.append("[Result]: \(result.debugDescription)")
91 | output.append("[Timeline]: \(timeline.debugDescription)")
92 |
93 | return output.joinWithSeparator("\n")
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Alamofire/Source/Result.swift:
--------------------------------------------------------------------------------
1 | // Result.swift
2 | //
3 | // Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
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
13 | // all 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
21 | // THE SOFTWARE.
22 |
23 | import Foundation
24 |
25 | /**
26 | Used to represent whether a request was successful or encountered an error.
27 |
28 | - Success: The request and all post processing operations were successful resulting in the serialization of the
29 | provided associated value.
30 | - Failure: The request encountered an error resulting in a failure. The associated values are the original data
31 | provided by the server as well as the error that caused the failure.
32 | */
33 | public enum Result {
34 | case Success(Value)
35 | case Failure(Error)
36 |
37 | /// Returns `true` if the result is a success, `false` otherwise.
38 | public var isSuccess: Bool {
39 | switch self {
40 | case .Success:
41 | return true
42 | case .Failure:
43 | return false
44 | }
45 | }
46 |
47 | /// Returns `true` if the result is a failure, `false` otherwise.
48 | public var isFailure: Bool {
49 | return !isSuccess
50 | }
51 |
52 | /// Returns the associated value if the result is a success, `nil` otherwise.
53 | public var value: Value? {
54 | switch self {
55 | case .Success(let value):
56 | return value
57 | case .Failure:
58 | return nil
59 | }
60 | }
61 |
62 | /// Returns the associated error value if the result is a failure, `nil` otherwise.
63 | public var error: Error? {
64 | switch self {
65 | case .Success:
66 | return nil
67 | case .Failure(let error):
68 | return error
69 | }
70 | }
71 | }
72 |
73 | // MARK: - CustomStringConvertible
74 |
75 | extension Result: CustomStringConvertible {
76 | /// The textual representation used when written to an output stream, which includes whether the result was a
77 | /// success or failure.
78 | public var description: String {
79 | switch self {
80 | case .Success:
81 | return "SUCCESS"
82 | case .Failure:
83 | return "FAILURE"
84 | }
85 | }
86 | }
87 |
88 | // MARK: - CustomDebugStringConvertible
89 |
90 | extension Result: CustomDebugStringConvertible {
91 | /// The debug textual representation used when written to an output stream, which includes whether the result was a
92 | /// success or failure in addition to the value or error.
93 | public var debugDescription: String {
94 | switch self {
95 | case .Success(let value):
96 | return "SUCCESS: \(value)"
97 | case .Failure(let error):
98 | return "FAILURE: \(error)"
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Alamofire/Source/Stream.swift:
--------------------------------------------------------------------------------
1 | // Stream.swift
2 | //
3 | // Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
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
13 | // all 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
21 | // THE SOFTWARE.
22 |
23 | import Foundation
24 |
25 | #if !os(watchOS)
26 |
27 | @available(iOS 9.0, OSX 10.11, tvOS 9.0, *)
28 | extension Manager {
29 | private enum Streamable {
30 | case Stream(String, Int)
31 | case NetService(NSNetService)
32 | }
33 |
34 | private func stream(streamable: Streamable) -> Request {
35 | var streamTask: NSURLSessionStreamTask!
36 |
37 | switch streamable {
38 | case .Stream(let hostName, let port):
39 | dispatch_sync(queue) {
40 | streamTask = self.session.streamTaskWithHostName(hostName, port: port)
41 | }
42 | case .NetService(let netService):
43 | dispatch_sync(queue) {
44 | streamTask = self.session.streamTaskWithNetService(netService)
45 | }
46 | }
47 |
48 | let request = Request(session: session, task: streamTask)
49 |
50 | delegate[request.delegate.task] = request.delegate
51 |
52 | if startRequestsImmediately {
53 | request.resume()
54 | }
55 |
56 | return request
57 | }
58 |
59 | /**
60 | Creates a request for bidirectional streaming with the given hostname and port.
61 |
62 | - parameter hostName: The hostname of the server to connect to.
63 | - parameter port: The port of the server to connect to.
64 |
65 | :returns: The created stream request.
66 | */
67 | public func stream(hostName hostName: String, port: Int) -> Request {
68 | return stream(.Stream(hostName, port))
69 | }
70 |
71 | /**
72 | Creates a request for bidirectional streaming with the given `NSNetService`.
73 |
74 | - parameter netService: The net service used to identify the endpoint.
75 |
76 | - returns: The created stream request.
77 | */
78 | public func stream(netService netService: NSNetService) -> Request {
79 | return stream(.NetService(netService))
80 | }
81 | }
82 |
83 | // MARK: -
84 |
85 | @available(iOS 9.0, OSX 10.11, tvOS 9.0, *)
86 | extension Manager.SessionDelegate: NSURLSessionStreamDelegate {
87 |
88 | // MARK: Override Closures
89 |
90 | /// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:readClosedForStreamTask:`.
91 | public var streamTaskReadClosed: ((NSURLSession, NSURLSessionStreamTask) -> Void)? {
92 | get {
93 | return _streamTaskReadClosed as? (NSURLSession, NSURLSessionStreamTask) -> Void
94 | }
95 | set {
96 | _streamTaskReadClosed = newValue
97 | }
98 | }
99 |
100 | /// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:writeClosedForStreamTask:`.
101 | public var streamTaskWriteClosed: ((NSURLSession, NSURLSessionStreamTask) -> Void)? {
102 | get {
103 | return _streamTaskWriteClosed as? (NSURLSession, NSURLSessionStreamTask) -> Void
104 | }
105 | set {
106 | _streamTaskWriteClosed = newValue
107 | }
108 | }
109 |
110 | /// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:betterRouteDiscoveredForStreamTask:`.
111 | public var streamTaskBetterRouteDiscovered: ((NSURLSession, NSURLSessionStreamTask) -> Void)? {
112 | get {
113 | return _streamTaskBetterRouteDiscovered as? (NSURLSession, NSURLSessionStreamTask) -> Void
114 | }
115 | set {
116 | _streamTaskBetterRouteDiscovered = newValue
117 | }
118 | }
119 |
120 | /// Overrides default behavior for NSURLSessionStreamDelegate method `URLSession:streamTask:didBecomeInputStream:outputStream:`.
121 | public var streamTaskDidBecomeInputStream: ((NSURLSession, NSURLSessionStreamTask, NSInputStream, NSOutputStream) -> Void)? {
122 | get {
123 | return _streamTaskDidBecomeInputStream as? (NSURLSession, NSURLSessionStreamTask, NSInputStream, NSOutputStream) -> Void
124 | }
125 | set {
126 | _streamTaskDidBecomeInputStream = newValue
127 | }
128 | }
129 |
130 | // MARK: Delegate Methods
131 |
132 | /**
133 | Tells the delegate that the read side of the connection has been closed.
134 |
135 | - parameter session: The session.
136 | - parameter streamTask: The stream task.
137 | */
138 | public func URLSession(session: NSURLSession, readClosedForStreamTask streamTask: NSURLSessionStreamTask) {
139 | streamTaskReadClosed?(session, streamTask)
140 | }
141 |
142 | /**
143 | Tells the delegate that the write side of the connection has been closed.
144 |
145 | - parameter session: The session.
146 | - parameter streamTask: The stream task.
147 | */
148 | public func URLSession(session: NSURLSession, writeClosedForStreamTask streamTask: NSURLSessionStreamTask) {
149 | streamTaskWriteClosed?(session, streamTask)
150 | }
151 |
152 | /**
153 | Tells the delegate that the system has determined that a better route to the host is available.
154 |
155 | - parameter session: The session.
156 | - parameter streamTask: The stream task.
157 | */
158 | public func URLSession(session: NSURLSession, betterRouteDiscoveredForStreamTask streamTask: NSURLSessionStreamTask) {
159 | streamTaskBetterRouteDiscovered?(session, streamTask)
160 | }
161 |
162 | /**
163 | Tells the delegate that the stream task has been completed and provides the unopened stream objects.
164 |
165 | - parameter session: The session.
166 | - parameter streamTask: The stream task.
167 | - parameter inputStream: The new input stream.
168 | - parameter outputStream: The new output stream.
169 | */
170 | public func URLSession(
171 | session: NSURLSession,
172 | streamTask: NSURLSessionStreamTask,
173 | didBecomeInputStream inputStream: NSInputStream,
174 | outputStream: NSOutputStream)
175 | {
176 | streamTaskDidBecomeInputStream?(session, streamTask, inputStream, outputStream)
177 | }
178 | }
179 |
180 | #endif
181 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Alamofire/Source/Timeline.swift:
--------------------------------------------------------------------------------
1 | // Timeline.swift
2 | //
3 | // Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
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
13 | // all 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
21 | // THE SOFTWARE.
22 |
23 | import Foundation
24 |
25 | /// Responsible for computing the timing metrics for the complete lifecycle of a `Request`.
26 | public struct Timeline {
27 | /// The time the request was initialized.
28 | public let requestStartTime: CFAbsoluteTime
29 |
30 | /// The time the first bytes were received from or sent to the server.
31 | public let initialResponseTime: CFAbsoluteTime
32 |
33 | /// The time when the request was completed.
34 | public let requestCompletedTime: CFAbsoluteTime
35 |
36 | /// The time when the response serialization was completed.
37 | public let serializationCompletedTime: CFAbsoluteTime
38 |
39 | /// The time interval in seconds from the time the request started to the initial response from the server.
40 | public let latency: NSTimeInterval
41 |
42 | /// The time interval in seconds from the time the request started to the time the request completed.
43 | public let requestDuration: NSTimeInterval
44 |
45 | /// The time interval in seconds from the time the request completed to the time response serialization completed.
46 | public let serializationDuration: NSTimeInterval
47 |
48 | /// The time interval in seconds from the time the request started to the time response serialization completed.
49 | public let totalDuration: NSTimeInterval
50 |
51 | /**
52 | Creates a new `Timeline` instance with the specified request times.
53 |
54 | - parameter requestStartTime: The time the request was initialized. Defaults to `0.0`.
55 | - parameter initialResponseTime: The time the first bytes were received from or sent to the server.
56 | Defaults to `0.0`.
57 | - parameter requestCompletedTime: The time when the request was completed. Defaults to `0.0`.
58 | - parameter serializationCompletedTime: The time when the response serialization was completed. Defaults
59 | to `0.0`.
60 |
61 | - returns: The new `Timeline` instance.
62 | */
63 | public init(
64 | requestStartTime: CFAbsoluteTime = 0.0,
65 | initialResponseTime: CFAbsoluteTime = 0.0,
66 | requestCompletedTime: CFAbsoluteTime = 0.0,
67 | serializationCompletedTime: CFAbsoluteTime = 0.0)
68 | {
69 | self.requestStartTime = requestStartTime
70 | self.initialResponseTime = initialResponseTime
71 | self.requestCompletedTime = requestCompletedTime
72 | self.serializationCompletedTime = serializationCompletedTime
73 |
74 | self.latency = initialResponseTime - requestStartTime
75 | self.requestDuration = requestCompletedTime - requestStartTime
76 | self.serializationDuration = serializationCompletedTime - requestCompletedTime
77 | self.totalDuration = serializationCompletedTime - requestStartTime
78 | }
79 | }
80 |
81 | // MARK: - CustomStringConvertible
82 |
83 | extension Timeline: CustomStringConvertible {
84 | /// The textual representation used when written to an output stream, which includes the latency, the request
85 | /// duration and the total duration.
86 | public var description: String {
87 | let latency = String(format: "%.3f", self.latency)
88 | let requestDuration = String(format: "%.3f", self.requestDuration)
89 | let serializationDuration = String(format: "%.3f", self.serializationDuration)
90 | let totalDuration = String(format: "%.3f", self.totalDuration)
91 |
92 | let timings = [
93 | "\"Latency\": \(latency) secs",
94 | "\"Request Duration\": \(requestDuration) secs",
95 | "\"Serialization Duration\": \(serializationDuration) secs",
96 | "\"Total Duration\": \(totalDuration) secs"
97 | ]
98 |
99 | return "Timeline: { \(timings.joinWithSeparator(", ")) }"
100 | }
101 | }
102 |
103 | // MARK: - CustomDebugStringConvertible
104 |
105 | extension Timeline: CustomDebugStringConvertible {
106 | /// The textual representation used when written to an output stream, which includes the request start time, the
107 | /// initial response time, the request completed time, the serialization completed time, the latency, the request
108 | /// duration and the total duration.
109 | public var debugDescription: String {
110 | let timings = [
111 | "\"Request Start Time\": \(requestStartTime)",
112 | "\"Initial Response Time\": \(initialResponseTime)",
113 | "\"Request Completed Time\": \(requestCompletedTime)",
114 | "\"Serialization Completed Time\": \(serializationCompletedTime)",
115 | "\"Latency\": \(latency) secs",
116 | "\"Request Duration\": \(requestDuration) secs",
117 | "\"Serialization Duration\": \(serializationDuration) secs",
118 | "\"Total Duration\": \(totalDuration) secs"
119 | ]
120 |
121 | return "Timeline: { \(timings.joinWithSeparator(", ")) }"
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Alamofire/Source/Validation.swift:
--------------------------------------------------------------------------------
1 | // Validation.swift
2 | //
3 | // Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
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
13 | // all 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
21 | // THE SOFTWARE.
22 |
23 | import Foundation
24 |
25 | extension Request {
26 |
27 | /**
28 | Used to represent whether validation was successful or encountered an error resulting in a failure.
29 |
30 | - Success: The validation was successful.
31 | - Failure: The validation failed encountering the provided error.
32 | */
33 | public enum ValidationResult {
34 | case Success
35 | case Failure(NSError)
36 | }
37 |
38 | /**
39 | A closure used to validate a request that takes a URL request and URL response, and returns whether the
40 | request was valid.
41 | */
42 | public typealias Validation = (NSURLRequest?, NSHTTPURLResponse) -> ValidationResult
43 |
44 | /**
45 | Validates the request, using the specified closure.
46 |
47 | If validation fails, subsequent calls to response handlers will have an associated error.
48 |
49 | - parameter validation: A closure to validate the request.
50 |
51 | - returns: The request.
52 | */
53 | public func validate(validation: Validation) -> Self {
54 | delegate.queue.addOperationWithBlock {
55 | if let
56 | response = self.response where self.delegate.error == nil,
57 | case let .Failure(error) = validation(self.request, response)
58 | {
59 | self.delegate.error = error
60 | }
61 | }
62 |
63 | return self
64 | }
65 |
66 | // MARK: - Status Code
67 |
68 | /**
69 | Validates that the response has a status code in the specified range.
70 |
71 | If validation fails, subsequent calls to response handlers will have an associated error.
72 |
73 | - parameter range: The range of acceptable status codes.
74 |
75 | - returns: The request.
76 | */
77 | public func validate(statusCode acceptableStatusCode: S) -> Self {
78 | return validate { _, response in
79 | if acceptableStatusCode.contains(response.statusCode) {
80 | return .Success
81 | } else {
82 | let failureReason = "Response status code was unacceptable: \(response.statusCode)"
83 | return .Failure(Error.errorWithCode(.StatusCodeValidationFailed, failureReason: failureReason))
84 | }
85 | }
86 | }
87 |
88 | // MARK: - Content-Type
89 |
90 | private struct MIMEType {
91 | let type: String
92 | let subtype: String
93 |
94 | init?(_ string: String) {
95 | let components: [String] = {
96 | let stripped = string.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
97 | let split = stripped.substringToIndex(stripped.rangeOfString(";")?.startIndex ?? stripped.endIndex)
98 | return split.componentsSeparatedByString("/")
99 | }()
100 |
101 | if let
102 | type = components.first,
103 | subtype = components.last
104 | {
105 | self.type = type
106 | self.subtype = subtype
107 | } else {
108 | return nil
109 | }
110 | }
111 |
112 | func matches(MIME: MIMEType) -> Bool {
113 | switch (type, subtype) {
114 | case (MIME.type, MIME.subtype), (MIME.type, "*"), ("*", MIME.subtype), ("*", "*"):
115 | return true
116 | default:
117 | return false
118 | }
119 | }
120 | }
121 |
122 | /**
123 | Validates that the response has a content type in the specified array.
124 |
125 | If validation fails, subsequent calls to response handlers will have an associated error.
126 |
127 | - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes.
128 |
129 | - returns: The request.
130 | */
131 | public func validate(contentType acceptableContentTypes: S) -> Self {
132 | return validate { _, response in
133 | guard let validData = self.delegate.data where validData.length > 0 else { return .Success }
134 |
135 | if let
136 | responseContentType = response.MIMEType,
137 | responseMIMEType = MIMEType(responseContentType)
138 | {
139 | for contentType in acceptableContentTypes {
140 | if let acceptableMIMEType = MIMEType(contentType) where acceptableMIMEType.matches(responseMIMEType) {
141 | return .Success
142 | }
143 | }
144 | } else {
145 | for contentType in acceptableContentTypes {
146 | if let MIMEType = MIMEType(contentType) where MIMEType.type == "*" && MIMEType.subtype == "*" {
147 | return .Success
148 | }
149 | }
150 | }
151 |
152 | let failureReason: String
153 |
154 | if let responseContentType = response.MIMEType {
155 | failureReason = (
156 | "Response content type \"\(responseContentType)\" does not match any acceptable " +
157 | "content types: \(acceptableContentTypes)"
158 | )
159 | } else {
160 | failureReason = "Response content type was missing and acceptable content type does not match \"*/*\""
161 | }
162 |
163 | return .Failure(Error.errorWithCode(.ContentTypeValidationFailed, failureReason: failureReason))
164 | }
165 | }
166 |
167 | // MARK: - Automatic
168 |
169 | /**
170 | Validates that the response has a status code in the default acceptable range of 200...299, and that the content
171 | type matches any specified in the Accept HTTP header field.
172 |
173 | If validation fails, subsequent calls to response handlers will have an associated error.
174 |
175 | - returns: The request.
176 | */
177 | public func validate() -> Self {
178 | let acceptableStatusCodes: Range = 200..<300
179 | let acceptableContentTypes: [String] = {
180 | if let accept = request?.valueForHTTPHeaderField("Accept") {
181 | return accept.componentsSeparatedByString(",")
182 | }
183 |
184 | return ["*/*"]
185 | }()
186 |
187 | return validate(statusCode: acceptableStatusCodes).validate(contentType: acceptableContentTypes)
188 | }
189 | }
190 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Manifest.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Alamofire (3.3.0)
3 |
4 | DEPENDENCIES:
5 | - Alamofire (~> 3.0)
6 |
7 | SPEC CHECKSUMS:
8 | Alamofire: 9054db4a1b1ca9e363223183e01cea380159a27c
9 |
10 | COCOAPODS: 0.38.2
11 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Pods.xcodeproj/xcuserdata/Nikhil.xcuserdatad/xcschemes/Alamofire.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
47 |
48 |
54 |
55 |
57 |
58 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Pods.xcodeproj/xcuserdata/Nikhil.xcuserdatad/xcschemes/Pods-Brainwaves.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
47 |
48 |
54 |
55 |
57 |
58 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Pods.xcodeproj/xcuserdata/Nikhil.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Alamofire.xcscheme
8 |
9 | isShown
10 |
11 |
12 | Pods-Brainwaves.xcscheme
13 |
14 | isShown
15 |
16 |
17 |
18 | SuppressBuildableAutocreation
19 |
20 | 9219B98EB82AD96713EE09393BF3142B
21 |
22 | primary
23 |
24 |
25 | C1256B9A6C84E34942961B033EDF92D2
26 |
27 | primary
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Target Support Files/Alamofire/Alamofire-Private.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Alamofire.xcconfig"
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Alamofire" "${PODS_ROOT}/Headers/Public"
4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
5 | PODS_ROOT = ${SRCROOT}
6 | SKIP_INSTALL = YES
--------------------------------------------------------------------------------
/Brainwaves/Pods/Target Support Files/Alamofire/Alamofire-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Alamofire : NSObject
3 | @end
4 | @implementation PodsDummy_Alamofire
5 | @end
6 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Target Support Files/Alamofire/Alamofire-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #endif
4 |
5 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Target Support Files/Alamofire/Alamofire-umbrella.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 |
4 | FOUNDATION_EXPORT double AlamofireVersionNumber;
5 | FOUNDATION_EXPORT const unsigned char AlamofireVersionString[];
6 |
7 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Target Support Files/Alamofire/Alamofire.modulemap:
--------------------------------------------------------------------------------
1 | framework module Alamofire {
2 | umbrella header "Alamofire-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Target Support Files/Alamofire/Alamofire.xcconfig:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nikhiljay/brainwaves/42d96dccedf09504589fc9e14e3b470de7f5c0b2/Brainwaves/Pods/Target Support Files/Alamofire/Alamofire.xcconfig
--------------------------------------------------------------------------------
/Brainwaves/Pods/Target Support Files/Alamofire/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 3.3.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Target Support Files/Pods-Brainwaves/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Target Support Files/Pods-Brainwaves/Pods-Brainwaves-acknowledgements.markdown:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 | This application makes use of the following third party libraries:
3 |
4 | ## Alamofire
5 |
6 | Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a copy
9 | of this software and associated documentation files (the "Software"), to deal
10 | in the Software without restriction, including without limitation the rights
11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | copies of the Software, and to permit persons to whom the Software is
13 | furnished to do so, subject to the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be included in
16 | all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | THE SOFTWARE.
25 |
26 | Generated by CocoaPods - http://cocoapods.org
27 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Target Support Files/Pods-Brainwaves/Pods-Brainwaves-acknowledgements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreferenceSpecifiers
6 |
7 |
8 | FooterText
9 | This application makes use of the following third party libraries:
10 | Title
11 | Acknowledgements
12 | Type
13 | PSGroupSpecifier
14 |
15 |
16 | FooterText
17 | Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
18 |
19 | Permission is hereby granted, free of charge, to any person obtaining a copy
20 | of this software and associated documentation files (the "Software"), to deal
21 | in the Software without restriction, including without limitation the rights
22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23 | copies of the Software, and to permit persons to whom the Software is
24 | furnished to do so, subject to the following conditions:
25 |
26 | The above copyright notice and this permission notice shall be included in
27 | all copies or substantial portions of the Software.
28 |
29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
35 | THE SOFTWARE.
36 |
37 | Title
38 | Alamofire
39 | Type
40 | PSGroupSpecifier
41 |
42 |
43 | FooterText
44 | Generated by CocoaPods - http://cocoapods.org
45 | Title
46 |
47 | Type
48 | PSGroupSpecifier
49 |
50 |
51 | StringsTable
52 | Acknowledgements
53 | Title
54 | Acknowledgements
55 |
56 |
57 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Target Support Files/Pods-Brainwaves/Pods-Brainwaves-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_Brainwaves : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_Brainwaves
5 | @end
6 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Target Support Files/Pods-Brainwaves/Pods-Brainwaves-frameworks.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
6 |
7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
8 |
9 | install_framework()
10 | {
11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
12 | local source="${BUILT_PRODUCTS_DIR}/$1"
13 | else
14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
15 | fi
16 |
17 | local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
18 |
19 | if [ -L "${source}" ]; then
20 | echo "Symlinked..."
21 | source="$(readlink "${source}")"
22 | fi
23 |
24 | # use filter instead of exclude so missing patterns dont' throw errors
25 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
26 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
27 |
28 | # Resign the code if required by the build settings to avoid unstable apps
29 | code_sign_if_enabled "${destination}/$(basename "$1")"
30 |
31 | # Embed linked Swift runtime libraries
32 | local basename
33 | basename="$(basename "$1" | sed -E s/\\..+// && exit ${PIPESTATUS[0]})"
34 | local swift_runtime_libs
35 | swift_runtime_libs=$(xcrun otool -LX "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/${basename}.framework/${basename}" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]})
36 | for lib in $swift_runtime_libs; do
37 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
38 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
39 | code_sign_if_enabled "${destination}/${lib}"
40 | done
41 | }
42 |
43 | # Signs a framework with the provided identity
44 | code_sign_if_enabled() {
45 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
46 | # Use the current code_sign_identitiy
47 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
48 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements \"$1\""
49 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1"
50 | fi
51 | }
52 |
53 |
54 | if [[ "$CONFIGURATION" == "Debug" ]]; then
55 | install_framework 'Pods-Brainwaves/Alamofire.framework'
56 | fi
57 | if [[ "$CONFIGURATION" == "Release" ]]; then
58 | install_framework 'Pods-Brainwaves/Alamofire.framework'
59 | fi
60 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Target Support Files/Pods-Brainwaves/Pods-Brainwaves-resources.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
5 |
6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
7 | > "$RESOURCES_TO_COPY"
8 |
9 | XCASSET_FILES=()
10 |
11 | realpath() {
12 | DIRECTORY="$(cd "${1%/*}" && pwd)"
13 | FILENAME="${1##*/}"
14 | echo "$DIRECTORY/$FILENAME"
15 | }
16 |
17 | install_resource()
18 | {
19 | case $1 in
20 | *.storyboard)
21 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
22 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
23 | ;;
24 | *.xib)
25 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
26 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
27 | ;;
28 | *.framework)
29 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
30 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
31 | echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
32 | rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
33 | ;;
34 | *.xcdatamodel)
35 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\""
36 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom"
37 | ;;
38 | *.xcdatamodeld)
39 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\""
40 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd"
41 | ;;
42 | *.xcmappingmodel)
43 | echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\""
44 | xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm"
45 | ;;
46 | *.xcassets)
47 | ABSOLUTE_XCASSET_FILE=$(realpath "${PODS_ROOT}/$1")
48 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
49 | ;;
50 | /*)
51 | echo "$1"
52 | echo "$1" >> "$RESOURCES_TO_COPY"
53 | ;;
54 | *)
55 | echo "${PODS_ROOT}/$1"
56 | echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY"
57 | ;;
58 | esac
59 | }
60 |
61 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
62 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
63 | if [[ "${ACTION}" == "install" ]]; then
64 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
65 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
66 | fi
67 | rm -f "$RESOURCES_TO_COPY"
68 |
69 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
70 | then
71 | case "${TARGETED_DEVICE_FAMILY}" in
72 | 1,2)
73 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
74 | ;;
75 | 1)
76 | TARGET_DEVICE_ARGS="--target-device iphone"
77 | ;;
78 | 2)
79 | TARGET_DEVICE_ARGS="--target-device ipad"
80 | ;;
81 | *)
82 | TARGET_DEVICE_ARGS="--target-device mac"
83 | ;;
84 | esac
85 |
86 | # Find all other xcassets (this unfortunately includes those of path pods and other targets).
87 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
88 | while read line; do
89 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then
90 | XCASSET_FILES+=("$line")
91 | fi
92 | done <<<"$OTHER_XCASSETS"
93 |
94 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
95 | fi
96 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Target Support Files/Pods-Brainwaves/Pods-Brainwaves-umbrella.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 |
4 | FOUNDATION_EXPORT double Pods_BrainwavesVersionNumber;
5 | FOUNDATION_EXPORT const unsigned char Pods_BrainwavesVersionString[];
6 |
7 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Target Support Files/Pods-Brainwaves/Pods-Brainwaves.debug.xcconfig:
--------------------------------------------------------------------------------
1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
2 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
3 | OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/Alamofire.framework/Headers"
4 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire"
5 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
6 | PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-Brainwaves
7 | PODS_ROOT = ${SRCROOT}/Pods
--------------------------------------------------------------------------------
/Brainwaves/Pods/Target Support Files/Pods-Brainwaves/Pods-Brainwaves.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_Brainwaves {
2 | umbrella header "Pods-Brainwaves-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Brainwaves/Pods/Target Support Files/Pods-Brainwaves/Pods-Brainwaves.release.xcconfig:
--------------------------------------------------------------------------------
1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
2 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
3 | OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/Alamofire.framework/Headers"
4 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire"
5 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
6 | PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-Brainwaves
7 | PODS_ROOT = ${SRCROOT}/Pods
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Measuring Brainwaves
2 |
3 | [](https://github.com/nikhiljay/brainwaves/releases)
4 | 
5 | 
6 |
7 | This is my project for Advanced Authentic Research (AAR). Follow the progress of this project on my blog. This project uses emokit which is an open source driver used to access the Emotiv Device raw data.
8 |
9 | 
10 |
11 | ## Extracting the Raw Data
12 |
13 | 1) Download the repository
14 |
15 | ```
16 | $ git clone https://github.com/nikhiljay/brainwaves.git
17 | ```
18 |
19 | 2) Plug in your Emotiv's USB dongle.
20 |
21 | 3) Find the Serial Number of the Emotiv by downloading HIDAPI.
22 |
23 | ```
24 | $ git clone https://github.com/signal11/hidapi.git
25 | $ cd hidapi
26 | ```
27 |
28 | 4) In the HIDAPI go to the directory that corresponds to your operating system and run:
29 |
30 | ```
31 | $ make -f Makefile-manual
32 | ```
33 |
34 | 5) A hidtest file should be created in the same directory. Open the hidtest to run it. On linux, you must run this using sudo.
35 |
36 | 6) The output should be a list of devices that are connected to the computer. Look at the Emotiv device information and copy the Serial Number.
37 |
38 | 7) In the brianwaves project, go to the emokit directory.
39 |
40 | ```
41 | $ cd emokit/python/emokit
42 | ```
43 |
44 | 8) Open "emotiv.py" and paste the serial number on line 361 where it says:
45 |
46 | ```
47 | serial_number=""
48 | ```
49 |
50 | 10) Run the "emotiv.py" file.
51 |
52 | ```
53 | $ python emotiv.py
54 | ```
55 |
56 | 11) If there are any dependencies that need to be installed used the "pip" command.
57 |
58 | ```
59 | $ sudo pip install [missing dependency goes here]
60 | ```
61 |
62 | 12) Install all dependencies until the following error is produced:
63 |
64 | ```
65 | Traceback (most recent call last):
66 | File "emotiv.py", line 674, in
67 | a.setup()
68 | File "emotiv.py", line 432, in setup
69 | self.setup_darwin()
70 | File "emotiv.py", line 537, in setup_darwin
71 | hidraw = hid.device(0x21a1, 0x0001)
72 | File "hid.pyx", line 45, in hid.device.__cinit__ (hid.c:1280)
73 | ```
74 |
75 | 9) Turn on the Emotiv and try again. A succesful output should be printed:
76 |
77 | 
78 |
79 | These electrodes in the picture above represent certain parts of the brain shown here:
80 |
81 | 
82 |
83 | ## Displaying Data on an iOS Device
84 |
85 | After extracting the Emotiv data, I sent the data as a JSON file to a local server. Then, I created an iOS app and used Alamofire to get request the data from the server. I created the app so that it would display the raw data on the iOS device. Here is what it looks like so far:
86 |
87 | 
88 |
--------------------------------------------------------------------------------
/emokit/.gitignore:
--------------------------------------------------------------------------------
1 | *build*
2 | *.pyc
--------------------------------------------------------------------------------
/emokit/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required (VERSION 2.6)
2 | PROJECT(emokit)
3 |
4 | SET(BUILD_SHARED_LIBS false)
5 | IF($ENV{EMOKIT_BUILD_SHARED_LIBS})
6 | SET(BUILD_SHARED_LIBS true)
7 | ENDIF()
8 |
9 | SET(LIBEMOKIT_HEADERS
10 | ${CMAKE_SOURCE_DIR}/include/emokit/emokit.h
11 | )
12 |
13 | LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake_modules)
14 | SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
15 | SET(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib)
16 |
17 | FIND_PACKAGE(Mcrypt REQUIRED)
18 | FIND_PACKAGE(HIDAPI REQUIRED)
19 |
20 | SET(LIBS ${Mcrypt_LIBS} ${HIDAPI_LIBRARIES})
21 |
22 | IF(LINUX)
23 | SET(LIBS ${LIBS} udev)
24 | ELSEIF(APPLE)
25 | SET(LIBS ${LIBS} "-framework IOKit" "-framework CoreFoundation")
26 | ENDIF()
27 |
28 |
29 | MESSAGE(STATUS ${LIBS})
30 | INCLUDE_DIRECTORIES(${HIDAPI_INCLUDE_DIR} ${Mcrypt_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/include)
31 |
32 | ADD_SUBDIRECTORY(src)
33 | ADD_SUBDIRECTORY(examples/emokitd)
34 | ADD_SUBDIRECTORY(examples/contact)
35 | ADD_SUBDIRECTORY(examples/emokit_osc)
36 |
37 | ##########################################
38 | ## PKGCONFIG file ###
39 | ##########################################
40 |
41 | IF(LINUX)
42 | IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/emokit.pc.in")
43 | MESSAGE(STATUS "configured ${CMAKE_CURRENT_SOURCE_DIR}/emokit.pc.in --> ${CMAKE_CURRENT_BINARY_DIR}/emokit.pc")
44 | CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/emokit.pc.in
45 | ${CMAKE_CURRENT_BINARY_DIR}/emokit.pc
46 | @ONLY )
47 |
48 | INSTALL(FILES
49 | ${CMAKE_CURRENT_BINARY_DIR}/emokit.pc
50 | DESTINATION lib/pkgconfig
51 | )
52 | ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/emokit.pc.in")
53 | ENDIF()
54 |
--------------------------------------------------------------------------------
/emokit/FAQ.md:
--------------------------------------------------------------------------------
1 | Emokit FAQ
2 | ==========
3 |
4 | * What data does emokit give me?
5 |
6 | The raw channels of the headset
7 |
8 | Battery power of the headset (in development at time of FAQ writing)
9 |
10 | Signal quality of each connection on the headset (in development at time of FAQ writing)
11 |
12 | * What data does emokit not give me?
13 |
14 | Processed data that can tell you moods or muscles or whatever.
15 |
16 | Basically, if you aren't up to doing a bit of DSP and aren't really
17 | educated in mathematics and neuroscience, you should use emokit under
18 | another library that will do the geekery for you. We publish emokit as
19 | a low level access tool, nothing more.
20 |
21 | * Does emokit work with all emotiv headsets?
22 |
23 | As far as we know, yes. If it doesn't work with yours, file an issue
24 | on the github project (http://github.com/openyou/emokit/issues)
25 |
26 | * I heard you need to know your key or something?
27 |
28 | That doesn't apply anymore. Emokit should work with all headsets and
29 | dongles. If it doesn't, file an issue (http://github.com/openyou/emokit/issues).
30 |
31 | * So I really don't need to know my key or whatever now?
32 |
33 | You shouldn't. It should "just work". So please stop asking.
34 |
35 | * OPTIONAL READING: The history of the key generation, and why you used to need keys
36 |
37 | When emokit first came out (For more information on this, check out
38 | Announcement.md in the doc directory), we only knew part of how the
39 | encryption worked, mainly because Daeken finished the first round,
40 | qDot took things over, and then neither of them had time to do
41 | anything for a while. So there was a lot of news that went around of
42 | "only certain headsets/keys work", so on and so forth.
43 |
44 | We managed to get lucky with the method for a while, because Emotiv
45 | was reusing keys on USB dongles, so one key would work for many
46 | headsets. Once Emotiv learned of this, they just had to switch out the
47 | firmware flashing on their keys, and emokit no longer worked.
48 |
49 | In late 2011, Daeken finished the key generation code, which means
50 | emokit should now work for any USB key. Note that the encryption
51 | happens on the USB KEY, not the headset. So it's actually tied to
52 | whatever you have plugged in regardless of the headset.
53 |
54 |
--------------------------------------------------------------------------------
/emokit/INSTALL:
--------------------------------------------------------------------------------
1 | Installation instructions for Linux (assuming ubuntu/debian packages)
2 |
3 |
4 | CMAKE
5 | Download : http://www.cmake.org/cmake/resources/software.html
6 | Go in the download folder and execute :
7 |
8 | To install cmake you need a working C++ compiler
9 | sudo apt-get install g++
10 |
11 | tar xzvf cmake-2.8.10.2.tar.gz
12 | cd cmake-2.8.10.2.tar.gz
13 | ./bootstrap
14 | make
15 | sudo make install
16 |
17 |
18 | MCRYPT
19 | First install the dependencies :
20 | sudo apt-get install libmcrypt-dev libmhash-dev git
21 |
22 | Download : http://sourceforge.net/projects/mcrypt/files/latest/download
23 | Go in the download folder and execute :
24 |
25 | tar xzvf mcrypt-2.6.8.tar.gz
26 | cd mcrypt-2.6.8/
27 | ./configure
28 | make
29 | make install
30 |
31 |
32 | HIPAPI
33 | First install the dependencies :
34 | sudo apt-get install libudev-dev libusb-1.0-0-dev libtool dh-autoreconf
35 |
36 | Download : https://github.com/signal11/hidapi/archive/master.zip
37 | IT WILL NOT WORK if you downloaded from: hidapi-0.7.0.zip from https://github.com/signal11/hidapi/downloads or the command git clone git://github.com/signal11/hidapi.git
38 | Extract the zip file and use the following commands :
39 |
40 | unzip hidapid-master.zip
41 | cd hidapid-master
42 | ./bootstrap
43 | ./configure
44 | make
45 | sudo make install
46 |
47 |
48 | EMOKIT
49 | Download https://github.com/openyou/emokit/archive/master.zip
50 |
51 | unzip emokit-master.zip
52 | cd emokit-master
53 | cmake .
54 | make
55 |
56 | This will build a static library. If you want to build a shared library
57 | instead, set the environment variable EMOKIT_BUILD_SHARED_LIBS.
58 |
59 | If you get:
60 | $ cmake .
61 | -- Found mcrypt: /usr/lib/libmcrypt.so
62 | -- Found HIDAPI: /usr/local/lib/libhidapi-hidraw.so
63 | -- /usr/lib/libmcrypt.so/usr/local/lib/libhidapi-hidraw.so
64 | -- oscpack NOT found.
65 | -- oscpack not found, not building emokit osc server
66 | -- Configuring done
67 | -- Generating done
68 | -- Build files have been written to: /emokit-master
69 |
70 | sudo apt-get install liboscpack*
71 |
72 | $ cmake .
73 | -- Found mcrypt: /usr/lib/libmcrypt.so
74 | -- /usr/lib/libmcrypt.so/usr/local/lib/libhidapi-hidraw.so
75 | -- Found oscpack: /usr/lib/liboscpack.so
76 | -- Configuring done
77 | -- Generating done
78 | -- Build files have been written to: /emokit-master
79 |
80 | If you try to run a python example and get
81 | ImportError: No module named gevent
82 |
83 | sudo pip install gevent
84 | sudo pip install greenlet
85 |
--------------------------------------------------------------------------------
/emokit/LICENSE:
--------------------------------------------------------------------------------
1 | Aes.py copyright 2001 Bram Cohen and released into the public domain.
2 |
3 | Everything else:
4 |
5 | In countries where it's respected, everything is released into the
6 | public domain; otherwise it's released under the following terms:
7 |
8 | Copyright (c) 2010-2012, Cody Brocious, Kyle Machulis/Nonpolynomial Labs
9 |
10 | All rights reserved.
11 |
12 | Redistribution and use in source and binary forms, with or without
13 | modification, are permitted provided that the following conditions are met:
14 | * Redistributions of source code must retain the above copyright
15 | notice, this list of conditions and the following disclaimer.
16 | * Redistributions in binary form must reproduce the above copyright
17 | notice, this list of conditions and the following disclaimer in the
18 | documentation and/or other materials provided with the distribution.
19 | * The names of its contributors may not be used to endorse or promote products
20 | derived from this software without specific prior written permission.
21 |
22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 | DISCLAIMED. IN NO EVENT SHALL Cody Brocious BE LIABLE FOR ANY
26 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/emokit/README.md:
--------------------------------------------------------------------------------
1 | Emokit
2 | ======
3 |
4 | Reverse engineering and original code written by
5 |
6 | * Cody Brocious (http://github.com/daeken)
7 | * Kyle Machulis (http://github.com/qdot)
8 |
9 | Contributions by
10 |
11 | * Severin Lemaignan - Base C Library and mcrypt functionality
12 | * Sharif Olorin (http://github.com/fractalcat) - hidapi support
13 | * Bill Schumacher (http://github.com/bschumacher) - Fixed the Python library
14 |
15 | Description
16 | ===========
17 |
18 | Emokit is a set of language for user space access to the raw stream
19 | data from the Emotiv EPOC headset. Note that this will not give you
20 | processed data (i.e. anything available in the Emo Suites in the
21 | software), just the raw sensor data.
22 |
23 | The C library is backed by hidapi, and should work on any platform
24 | that hidapi also works on.
25 |
26 | Information
27 | ===========
28 |
29 | FAQ (READ BEFORE FILING ISSUES): https://github.com/openyou/emokit/blob/master/FAQ.md
30 |
31 | If you have a problem not covered in the FAQ, file it as an
32 | issue on the github project.
33 |
34 | PLEASE DO NOT EMAIL OR OTHERWISE CONTACT THE DEVELOPERS DIRECTLY.
35 | Seriously. I'm sick of email and random facebook friendings asking for
36 | help. What happens on the project stays on the project.
37 |
38 | Issues: http://github.com/openyou/emokit/issues
39 |
40 | If you are using the Python library and a research headset you may have
41 | to change the is_research variable in emotiv.py's setup_crypto function.
42 |
43 | Required Libraries
44 | ==================
45 |
46 | Python
47 | ------
48 |
49 | * pywinhid (Windows Only) - https://pypi.python.org/pypi/pywinusb/
50 | * (OS X) HIDAPI - http://www.signal11.us/oss/hidapi/
51 | * (OS X) cython-hidapi - https://github.com/gbishop/cython-hidapi
52 | * pycrypto - https://www.dlitz.net/software/pycrypto/
53 | * gevent - http://gevent.org
54 | * realpath - http://? sudo apt-get install realpath
55 |
56 | C Language
57 | ----------
58 |
59 | * CMake - http://www.cmake.org
60 | * libmcrypt - https://sourceforge.net/projects/mcrypt/
61 | * hidapi - http://www.signal11.us/oss/hidapi/
62 |
63 | Usage
64 | =====
65 |
66 | C library
67 | ---------
68 |
69 | See emokitd.c example
70 |
71 | Python library
72 | --------------
73 |
74 | Code:
75 |
76 | import emotiv
77 | import platform
78 | if platform.system() == "Windows":
79 | import socket
80 | import gevent
81 |
82 | if __name__ == "__main__":
83 | headset = emotiv.Emotiv()
84 | gevent.spawn(headset.setup)
85 | gevent.sleep(0)
86 | try:
87 | while True:
88 | packet = headset.dequeue()
89 | print packet.gyro_x, packet.gyro_y
90 | gevent.sleep(0)
91 | except KeyboardInterrupt:
92 | headset.close()
93 | finally:
94 | headset.close()
95 |
96 |
97 | Bindings
98 | ========
99 |
100 | Go: https://github.com/fractalcat/emogo
101 |
102 | Platform Specifics Issues
103 | =========================
104 |
105 | Linux
106 | -----
107 |
108 | Due to the way hidapi works, the linux version of emokit can run using
109 | either hidraw calls or libusb. These will require different udev rules
110 | for each. We've tried to cover both (as based on hidapi's example udev
111 | file), but your mileage may vary. If you have problems, please post
112 | them to the github issues page (http://github.com/openyou/emokit/issues).
113 |
114 | Your kernel may not support /dev/hidraw devices by default, such as an RPi.
115 | To fix that re-comiple your kernel with /dev/hidraw support
116 |
117 | OS X
118 | ----
119 | Recent OS versions no longer allow usb devices to become unclaimed by the kernel.
120 | You must use a HIDAPI library.
121 |
122 | The render.py file uses pygame, visit http://pygame.org/wiki/MacCompile
123 | Do not export the architecture compiler flags for recent 64bit versions of OS X.
124 |
125 |
126 | Credits - Cody
127 | ==============
128 |
129 | Huge thanks to everyone who donated to the fund drive that got the
130 | hardware into my hands to build this.
131 |
132 | Thanks to Bryan Bishop and the other guys in #hplusroadmap on Freenode
133 | for your help and support.
134 |
135 | And as always, thanks to my friends and family for supporting me and
136 | suffering through my obsession of the week.
137 |
138 | Credits - Kyle
139 | ==============
140 |
141 | Kyle would like to thank Cody for doing the hard part.
142 |
143 | He would also like to thank emotiv for putting emo on the front of
144 | everything because it's god damn hilarious. I mean, really, Emo
145 | Suites? Saddest hotel EVER.
146 |
147 | # Frequently asked questions
148 |
149 | - *What unit is the data I'm getting back in? How do I get volts out of
150 | it?*
151 |
152 | One least-significant-bit of the fourteen-bit value you get back is
153 | 0.51 microvolts. See the
154 | [specification](http://emotiv.com/upload/manual/EPOCSpecifications.pdf)
155 | for more details.
--------------------------------------------------------------------------------
/emokit/cmake_modules/FindHIDAPI.cmake:
--------------------------------------------------------------------------------
1 | # - try to find HIDAPI library
2 | # from http://www.signal11.us/oss/hidapi/
3 | #
4 | # Cache Variables: (probably not for direct use in your scripts)
5 | # HIDAPI_INCLUDE_DIR
6 | # HIDAPI_LIBRARY
7 | #
8 | # Non-cache variables you might use in your CMakeLists.txt:
9 | # HIDAPI_FOUND
10 | # HIDAPI_INCLUDE_DIRS
11 | # HIDAPI_LIBRARIES
12 | #
13 | # Requires these CMake modules:
14 | # FindPackageHandleStandardArgs (known included with CMake >=2.6.2)
15 | #
16 | # Original Author:
17 | # 2009-2010 Ryan Pavlik
18 | # http://academic.cleardefinition.com
19 | # Iowa State University HCI Graduate Program/VRAC
20 | #
21 | # Copyright Iowa State University 2009-2010.
22 | # Distributed under the Boost Software License, Version 1.0.
23 | # (See accompanying file LICENSE_1_0.txt or copy at
24 | # http://www.boost.org/LICENSE_1_0.txt)
25 |
26 | find_library(HIDAPI_LIBRARY
27 | NAMES hidapi hidapi-hidraw hidapi-libusb)
28 |
29 | find_path(HIDAPI_INCLUDE_DIR
30 | NAMES hidapi/hidapi.h)
31 |
32 | include(FindPackageHandleStandardArgs)
33 | find_package_handle_standard_args(HIDAPI
34 | DEFAULT_MSG
35 | HIDAPI_LIBRARY
36 | HIDAPI_INCLUDE_DIR)
37 |
38 | if(HIDAPI_FOUND)
39 | set(HIDAPI_LIBRARIES "${HIDAPI_LIBRARY}")
40 |
41 | set(HIDAPI_INCLUDE_DIRS "${HIDAPI_INCLUDE_DIR}")
42 | endif()
43 |
44 | mark_as_advanced(HIDAPI_INCLUDE_DIR HIDAPI_LIBRARY)
45 |
--------------------------------------------------------------------------------
/emokit/cmake_modules/FindMcrypt.cmake:
--------------------------------------------------------------------------------
1 | # - Find Mcrypt (a cross platform RPC lib/tool)
2 | # This module defines
3 | # Mcrypt_INCLUDE_DIR, where to find Mcrypt headers
4 | # Mcrypt_LIBS, Mcrypt libraries
5 | # Mcrypt_FOUND, If false, do not try to use Mcrypt
6 |
7 | find_path(Mcrypt_INCLUDE_DIR mcrypt.h PATHS
8 | /usr/local/include
9 | /opt/local/include
10 | )
11 |
12 |
13 | #find_library can't seem to find a 64-bit binary if the 32-bit isn't there
14 |
15 | set(Mcrypt_LIB_PATHS /usr/local/lib /opt/local/lib /usr/lib64)
16 | find_library(Mcrypt_LIB NAMES mcrypt PATHS ${Mcrypt_LIB_PATHS})
17 |
18 | if (Mcrypt_LIB AND Mcrypt_INCLUDE_DIR)
19 | set(Mcrypt_FOUND TRUE)
20 | set(Mcrypt_LIBS ${Mcrypt_LIB})
21 | else ()
22 | set(Mcrypt_FOUND FALSE)
23 | endif ()
24 |
25 | if (Mcrypt_FOUND)
26 | if (NOT Mcrypt_FIND_QUIETLY)
27 | message(STATUS "Found mcrypt: ${Mcrypt_LIBS}")
28 | endif ()
29 | else ()
30 | if (Mcrypt_FIND_REQUIRED)
31 | message(FATAL_ERROR "Could NOT find mcrypt library.")
32 | endif ()
33 | message(STATUS "mcrypt NOT found.")
34 | endif ()
35 |
36 | mark_as_advanced(
37 | Mcrypt_LIB
38 | Mcrypt_INCLUDE_DIR
39 | )
40 |
--------------------------------------------------------------------------------
/emokit/cmake_modules/Findlibusb-1.0.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find libusb-1.0
2 | # Once done this will define
3 | #
4 | # LIBUSB_1_FOUND - system has libusb
5 | # LIBUSB_1_INCLUDE_DIRS - the libusb include directory
6 | # LIBUSB_1_LIBRARIES - Link these to use libusb
7 | # LIBUSB_1_DEFINITIONS - Compiler switches required for using libusb
8 | #
9 | # Adapted from cmake-modules Google Code project
10 | #
11 | # Copyright (c) 2006 Andreas Schneider
12 | #
13 | # (Changes for libusb) Copyright (c) 2008 Kyle Machulis
14 | #
15 | # Redistribution and use is allowed according to the terms of the New BSD license.
16 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
17 | #
18 |
19 |
20 | if (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
21 | # in cache already
22 | set(LIBUSB_FOUND TRUE)
23 | else (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
24 | find_path(LIBUSB_1_INCLUDE_DIR
25 | NAMES
26 | libusb.h
27 | PATHS
28 | /usr/include
29 | /usr/local/include
30 | /opt/local/include
31 | /sw/include
32 | PATH_SUFFIXES
33 | libusb-1.0
34 | )
35 |
36 | find_library(LIBUSB_1_LIBRARY
37 | NAMES
38 | usb-1.0
39 | PATHS
40 | /usr/lib
41 | /usr/local/lib
42 | /opt/local/lib
43 | /sw/lib
44 | )
45 |
46 | set(LIBUSB_1_INCLUDE_DIRS
47 | ${LIBUSB_1_INCLUDE_DIR}
48 | )
49 | set(LIBUSB_1_LIBRARIES
50 | ${LIBUSB_1_LIBRARY}
51 | )
52 |
53 | if (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
54 | set(LIBUSB_1_FOUND TRUE)
55 | endif (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
56 |
57 | if (LIBUSB_1_FOUND)
58 | if (NOT libusb_1_FIND_QUIETLY)
59 | message(STATUS "Found libusb-1.0:")
60 | message(STATUS " - Includes: ${LIBUSB_1_INCLUDE_DIRS}")
61 | message(STATUS " - Libraries: ${LIBUSB_1_LIBRARIES}")
62 | endif (NOT libusb_1_FIND_QUIETLY)
63 | else (LIBUSB_1_FOUND)
64 | if (libusb_1_FIND_REQUIRED)
65 | message(FATAL_ERROR "Could not find libusb")
66 | endif (libusb_1_FIND_REQUIRED)
67 | endif (LIBUSB_1_FOUND)
68 |
69 | # show the LIBUSB_1_INCLUDE_DIRS and LIBUSB_1_LIBRARIES variables only in the advanced view
70 | mark_as_advanced(LIBUSB_1_INCLUDE_DIRS LIBUSB_1_LIBRARIES)
71 |
72 | endif (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
--------------------------------------------------------------------------------
/emokit/doc/Announcement.md:
--------------------------------------------------------------------------------
1 | Intro
2 | =====
3 |
4 | I've been interested in the [Emotiv EPOC](http://emotiv.com/) headset for a while; a $300 14-sensor EEG. It's intended for gaming, but it's quite high quality. There's a research SDK available for $750, but it's Windows-only and totally proprietary. I decided to hack it, and open the consumer headset up to development. Thanks to [donations](http://pledgie.com/campaigns/12906) I got some hardware in hand this weekend.
5 |
6 | I'm happy to announce the Emokit project, an open source interface to the EPOC. The goal is to open it up to development and enable new products and research. For the first time, we have access to a high-quality EEG for $300 -- this is huge.
7 |
8 | Code
9 | ====
10 |
11 | The code is available on github on the [daeken/Emokit](http://github.com/daeken/Emokit) repository. There's a Python library for interacting with the EPOC, as well as a renderer that will graph the sensor data.
12 |
13 | 
14 |
15 | Where things are right now
16 | ==========================
17 |
18 | You can access raw EEG data from the Emotiv EPOC on Windows, Linux, and OS X from Python. Sensor locations can be found at https://github.com/bschumacher/emokit-1/wiki/Sensor-Locations. Word of warning: this project is less than 48 hours old (I just got hardware in my hands Saturday night) and has only been run by me on Windows due to a dead Linux box. It's very much alpha quality right now -- don't trust it.
19 |
20 | How it happened
21 | ===============
22 |
23 | The first step was to figure out how exactly the PC communicates with it. This part was straightforward; it's a USB device with VID=21A1, PID=0001 (note: from walking through the device enum code in the EDK, it seems that PID=0002 might be the development headset, but that's totally unverified). It presents two HID interfaces, "EPOC BCI" and "Brain Waves". Reading data off the "Brain Waves" interface gives you reports of 32 bytes at a time; "EPOC BCI" I'm unsure about.
24 |
25 | Next step was to read some data off the wire and figure out what's going on. I utilized the pywinusb.hid library for this. It was immediately apparent that it's encrypted, so figuring out what the crypto was became the top priority. This took a couple hours due to a few red herrings and failed approaches, but here's what it boiled down to:
26 |
27 | - Throw EmotivControlPanel.exe into IDA.
28 | - Throw EmotivControlPanel.exe into PeID and run the Krypto Analyzer plugin on it.
29 | - You'll see a Rijndael S-Box (used for AES encryption and key schedule initialization) come up from KAnal.
30 | - Using IDA, go to the S-Box address.
31 | - You'll see a single function that references the S-Box -- this is the key initialization code (*not* encryption, as I originally thought).
32 | - Use a debugger (I used the debugger built into IDA for simplicity's sake) and attach to the beginning of the key init function.
33 | - You'll see two arguments: a 16-byte key and an integer containing `16`.
34 |
35 | So that you don't have to do that yourself, here's the key: 31003554381037423100354838003750 or `1\x005T8\x107B1\x005H8\x007P`. Given that, decrypting the data is trivial: it's simply 128-bit AES in ECB mode, block size of 16 bytes.
36 |
37 | The first byte of each report is a counter that goes from 0-127 then to 233, then cycles back to 0. Once this was determined, I figured out the gyro data. To do that, I broke out pygame and wrote a simple app that drew a rectangle at the X and Y coords coming from two bytes of the records. I pretty quickly figured out that the X coord from the gyro is byte 29 and the Y coord is byte 30. The EPOC has some sort of logic in it to reset the gyro baseline levels, but I'm not sure on the details there; the baseline I'm seeing generally (not perfect) is roughly 102 for X and 204 for Y. This lets you get control from the gyro fairly easy.
38 |
39 | That accounts for 3 bytes of the packet, but we have 14 sensors. If you assume that each sensor is represented by 2 bytes of data, that gives us 28 bytes for sensor data. 32 - 28 == 4, so what's the extra byte? Looking at byte 15, it's pretty clear that it's (almost) always zero -- the only time it's non-zero is the very first report from the device. I have absolutely no idea what this is.
40 |
41 | From here, all we have is data from the sensors. Another quick script with pygame and boom, we have a graph renderer for this data.
42 |
43 | However, here's where it gets tough. Figuring out which bytes correspond to which sensors is difficult, because effectively all the signal processing and filtering happens on the PC side, meaning it's not in this library yet. Figuring out the high bytes (which are less noisy and change less frequently) isn't terribly difficult, and I've identified a few of them, but there's a lot of work to be done still.
44 |
45 | What needs to be done
46 | =====================
47 |
48 | Reversing-wise:
49 |
50 | - Determine which bytes correspond to which signals -- I'm sure someone more knowledgable than myself can do this no problem
51 | - Figure out how the sensor quality is transmitted -- according to some data on the research SDK, there's 4 bits per sensor that give you the signal quality (0=none, 1=very poor, 2=poor, 3=decent, 4=good, 5=very good)
52 | - Figure out how to read the battery meter
53 |
54 | Emokit-wise:
55 |
56 | - Linux and OS X support haven't been tested at all, but they should be good to go
57 | - Build a C library for working with the EPOC
58 | - Build an acquisition module for [OpenViBE](http://openvibe.inria.fr/)
59 |
60 | Get involved
61 | ================
62 |
63 | Contact us
64 | ----------
65 |
66 | I've started the [#emokit channel on Freenode](irc://irc.freenode.net/emokit) and I'm idling there (nick=Daeken).
67 |
68 | How you can help
69 | ----------------
70 |
71 | I'm about to get started on an acquisition module for OpenViBE, but someone more knowledgable than myself could probably do this far more quickly. However, the reversing side of things -- particularly figuring out the sensor bytes -- would be much more useful.
72 |
73 | Summary
74 | =======
75 |
76 | I hope that the Emokit project will open new research that was never possible before, and I can't wait to see what people do with this. Let me know if you have any questions or comments.
77 |
78 | Happy Hacking,
79 | - Cody Brocious (Daeken)
80 |
--------------------------------------------------------------------------------
/emokit/doc/emotiv_protocol.asciidoc:
--------------------------------------------------------------------------------
1 | = Emotiv EEG Protocol Documentation
2 |
3 | By Daeken, Eguru, qDot
4 | Version 1.0, 2012-05-26
5 |
6 | == Introduction
7 |
8 | This document gives an overview of the communications and obfuscation
9 | mechanisms for the Emotiv EEG Headset. It covers the raw data
10 | transmission protocols, as well as the techniques used to lock down
11 | the system.
12 |
13 | This document does not cover the inner working of any of the Emotiv
14 | SDK or Suites used on top of the raw data. It exists mainly for those
15 | interested in doing research with raw wave processing software such as
16 | OpenVibe and BrainBay.
17 |
18 | == Communications Mechanisms
19 |
20 | The Emotiv EEG communicates via a proprietary wireless protocol to a
21 | USB dongle hooked to the host computer. The USB dongle identifies as a
22 | USB HID device, emitting 32-byte reports at a rate of 128hz when the
23 | headset is on and in range. No data is ever written to the dongle or
24 | head, only read from them.
25 |
26 | Each report contains the following information:
27 |
28 | * Packet Counter
29 | * Battery Level
30 | * Contact Quality
31 | * Contact Sensor Readings
32 | * Gyro Sensor Readings
33 |
34 | == Cryptography
35 |
36 | === Information and History
37 |
38 | To ensure that raw data is only read by those that have paid for the
39 | raw data license, each USB dongle encrypts incoming wireless data via
40 | AES against a key composed of the Serial Number (relayed in the USB
41 | feature report descriptor for the HID endpoint) of the dongle before
42 | emitting it as an HID report. It is assumed that data coming to the
43 | dongle from the wireless protocol is unencrypted, and all encryption
44 | happens on the dongle.
45 |
46 | While one would figure that dongles would have unique serials, this
47 | was not necessarily the case for the first year or so of emotiv
48 | development, and cracked decryption keys could be passed around as
49 | long as serials for USB dongles matched. However, later headsets now
50 | have unique serials per USB dongle.
51 |
52 | Initial key extraction techniques can be found at "Announcement.md"
53 | documentation in the emokit repository.
54 |
55 | === Key Strategy
56 |
57 | To create a 128-bit key to decrypt incoming data from the usb dongle,
58 | we first need to request a feature report from the device that
59 | contains whether the device is a consumer or research headset. This
60 | fact changes the makeup of the key.
61 |
62 | Serial numbers are fetched via the feature report for the HID
63 | endpoint. Serial numbers are 16 byte strings of the format:
64 |
65 | -------
66 | SNXXXXXXXXXXYYYY
67 | -------
68 |
69 | Where Xs and Ys are usually numbers. The last 4 characters of the
70 | serial number are what are used to create the key. It's interesting to
71 | note that sometimes serials have dates embedded in them, i.e.
72 |
73 | -------
74 | SN20120526998912
75 | -------
76 |
77 | The date is probably the day the usb dongle was flashed.
78 |
79 | For the research headset, the key is composed of the following values:
80 |
81 | -------
82 | [15] 0x00 [14] 0x54 [13] 0x10 [12] 0x42 [15] 0x00 [14] 0x48 [13] 0x00 [12] 0x50
83 | -------
84 |
85 | For the consumer headset, the key is composed of the following values:
86 |
87 | -------
88 | [15] 0x00 [14] 0x48 [13] 0x00 [12] 0x54 [15] 0x10 [14] 0x42 [13] 0x00 [12] 0x50
89 | -------
90 |
91 | Where the numbers in brackets are indexes of the serial string
92 | retrieved from the USB feature report descriptor. So for instance, if
93 | a serial number for a consumer headset is
94 |
95 | -------
96 | SN20120526998912
97 | -------
98 |
99 | The characters we're interested in are the last 4:
100 |
101 | -------
102 | 8 [0x38] 9 [0x39] 1 [0x31] 2 [0x32]
103 | -------
104 |
105 | Then the resulting crypto key will be
106 |
107 | -------
108 | 0x32 0x00 0x31 0x48 0x39 0x00 0x38 0x54 0x32 0x10 0x31 0x42 0x39 0x00 0x38 0x50
109 | -------
110 |
111 | == Packet Analysis
112 |
113 | 32-byte packets are received from the USB device at 128hz. Update
114 | rates within that packet are:
115 |
116 | * Sensor Data - 128hz
117 | * Gyro Data - 128hz
118 | * Battery - 1hz
119 | * Sensor Quality - 1hz-16hz (Depending on sensor)
120 |
121 | === Packet Layout
122 |
123 | An Overview of the 256-bit Packet Layout:
124 |
125 | |=============================
126 | | Bit Indexes | Used for
127 | | 0:7 | Counter/Battery
128 | | 8:21 | F3 Data
129 | | 22:35 | FC5 Data
130 | | 36:49 | AF3 Data
131 | | 50:63 | F7 Data
132 | | 64:77 | T7 Data
133 | | 78:91 | P7 Data
134 | | 92:105 | O1 Data
135 | | 107:120 | Connection Quality (Rotating)
136 | | 121:133 | ?
137 | | 134:147 | O2 Data
138 | | 148:161 | P8 Data
139 | | 162:175 | T8 Data
140 | | 176:189 | F8 Data
141 | | 190:203 | AF4 Data
142 | | 204:217 | FC6 Data
143 | | 218:231 | F4 Data
144 | | 233:239 | Gyro X
145 | | 240:247 | Gyro Y
146 | | 248:255 | ?
147 | |=============================
148 |
149 | === Counter and Battery
150 |
151 | The first byte of each packet can denote one of two things: the packet
152 | count, or the battery power level.
153 |
154 | Packet count makes up the lower 7 bits of the first byte. If the
155 | highest bit is a 1, then the battery level is being relayed. This
156 | happens once per second.
157 |
158 | Packet count goes from 0-127, then transmits a battery power packet,
159 | then wraps back to 0. This can be used to detect dropped packets. The
160 | battery power packet will always have the highest bit set to 1.
161 |
162 | Battery count is read via this table:
163 |
164 | |============================
165 | | Value | Battery Level (%)
166 | | >= 248 | ~100
167 | | 247 | 99.93
168 | | 246 | 97.02
169 | | 245 | 93.40
170 | | 244 | 89.45
171 | | 243 | 85.23
172 | | 242 | 81.89
173 | | 241 | 76.77
174 | | 240 | 71.54
175 | | 239 | 66.59
176 | | 238 | 61.92
177 | | 237 | 55.37
178 | | 236 | 45.93
179 | | 235 | 32.34
180 | | 234 | 20.43
181 | | 233 | 12.37
182 | | 232 | 5.08
183 | | 231 | 3.63
184 | | 230 | 2.80
185 | | 229 | 2.05
186 | | 228 | 1.42
187 | | 227 | 0.88
188 | | 226 | 0.42
189 | | 225 | 0
190 | | < 225 | ~0
191 | |============================
192 |
193 | === Contact Readings
194 |
195 | Readings from the contacts are available as 14 bit values, with each
196 | sensor sending at 128hz. The values are interspered throughout the
197 | packet. See the Packet Layout section for which sensors are covered by
198 | each bit range.
199 |
200 | === Contact Quality
201 |
202 | Contact quality consists of 14 bits, and refers to the contact quality
203 | of the sensor as an amplitude of its calibration signal. The sensor
204 | context of the field changes based on the value of the packet counter
205 | in the first byte. For instance, a counter value of 1 means the packet
206 | is showing the quality for sensor FC5, while a counter value of 2
207 | means that the packet is showing the quality for sensor AF3, and
208 | so on.
209 |
210 | The following list shows the order that the sensors are listed in, in
211 | relation to the counter, starting with counter = 0.
212 |
213 | |============================
214 | | Counter Index | Contact
215 | | 0 | F3
216 | | 1 | FC5
217 | | 2 | AF3
218 | | 3 | F7
219 | | 4 | T7
220 | | 5 | P7
221 | | 6 | O1
222 | | 7 | O2
223 | | 8 | P8
224 | | 9 | T8
225 | | 10 | F8
226 | | 11 | AF4
227 | | 12 | FC6
228 | | 13 | F4
229 | | 14 | F8
230 | | 15 | AF4
231 | | 16-63 | Unknown?
232 | | 64 | F3
233 | | 65 | FC5
234 | | 66 | AF3
235 | | 67 | F7
236 | | 68 | T7
237 | | 69 | P7
238 | | 70 | O1
239 | | 71 | O2
240 | | 72 | P8
241 | | 73 | T8
242 | | 74 | F8
243 | | 75 | AF4
244 | | 76 | FC6
245 | | 77 | F4
246 | | 78 | F8
247 | | 79 | AF4
248 | | 80 | FC6
249 | | .. | 77-80 Pattern repeats until counter hits 127
250 | |============================
251 |
252 | To get a useful reading, divide each readout by ~540. A value of
253 | 0.8-1.0 means a "good" contact.
254 |
255 | === Gyros
256 |
257 | Gyro readings are available for 2 axes (head turned left/right and
258 | foreward/back). These are 8-bit values that update at a rate of 128hz,
259 | with 7-bits of resolution on either side of the median point for the
260 | turn.
261 |
--------------------------------------------------------------------------------
/emokit/doc/usbinfo.txt:
--------------------------------------------------------------------------------
1 | Bus 002 Device 003: ID 21a1:0001
2 | Device Descriptor:
3 | bLength 18
4 | bDescriptorType 1
5 | bcdUSB 2.00
6 | bDeviceClass 0 (Defined at Interface level)
7 | bDeviceSubClass 0
8 | bDeviceProtocol 0
9 | bMaxPacketSize0 8
10 | idVendor 0x21a1
11 | idProduct 0x0001
12 | bcdDevice 0.03
13 | iManufacturer 1
14 | iProduct 2
15 | iSerial 3
16 | bNumConfigurations 1
17 | Configuration Descriptor:
18 | bLength 9
19 | bDescriptorType 2
20 | wTotalLength 59
21 | bNumInterfaces 2
22 | bConfigurationValue 1
23 | iConfiguration 0
24 | bmAttributes 0x80
25 | (Bus Powered)
26 | MaxPower 100mA
27 | Interface Descriptor:
28 | bLength 9
29 | bDescriptorType 4
30 | bInterfaceNumber 0
31 | bAlternateSetting 0
32 | bNumEndpoints 1
33 | bInterfaceClass 3 Human Interface Device
34 | bInterfaceSubClass 0 No Subclass
35 | bInterfaceProtocol 0 None
36 | iInterface 0
37 | HID Device Descriptor:
38 | bLength 9
39 | bDescriptorType 33
40 | bcdHID 1.11
41 | bCountryCode 33 US
42 | bNumDescriptors 1
43 | bDescriptorType 34 Report
44 | wDescriptorLength 20
45 | Report Descriptors:
46 | ** UNAVAILABLE **
47 | Endpoint Descriptor:
48 | bLength 7
49 | bDescriptorType 5
50 | bEndpointAddress 0x81 EP 1 IN
51 | bmAttributes 3
52 | Transfer Type Interrupt
53 | Synch Type None
54 | Usage Type Data
55 | wMaxPacketSize 0x0008 1x 8 bytes
56 | bInterval 1
57 | Interface Descriptor:
58 | bLength 9
59 | bDescriptorType 4
60 | bInterfaceNumber 1
61 | bAlternateSetting 0
62 | bNumEndpoints 1
63 | bInterfaceClass 3 Human Interface Device
64 | bInterfaceSubClass 0 No Subclass
65 | bInterfaceProtocol 0 None
66 | iInterface 4
67 | HID Device Descriptor:
68 | bLength 9
69 | bDescriptorType 33
70 | bcdHID 1.11
71 | bCountryCode 0 Not supported
72 | bNumDescriptors 1
73 | bDescriptorType 34 Report
74 | wDescriptorLength 28
75 | Report Descriptors:
76 | ** UNAVAILABLE **
77 | Endpoint Descriptor:
78 | bLength 7
79 | bDescriptorType 5
80 | bEndpointAddress 0x82 EP 2 IN
81 | bmAttributes 3
82 | Transfer Type Interrupt
83 | Synch Type None
84 | Usage Type Data
85 | wMaxPacketSize 0x0020 1x 32 bytes
86 | bInterval 1
87 | can't get device qualifier: Operation not permitted
88 | can't get debug descriptor: Operation not permitted
89 | cannot read device status, Operation not permitted (1)
90 |
--------------------------------------------------------------------------------
/emokit/examples/contact/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ##################################################
2 | # epoc contact #
3 | ##################################################
4 |
5 | add_executable (contact contact.c)
6 | ADD_DEPENDENCIES(contact emokit)
7 | target_link_libraries (contact emokit ${LIBS})
8 |
9 | SET_TARGET_PROPERTIES(contact PROPERTIES
10 | INSTALL_RPATH_USE_LINK_PATH TRUE
11 | INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib
12 | BUILD_WITH_INSTALL_RPATH TRUE )
13 |
14 | INSTALL (TARGETS contact
15 | RUNTIME DESTINATION bin
16 | )
17 |
--------------------------------------------------------------------------------
/emokit/examples/contact/contact.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Get real-time contact quality readings
4 |
5 | */
6 |
7 | #include
8 | #include
9 | #include
10 | #include "emokit/emokit.h"
11 |
12 | int quit;
13 | void cleanup(int i){
14 | fprintf(stdout,"Shutting down\n");
15 | quit=1;
16 | }
17 |
18 | int main(int argc, char **argv)
19 | {
20 | struct emokit_device* d;
21 | signal(SIGINT, cleanup); //trap cntrl c
22 |
23 |
24 | quit=0;
25 |
26 | d = emokit_create();
27 | int count=emokit_get_count(d, EMOKIT_VID, EMOKIT_PID);
28 | printf("Current epoc devices connected: %d\n", count );
29 | int r = emokit_open(d, EMOKIT_VID, EMOKIT_PID, 1);
30 | if(r != 0)
31 | {
32 | emokit_close(d);
33 | emokit_delete(d);
34 | d = emokit_create();
35 | r = emokit_open(d, EMOKIT_VID, EMOKIT_PID, 0);
36 | if (r!=0) {
37 | printf("CANNOT CONNECT: %d\n", r);
38 | return 1;
39 | }
40 | }
41 | printf("Connected to headset.\n");
42 |
43 | r = emokit_read_data_timeout(d,1000);
44 | if (r<=0) {
45 | if(r<0)
46 | fprintf(stderr, "Error reading from headset\n");
47 | else
48 | fprintf(stderr, "Headset Timeout...\n");
49 | emokit_close(d);
50 | emokit_delete(d);
51 | return 1;
52 | }
53 |
54 | struct emokit_frame c;
55 | while (!quit) {
56 | int err = emokit_read_data_timeout(d, 1000);
57 | if(err > 0) {
58 | c = emokit_get_next_frame(d);
59 | fprintf(stdout,"\033[H\033[2JPress CTRL+C to exit\n\nContact quality:\nF3 %4d\nFC6 %4d\nP7 %4d\nT8 %4d\nF7 %4d\nF8 %4d\nT7 %4d\nP8 %4d\nAF4 %4d\nF4 %4d\nAF3 %4d\nO2 %4d\nO1 %4d\nFC5 %4d",c.cq.F3, c.cq.FC6, c.cq.P7, c.cq.T8,c.cq.F7, c.cq.F8, c.cq.T7, c.cq.P8, c.cq.AF4, c.cq.F4, c.cq.AF3, c.cq.O2, c.cq.O1, c.cq.FC5);
60 | fflush(stdout);
61 | } else if(err == 0) {
62 | fprintf(stderr, "Headset Timeout...\n");
63 | }
64 | }
65 | emokit_close(d);
66 | emokit_delete(d);
67 | return 0;
68 | }
69 |
70 |
--------------------------------------------------------------------------------
/emokit/examples/emokit_osc/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
2 | FIND_PACKAGE(oscpack)
3 |
4 | IF(NOT oscpack_FOUND)
5 | MESSAGE(STATUS "oscpack not found, not building emokit osc server")
6 | ELSE()
7 | INCLUDE_DIRECTORIES(${oscpack_INCLUDE_DIR})
8 | ADD_EXECUTABLE(emokit_osc emokit_osc.cpp)
9 | ADD_DEPENDENCIES(emokit_osc emokit)
10 | TARGET_LINK_LIBRARIES(emokit_osc ${oscpack_LIBS} emokit ${LIBS})
11 | ENDIF()
12 |
--------------------------------------------------------------------------------
/emokit/examples/emokit_osc/Findoscpack.cmake:
--------------------------------------------------------------------------------
1 | # - Find Mcrypt (a cross platform RPC lib/tool)
2 | # This module defines
3 | # Mcrypt_INCLUDE_DIR, where to find Mcrypt headers
4 | # Mcrypt_LIBS, Mcrypt libraries
5 | # Mcrypt_FOUND, If false, do not try to use Mcrypt
6 |
7 | find_path(oscpack_INCLUDE_DIR oscpack/osc/OscTypes.h PATHS
8 | /usr/local/include
9 | /opt/local/include
10 | )
11 |
12 | #find_library can't seem to find a 64-bit binary if the 32-bit isn't there
13 |
14 | set(oscpack_LIB_PATHS /usr/local/lib /opt/local/lib /usr/lib64)
15 | find_library(oscpack_LIB NAMES oscpack PATHS ${oscpack_LIB_PATHS})
16 |
17 | if (oscpack_LIB AND oscpack_INCLUDE_DIR)
18 | set(oscpack_FOUND TRUE)
19 | set(oscpack_LIBS ${oscpack_LIB})
20 | else ()
21 | set(oscpack_FOUND FALSE)
22 | endif ()
23 |
24 | if (oscpack_FOUND)
25 | if (NOT oscpack_FIND_QUIETLY)
26 | message(STATUS "Found oscpack: ${oscpack_LIBS}")
27 | endif ()
28 | else ()
29 | if (oscpack_FIND_REQUIRED)
30 | message(FATAL_ERROR "Could NOT find oscpack library.")
31 | endif ()
32 | message(STATUS "oscpack NOT found.")
33 | endif ()
34 |
35 | mark_as_advanced(
36 | oscpack_LIB
37 | oscpack_INCLUDE_DIR
38 | )
39 |
--------------------------------------------------------------------------------
/emokit/examples/emokit_osc/emokit_osc.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Simple example of sending an OSC message using oscpack.
3 | */
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include "oscpack/osc/OscOutboundPacketStream.h"
11 | #include "oscpack/ip/UdpSocket.h"
12 | #include "emokit/emokit.h"
13 |
14 | #define ADDRESS "127.0.0.1"
15 | #define PORT 9997
16 |
17 | #define OUTPUT_BUFFER_SIZE 4096
18 |
19 | void sigproc(int i)
20 | {
21 | std::cout << "closing epoc and quitting" << std::endl;
22 | exit(0);
23 | }
24 |
25 | float conv(int v)
26 | {
27 | return (v-8200)/8200.0;
28 | }
29 |
30 | int main(int argc, char* argv[])
31 | {
32 | signal(SIGINT, sigproc);
33 | #ifndef WIN32
34 | signal(SIGQUIT, sigproc);
35 | #endif
36 |
37 | UdpTransmitSocket transmitSocket( IpEndpointName( ADDRESS, PORT ) );
38 |
39 | char buffer[OUTPUT_BUFFER_SIZE];
40 |
41 |
42 | FILE *input;
43 | FILE *output;
44 |
45 | char raw_frame[32];
46 | struct emokit_frame frame;
47 | emokit_device* d;
48 | uint8_t data[32];
49 |
50 | d = emokit_create();
51 | printf("Current epoc devices connected: %d\n", emokit_get_count(d, EMOKIT_VID, EMOKIT_PID));
52 | if(emokit_open(d, EMOKIT_VID, EMOKIT_PID, 1) != 0)
53 | {
54 | printf("CANNOT CONNECT\n");
55 | return 1;
56 | }
57 | while(1)
58 | {
59 | int r;
60 | if((r=emokit_read_data_timeout(d, 1000)) > 0)
61 | {
62 | frame = emokit_get_next_frame(d);
63 | osc::OutboundPacketStream p( buffer, OUTPUT_BUFFER_SIZE );
64 | p << osc::BeginMessage( "/multiplot" )
65 | << conv(frame.F3) << conv(frame.FC6) << conv(frame.P7)
66 | << conv(frame.T8) << conv(frame.F7) << conv(frame.F8)
67 | << conv(frame.T7) << conv(frame.P8) << conv(frame.AF4)
68 | << conv(frame.F4) << conv(frame.AF3) << conv(frame.O2)
69 | << conv(frame.O1) << conv(frame.FC5) << osc::EndMessage;
70 |
71 | transmitSocket.Send( p.Data(), p.Size() );
72 | } else if(r == 0)
73 | fprintf(stderr, "Headset Timeout\n");
74 | else {
75 | fprintf(stderr, "Headset Error\n");
76 | break;
77 | }
78 | }
79 |
80 | emokit_close(d);
81 | emokit_delete(d);
82 | return 0;
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/emokit/examples/emokit_osc/pd/emokit-osc.pd:
--------------------------------------------------------------------------------
1 | #N canvas 861 136 478 400 10;
2 | #X obj 6 -38 udpreceive 9997;
3 | #X obj 6 -6 unpackOSC;
4 | #X obj 76 79 unpack 0 0;
5 | #X floatatom 76 103 5 0 0 0 - - -;
6 | #X floatatom 133 103 5 0 0 0 - - -;
7 | #X obj 6 55 routeOSC /channels /gyro;
8 | #X obj 6 27 routeOSC /epoc;
9 | #X text 68 117 gyro x;
10 | #X text 127 117 gyro y;
11 | #X obj 6 80 s ch;
12 | #X obj 210 -39 r ch;
13 | #X floatatom 210 316 5 0 0 0 - - -;
14 | #X floatatom 225 295 5 0 0 0 - - -;
15 | #X floatatom 240 274 5 0 0 0 - - -;
16 | #X floatatom 256 253 5 0 0 0 - - -;
17 | #X floatatom 271 230 5 0 0 0 - - -;
18 | #X floatatom 287 208 5 0 0 0 - - -;
19 | #X floatatom 349 112 5 0 0 0 - - -;
20 | #X floatatom 302 182 5 0 0 0 - - -;
21 | #X floatatom 318 157 5 0 0 0 - - -;
22 | #X floatatom 333 133 5 0 0 0 - - -;
23 | #X floatatom 364 89 5 0 0 0 - - -;
24 | #X floatatom 380 67 5 0 0 0 - - -;
25 | #X floatatom 395 41 5 0 0 0 - - -;
26 | #X floatatom 411 17 5 0 0 0 - - -;
27 | #X text 245 316 F3;
28 | #X text 259 294 FC6;
29 | #X text 275 274 P7;
30 | #X text 289 253 T8;
31 | #X text 303 229 F7;
32 | #X text 319 208 F8;
33 | #X obj 210 -10 unpack 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
34 | #X text 335 182 T7;
35 | #X text 353 155 P8;
36 | #X text 366 132 AF4;
37 | #X text 382 111 F4;
38 | #X text 397 89 AF3;
39 | #X text 412 67 O2;
40 | #X text 427 42 O1;
41 | #X text 445 18 FC5;
42 | #X connect 0 0 1 0;
43 | #X connect 1 0 6 0;
44 | #X connect 2 0 3 0;
45 | #X connect 2 1 4 0;
46 | #X connect 5 0 9 0;
47 | #X connect 5 1 2 0;
48 | #X connect 6 0 5 0;
49 | #X connect 10 0 31 0;
50 | #X connect 31 0 11 0;
51 | #X connect 31 1 12 0;
52 | #X connect 31 2 13 0;
53 | #X connect 31 3 14 0;
54 | #X connect 31 4 15 0;
55 | #X connect 31 5 16 0;
56 | #X connect 31 6 18 0;
57 | #X connect 31 7 19 0;
58 | #X connect 31 8 20 0;
59 | #X connect 31 9 17 0;
60 | #X connect 31 10 21 0;
61 | #X connect 31 11 22 0;
62 | #X connect 31 12 23 0;
63 | #X connect 31 13 24 0;
64 |
--------------------------------------------------------------------------------
/emokit/examples/emokitd/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ##################################################
2 | # epoc daemon #
3 | ##################################################
4 |
5 | add_executable (emokitd emokitd.c)
6 | ADD_DEPENDENCIES(emokitd emokit)
7 | target_link_libraries (emokitd emokit ${LIBS} pthread)
8 |
9 | SET_TARGET_PROPERTIES(emokitd PROPERTIES
10 | INSTALL_RPATH_USE_LINK_PATH TRUE
11 | INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib
12 | BUILD_WITH_INSTALL_RPATH TRUE )
13 |
14 | INSTALL (TARGETS emokitd
15 | RUNTIME DESTINATION bin
16 | )
17 |
18 |
--------------------------------------------------------------------------------
/emokit/examples/emokitd/emokitd.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | #include "emokit/emokit.h"
15 |
16 | #include "emokitd.h"
17 |
18 | sigset_t mask;
19 |
20 | typedef struct emokit_device emokit_device;
21 |
22 | void fatal_err(const char *msg) {
23 | syslog(LOG_INFO, msg);
24 | exit(1);
25 | }
26 |
27 | void init_fatal_err(const char *msg) {
28 | printf("Fatal: %s\n", msg);
29 | exit(1);
30 | }
31 |
32 | void *thr_signal_handler(void *arg) {
33 | int sig;
34 | for (;;) {
35 | if (sigwait(&mask, &sig) != 0) {
36 | fatal_err("sigwait failed.");
37 | }
38 | switch (sig) {
39 | case SIGTERM:
40 | syslog(LOG_INFO, "Caught SIGTERM. Exiting.");
41 | remove(FIFO_PATH);
42 | exit(0);
43 |
44 | case SIGPIPE:
45 | syslog(LOG_INFO, "Reader exited; blocking.");
46 | break;
47 |
48 | default:
49 | syslog(LOG_INFO, "Caught unexpected signal: %d", sig);
50 | }
51 | }
52 | }
53 |
54 | int daemon_running() {
55 | int fd;
56 | char buf[16];
57 | struct flock fl;
58 | fd = open(PIDFILE, O_RDWR|O_CREAT, LOCKMODE);
59 | if (fd < 0)
60 | fatal_err("cannot open pidfile.");
61 | fl.l_type = F_WRLCK;
62 | fl.l_start = 0;
63 | fl.l_whence = SEEK_SET;
64 | fl.l_len = 0;
65 | fl.l_pid = getpid();
66 | if (fcntl(fd, F_SETLK, &fl) < 0) {
67 | if (errno == EACCES || errno == EAGAIN) {
68 | close(fd);
69 | return 1;
70 | }
71 | fatal_err("cannot lock pidfile.");
72 | }
73 | ftruncate(fd, 0);
74 | sprintf(buf, "%ld", (long) getpid());
75 | write(fd, buf, strlen(buf)+1);
76 | return 0;
77 | }
78 |
79 | void daemonize() {
80 | int i, fd0, fd1, fd2;
81 | pid_t pid;
82 | struct rlimit rl;
83 | struct sigaction sa;
84 | umask(0);
85 | if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
86 | init_fatal_err("Fatal: can't get file limit.");
87 |
88 | if ((pid = fork()) < 0)
89 | init_fatal_err("Fatal: can't fork.");
90 | else if (pid != 0)
91 | exit(0);
92 | setsid();
93 |
94 | sa.sa_handler = SIG_IGN;
95 | sigemptyset(&sa.sa_mask);
96 | sa.sa_flags = 0;
97 | if (sigaction(SIGHUP, &sa, NULL) < 0)
98 | init_fatal_err("Fatal: can't ignore SIGHUP.");
99 | if ((pid = fork()) < 0)
100 | init_fatal_err("Fatal: can't fork.\n");
101 | else if (pid != 0)
102 | exit(0);
103 |
104 | /* switch working directory to / so we're not preventing
105 | anything from unmounting */
106 | if (chdir("/") < 0)
107 | init_fatal_err("Fatal: can't chdir to /.");
108 |
109 | if (rl.rlim_max == RLIM_INFINITY)
110 | rl.rlim_max = 1024;
111 | for (i=0; i < rl.rlim_max; ++i)
112 | close(i);
113 |
114 | /* so we can't spew into standard streams */
115 | fd0 = open("/dev/null", O_RDWR);
116 | fd1 = dup(fd0);
117 | fd2 = dup(fd0);
118 |
119 | openlog(DAEMON_IDENT, LOG_CONS, LOG_DAEMON);
120 | syslog(LOG_INFO, "emokitd running; decrypted EEG data will be written to %s.", FIFO_PATH);
121 |
122 | }
123 |
124 | void dbg_stream(emokit_device *eeg) {
125 | int i;
126 | for (;;) {
127 | if (emokit_read_data(eeg) > 0) {
128 | emokit_get_next_frame(eeg);
129 | for (i=0; i < 32; ++i) {
130 | //printf("%d ", eeg->raw_frame[i]);
131 | }
132 | putchar('\n');
133 | fflush(stdout);
134 | }
135 | }
136 | }
137 |
138 | void decrypt_loop(emokit_device *eeg) {
139 | int i;
140 | FILE *emokitd_fifo;
141 | emokitd_fifo = fopen(FIFO_PATH, "wb");
142 | if (!emokitd_fifo) {
143 | fatal_err("cannot open FIFO for writing.");
144 | }
145 | for (;;) {
146 | if (emokit_read_data(eeg) > 0) {
147 | emokit_get_next_frame(eeg);
148 | unsigned char raw_frame[32];
149 | emokit_get_raw_frame(eeg, raw_frame);
150 | fwrite(raw_frame, 1, EMOKIT_PKT_SIZE, emokitd_fifo);
151 | }
152 | }
153 | }
154 |
155 | int main(int argc, char **argv) {
156 | int i;
157 | unsigned char dev_type;
158 | pthread_t tid;
159 | struct sigaction sa;
160 | emokit_device *eeg;
161 | if (!DEBUG) {
162 | daemonize();
163 | if (daemon_running()) {
164 | syslog(LOG_INFO, "Looks like emokitd is already running.\n");
165 | exit(1);
166 | }
167 | }
168 | eeg = emokit_create();
169 | if (emokit_open(eeg, EMOKIT_VID, EMOKIT_PID, 0) != 0) {
170 | fatal_err("cannot access device. Are you root?");
171 | return 1;
172 | }
173 |
174 | if ((access(FIFO_PATH, W_OK) < 0) && mkfifo(FIFO_PATH, 0666) != 0) {
175 | fatal_err("cannot create FIFO.");
176 | }
177 | sa.sa_handler = SIG_DFL;
178 | sigemptyset(&sa.sa_mask);
179 | if (sigaction(SIGHUP, &sa, NULL) < 0)
180 | fatal_err("cannot restore SIGHUP.");
181 | sigfillset(&mask);
182 | if (pthread_sigmask(SIG_BLOCK, &mask, NULL) != 0)
183 | fatal_err("SIG_BLOCK error.");
184 | if (pthread_create(&tid, NULL, thr_signal_handler, 0) != 0)
185 | fatal_err("cannot create thread.");
186 | if (DEBUG)
187 | printf("Entering decrypt loop...\n");
188 | decrypt_loop(eeg);
189 | return 0;
190 | }
191 |
--------------------------------------------------------------------------------
/emokit/examples/emokitd/emokitd.h:
--------------------------------------------------------------------------------
1 | #include "sys/stat.h"
2 |
3 | #define DAEMON_IDENT "emokitd"
4 | #define PIDFILE "/var/run/emokitd.pid"
5 | #define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
6 | #define FIFO_PATH "/dev/emokitd"
7 | #define EMOKIT_PKT_SIZE 32
8 |
9 | #ifndef DEBUG
10 | #define DEBUG 0
11 | #endif
12 |
--------------------------------------------------------------------------------
/emokit/include/emokit/emokit.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2010, Daeken and Skadge
2 | * Copyright (c) 2011-2012, OpenYou Organization (http://openyou.org)
3 | *
4 | * Permission to use, copy, modify, and/or distribute this software for any
5 | * purpose with or without fee is hereby granted, provided that the above
6 | * copyright notice and this permission notice appear in all copies.
7 | *
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 | */
16 |
17 | #ifndef LIBEMOKIT_H_
18 | #define LIBEMOKIT_H_
19 |
20 | #define E_EMOKIT_DRIVER_ERROR -1
21 | #define E_EMOKIT_NOT_INITED -2
22 | #define E_EMOKIT_NOT_OPENED -3
23 |
24 | #include
25 | #if !defined(WIN32)
26 | #define EMOKIT_DECLSPEC
27 | #else
28 | #define EMOKIT_DECLSPEC __declspec(dllexport)
29 | #endif
30 |
31 | /// Vendor ID for all emotiv devices
32 | const static uint32_t EMOKIT_VID = 0x21a1;
33 | /// Product ID for all emotiv devices
34 | const static uint32_t EMOKIT_PID = 0x0001;
35 |
36 | /// Out endpoint for all emotiv devices
37 | const static uint32_t EMOKIT_OUT_ENDPT = 0x02;
38 | /// In endpoint for all emotiv devices
39 | const static uint32_t EMOKIT_IN_ENDPT = 0x82;
40 |
41 | struct emokit_contact_quality {//values > 4000 are good
42 | short F3, FC6, P7, T8, F7, F8, T7, P8, AF4, F4, AF3, O2, O1, FC5;
43 | };
44 |
45 | struct emokit_frame {
46 | unsigned char counter; //loops from 0 to 128 (129 values)
47 | int F3, FC6, P7, T8, F7, F8, T7, P8, AF4, F4, AF3, O2, O1, FC5; //raw data values
48 | struct emokit_contact_quality cq;
49 | char gyroX, gyroY;
50 | unsigned char battery; //percentage of full charge, read on counter=128
51 | };
52 |
53 |
54 | #ifdef __cplusplus
55 | extern "C"
56 | {
57 | #endif
58 | struct emokit_device;
59 | /**
60 | * Kills crypto context. Not meant for public calling, call
61 | * emokit_delete instead.
62 | *
63 | */
64 | void emokit_deinit(struct emokit_device* s);
65 |
66 | /**
67 | * Create a new struct emokit_device structure and return a pointer to it.
68 | * Makes sure structure is initialized properly. To delete, call
69 | * emokit_delete().
70 | *
71 | *
72 | * @return new struct emokit_device structure
73 | */
74 | EMOKIT_DECLSPEC struct emokit_device* emokit_create();
75 |
76 | /**
77 | * Return the number of devices currently connected to the system
78 | *
79 | * @param s Inited device structure
80 | * @param device_vid VID to look for, usually EMOKIT_VID constant
81 | * @param device_pid PID to look for, usually EMOKIT_PID constant
82 | *
83 | * @return Number of devices currently connected to system, or < 0
84 | * for error
85 | */
86 | EMOKIT_DECLSPEC int emokit_get_count(struct emokit_device* s,
87 | int device_vid,
88 | int device_pid);
89 |
90 | /**
91 | * Open an inited device
92 | *
93 | * @param s Inited device structure
94 | * @param device_vid VID to look for, usually EMOKIT_VID constant
95 | * @param device_pid PID to look for, usually EMOKIT_PID constant
96 | * @param device_index Index of device to open on the bus (0 for first device
97 | * found)
98 | *
99 | * @return 0 if successful, < 0 for error
100 | */
101 | EMOKIT_DECLSPEC int emokit_open(struct emokit_device* s,
102 | int device_vid,
103 | int device_pid,
104 | unsigned int device_index);
105 |
106 | /**
107 | * Close an opened device
108 | *
109 | * @param s Currently opened device
110 | *
111 | * @return 0 if successful, < 0 for error
112 | */
113 | EMOKIT_DECLSPEC int emokit_close(struct emokit_device* s);
114 |
115 | /**
116 | * Delete an inited device
117 | *
118 | * @param dev Initied device strucure
119 | */
120 | EMOKIT_DECLSPEC void emokit_delete(struct emokit_device* dev);
121 |
122 | /**
123 | * Read a single raw report from the device. This function will
124 | * block until a single report is read. We are guarenteed each
125 | * report will be a full message from the device, so we do not need
126 | * to maintain read state between reads.
127 | *
128 | * @param dev Opened device structure
129 | *
130 | * @return <0 for error, otherwise return the number of bytes read.
131 | */
132 | EMOKIT_DECLSPEC int emokit_read_data(struct emokit_device* dev);
133 |
134 | /**
135 | * Read a single raw report from the device.
136 | *
137 | * @param dev Opened device structure
138 | * @param timeout Max wait time in ms
139 | *
140 | * @return <0 for error, otherwise return the number of bytes read.
141 | */
142 | EMOKIT_DECLSPEC int emokit_read_data_timeout(struct emokit_device* dev,
143 | unsigned timeout);
144 |
145 | EMOKIT_DECLSPEC struct emokit_frame
146 | emokit_get_next_frame(struct emokit_device* dev);
147 |
148 | /**
149 | * Given a feature report from the device, extract the serial and
150 | * create the crypto key. Exposed because why not. Sets "key" field
151 | * in device struct.
152 | *
153 | * @param s Initied, opened device
154 | * @param dev_type EMOKIT_CONSUMER or EMOKIT_RESEARCH
155 | *
156 | * @return 0 if successful, < 0 for error
157 | */
158 | EMOKIT_DECLSPEC void emokit_get_crypto_key(struct emokit_device* s,
159 | int dev_type);
160 |
161 | /**
162 | * Given an emokit_device and an unsigned char array of not
163 | * fewer than 32 bytes, load the most recent unencrypted data
164 | * frame into the array. Does not return a value.
165 | */
166 | EMOKIT_DECLSPEC void emokit_get_raw_frame(struct emokit_device *dev, unsigned char *buf);
167 |
168 | #ifdef __cplusplus
169 | };
170 | #endif
171 | #endif //LIBEMOKIT_H_
172 |
--------------------------------------------------------------------------------
/emokit/linux/epoc.rules:
--------------------------------------------------------------------------------
1 | #UDEV rule for the Emotiv EPOC headset
2 | #
3 | #Once installed into /etc/udev/rules.d, udev will recognize the headset and
4 | #create a /dev/eeg/encrypted device where you can access the headset encryted
5 | #stream.
6 | #
7 | #It will as well attempt to start a daemon in charge of decrypting the stream.
8 | #If the daemon successfully starts, you will find the data under /dev/eeg/raw
9 |
10 | ATTR{manufacturer}=="Emotiv Systems Pty Ltd", ATTRS{product}=="Receiver Dongle L01", NAME="eeg/epoc%2", SYMLINK+="epoc%n"
11 |
12 | #Consumer headset
13 | #SUBSYSTEM=="hidraw", ATTRS{idVendor}=="21a1", ATTRS{idProduct}=="0001", ATTRS{interface}=="Emotiv RAW DATA", NAME="eeg/encrypted%n", SYMLINK+="eeg/encrypted", MODE="0444", RUN +="decrypt_emotiv.sh consumer"
14 |
15 | #Research headset
16 | SUBSYSTEM=="hidraw", ATTRS{interface}=="Emotiv RAW DATA", NAME="eeg/encrypted%n", SYMLINK+="eeg/encrypted", MODE="0444", RUN +="decrypt_emotiv.sh research"
17 |
18 |
--------------------------------------------------------------------------------
/emokit/python/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include requirements.txt tests/*
2 |
--------------------------------------------------------------------------------
/emokit/python/Makefile:
--------------------------------------------------------------------------------
1 | SHELL := /bin/bash
2 |
3 | test:
4 | nosetests-2.7 -s --verbosity=2
5 |
6 | clean:
7 | rm -fr build dist
8 | rm -fr *.egg-info
9 | find . -name *.pyc -exec rm {} \;
10 | find . -name *.swp -exec rm {} \;
11 |
12 | install:
13 | python2.7 setup.py install
14 |
15 | upload: clean
16 | python2.7 setup.py sdist upload
17 |
18 |
--------------------------------------------------------------------------------
/emokit/python/dist/emokit-0.0.1-py2.7.egg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nikhiljay/brainwaves/42d96dccedf09504589fc9e14e3b470de7f5c0b2/emokit/python/dist/emokit-0.0.1-py2.7.egg
--------------------------------------------------------------------------------
/emokit/python/emokit.egg-info/PKG-INFO:
--------------------------------------------------------------------------------
1 | Metadata-Version: 1.1
2 | Name: emokit
3 | Version: 0.0.1
4 | Summary: emotiv epoc eeg headset sdk
5 | Home-page: https://github.com/kanzure/emokit
6 | Author: Bryan Bishop
7 | Author-email: kanzure@gmail.com
8 | License: UNKNOWN
9 | Description: UNKNOWN
10 | Platform: any
11 | Classifier: Operating System :: OS Independent
12 | Classifier: Programming Language :: Python
13 |
--------------------------------------------------------------------------------
/emokit/python/emokit.egg-info/SOURCES.txt:
--------------------------------------------------------------------------------
1 | MANIFEST.in
2 | requirements.txt
3 | setup.py
4 | emokit/__init__.py
5 | emokit/emotiv.py
6 | emokit.egg-info/PKG-INFO
7 | emokit.egg-info/SOURCES.txt
8 | emokit.egg-info/dependency_links.txt
9 | emokit.egg-info/not-zip-safe
10 | emokit.egg-info/requires.txt
11 | emokit.egg-info/top_level.txt
12 | tests/test_emokit.py
--------------------------------------------------------------------------------
/emokit/python/emokit.egg-info/dependency_links.txt:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/emokit/python/emokit.egg-info/not-zip-safe:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/emokit/python/emokit.egg-info/requires.txt:
--------------------------------------------------------------------------------
1 | gevent
2 | pycrypto
--------------------------------------------------------------------------------
/emokit/python/emokit.egg-info/top_level.txt:
--------------------------------------------------------------------------------
1 | emokit
2 |
--------------------------------------------------------------------------------
/emokit/python/emokit/Makefile-manual:
--------------------------------------------------------------------------------
1 | ###########################################
2 | # Simple Makefile for HIDAPI test program
3 | #
4 | # Alan Ott
5 | # Signal 11 Software
6 | # 2010-07-03
7 | ###########################################
8 |
9 | all: hidtest
10 |
11 | CC=gcc
12 | CXX=g++
13 | COBJS=hid.o
14 | CPPOBJS=../hidtest/hidtest.o
15 | OBJS=$(COBJS) $(CPPOBJS)
16 | CFLAGS+=-I../hidapi -Wall -g -c
17 | LIBS=-framework IOKit -framework CoreFoundation
18 |
19 |
20 | hidtest: $(OBJS)
21 | g++ -Wall -g $^ $(LIBS) -o hidtest
22 |
23 | $(COBJS): %.o: %.c
24 | $(CC) $(CFLAGS) $< -o $@
25 |
26 | $(CPPOBJS): %.o: %.cpp
27 | $(CXX) $(CFLAGS) $< -o $@
28 |
29 | clean:
30 | rm -f *.o hidtest $(CPPOBJS)
31 |
32 | .PHONY: clean
33 |
--------------------------------------------------------------------------------
/emokit/python/emokit/Makefile.am:
--------------------------------------------------------------------------------
1 | lib_LTLIBRARIES = libhidapi.la
2 | libhidapi_la_SOURCES = hid.c
3 | libhidapi_la_LDFLAGS = $(LTLDFLAGS)
4 | AM_CPPFLAGS = -I$(top_srcdir)/hidapi/
5 |
6 | hdrdir = $(includedir)/hidapi
7 | hdr_HEADERS = $(top_srcdir)/hidapi/hidapi.h
8 |
9 | EXTRA_DIST = Makefile-manual
10 |
--------------------------------------------------------------------------------
/emokit/python/emokit/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | emokit - emotiv epoc reverse engineering
4 | ~~~~~~~~~~~~~~~
5 |
6 | :copyright: (c) 2013 by ???
7 | :license: ???
8 | """
9 |
10 | __title__ = "emokit"
11 | __version__ = "0.0.1"
12 | __build__ = 0x000001
13 | __author__ = "Bryan Bishop "
14 | __license__ = "???"
15 | __copyright__ = "Copyright 2013 Bryan Bishop"
16 |
17 | from . import emotiv
18 |
--------------------------------------------------------------------------------
/emokit/python/emokit/cv.py:
--------------------------------------------------------------------------------
1 | /usr/local/Cellar/opencv/2.4.12/lib/python2.7/site-packages/cv.py
--------------------------------------------------------------------------------
/emokit/python/emokit/cv2.so:
--------------------------------------------------------------------------------
1 | /usr/local/Cellar/opencv/2.4.12/lib/python2.7/site-packages/cv2.so
--------------------------------------------------------------------------------
/emokit/python/emokit/data.txt:
--------------------------------------------------------------------------------
1 | {"Y": {"quality": 0, "value": -5}, "F3": {"quality": 0, "value": -92}, "F4": {"quality": 0, "value": 555}, "P7": {"quality": 0, "value": -1221}, "FC6": {"quality": 0, "value": 185}, "F7": {"quality": 0, "value": 150}, "F8": {"quality": 0, "value": -142}, "T7": {"quality": 0, "value": -66}, "P8": {"quality": 0, "value": 376}, "FC5": {"quality": 0, "value": 300}, "AF4": {"quality": 0, "value": -177}, "battery": {"value": 46}, "Unknown": {"quality": 0, "value": 37}, "T8": {"quality": 0, "value": 178}, "X": {"quality": 0, "value": 5}, "O2": {"quality": 0, "value": 25}, "O1": {"quality": 0, "value": -146}, "AF3": {"quality": 0, "value": 357}}
--------------------------------------------------------------------------------
/emokit/python/emokit/hid.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nikhiljay/brainwaves/42d96dccedf09504589fc9e14e3b470de7f5c0b2/emokit/python/emokit/hid.o
--------------------------------------------------------------------------------
/emokit/python/emokit/src/pip-delete-this-directory.txt:
--------------------------------------------------------------------------------
1 | This file is placed here by pip to indicate the source was put
2 | here by pip.
3 |
4 | Once this package is successfully installed this source code will be
5 | deleted (unless you remove this file).
6 |
--------------------------------------------------------------------------------
/emokit/python/example.py:
--------------------------------------------------------------------------------
1 | # This is an example of popping a packet from the Emotiv class's packet queue
2 | # and printing the gyro x and y values to the console.
3 |
4 | from emokit.emotiv import Emotiv
5 | import platform
6 | if platform.system() == "Windows":
7 | import socket # Needed to prevent gevent crashing on Windows. (surfly / gevent issue #459)
8 | import gevent
9 |
10 | if __name__ == "__main__":
11 | headset = Emotiv()
12 | gevent.spawn(headset.setup)
13 | gevent.sleep(0)
14 | try:
15 | while True:
16 | packet = headset.dequeue()
17 | print packet.gyro_x, packet.gyro_y
18 | gevent.sleep(0)
19 | except KeyboardInterrupt:
20 | headset.close()
21 | finally:
22 | headset.close()
23 |
--------------------------------------------------------------------------------
/emokit/python/mouse_control.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # Example of using the gyro values to control mouse movement.
3 | import ctypes
4 | from ctypes import cdll
5 |
6 | import platform
7 | if platform.system() == "Windows":
8 | import socket # Needed to prevent gevent crashing on Windows. (surfly / gevent issue #459)
9 | import gevent
10 |
11 | from emokit.emotiv import Emotiv
12 |
13 |
14 | class Xlib:
15 | def __init__(self):
16 | self.xlib = cdll.LoadLibrary('libX11.so')
17 |
18 | display = self.xlib.XOpenDisplay(None)
19 | dflt_screen_num = self.xlib.XDefaultScreen(display)
20 | default_screen = self.xlib.XScreenOfDisplay(display, dflt_screen_num)
21 |
22 | self.width = self.xlib.XWidthOfScreen(default_screen)
23 | self.height = self.xlib.XHeightOfScreen(default_screen)
24 | self.xlib.XCloseDisplay(display)
25 |
26 | def move_mouse(self, x, y):
27 | display = self.xlib.XOpenDisplay(None)
28 | root = self.xlib.XDefaultRootWindow(display)
29 | self.xlib.XWarpPointer(display, None, root, 0, 0, 0, 0, x, y)
30 | self.xlib.XCloseDisplay(display)
31 |
32 |
33 | class WinMouse:
34 | def __init__(self):
35 | user32 = ctypes.windll.user32
36 | self.width = user32.GetSystemMetrics(0)
37 | self.height = user32.GetSystemMetrics(1)
38 |
39 | def click(self, x, y):
40 | ctypes.windll.user32.SetCursorPos(x, y)
41 | ctypes.windll.user32.mouse_event(2, 0, 0, 0, 0) # left down
42 | ctypes.windll.user32.mouse_event(4, 0, 0, 0, 0) # left up
43 |
44 | def move_mouse(self, x, y):
45 | ctypes.windll.user32.SetCursorPos(x, y)
46 |
47 |
48 | def main():
49 | if not platform.system() == 'Windows':
50 | screen = Xlib()
51 | else:
52 | screen = WinMouse()
53 | width = screen.width
54 | height = screen.height
55 |
56 | cursor_x, cursor_y = width / 2, height / 2
57 | while True:
58 | updated = False
59 | packet = headset.dequeue()
60 | if abs(packet.gyro_x) > 1:
61 | cursor_x -= packet.gyro_x
62 | updated = True
63 | if abs(packet.gyro_y) > 1:
64 | cursor_y += packet.gyro_y
65 | updated = True
66 | cursor_x = max(0, min(cursor_x, width))
67 | cursor_y = max(0, min(cursor_y, height))
68 | if updated:
69 | screen.move_mouse(cursor_x, cursor_y)
70 | gevent.sleep(0)
71 |
72 |
73 | headset = None
74 | if __name__ == "__main__":
75 | try:
76 | headset = Emotiv()
77 | gevent.spawn(headset.setup)
78 | gevent.sleep(0)
79 | main()
80 |
81 | finally:
82 | if headset:
83 | headset.close()
84 |
--------------------------------------------------------------------------------
/emokit/python/render.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # Renders a window with graph values for each sensor and a box for gyro values.
3 | try:
4 | import psyco
5 | psyco.full()
6 | except ImportError:
7 | print 'No psyco. Expect poor performance. Not really...'
8 |
9 | import pygame
10 | import platform
11 | from pygame import FULLSCREEN
12 | if platform.system() == "Windows":
13 | import socket # Needed to prevent gevent crashing on Windows. (surfly / gevent issue #459)
14 | import gevent
15 | from emokit.emotiv import Emotiv
16 |
17 | quality_color = {
18 | "0": (0, 0, 0),
19 | "1": (255, 0, 0),
20 | "2": (255, 0, 0),
21 | "3": (255, 255, 0),
22 | "4": (255, 255, 0),
23 | "5": (0, 255, 0),
24 | "6": (0, 255, 0),
25 | "7": (0, 255, 0),
26 | }
27 |
28 | old_quality_color = {
29 | "0": (0, 0, 0),
30 | "1": (255, 0, 0),
31 | "2": (255, 255, 0),
32 | "3": (0, 255, 0),
33 | "4": (0, 255, 0),
34 | }
35 |
36 |
37 | class Grapher(object):
38 | """
39 | Worker that draws a line for the sensor value.
40 | """
41 | def __init__(self, screen, name, i):
42 | """
43 | Initializes graph worker
44 | """
45 | self.screen = screen
46 | self.name = name
47 | self.range = float(1 << 13)
48 | self.x_offset = 40
49 | self.y = i * gheight
50 | self.buffer = []
51 | font = pygame.font.Font(None, 24)
52 | self.text = font.render(self.name, 1, (255, 0, 0))
53 | self.text_pos = self.text.get_rect()
54 | self.text_pos.centery = self.y + gheight
55 | self.first_packet = True
56 | self.y_offset = 0
57 |
58 | def update(self, packet):
59 | """
60 | Appends value and quality values to drawing buffer.
61 | """
62 | if len(self.buffer) == 800 - self.x_offset:
63 | self.buffer = self.buffer[1:]
64 | self.buffer.append([packet.sensors[self.name]['value'], packet.sensors[self.name]['quality'], packet.old_model])
65 |
66 | def calc_y(self, val):
67 | """
68 | Calculates line height from value.
69 | """
70 | return val - self.y_offset + gheight
71 |
72 | def draw(self):
73 | """
74 | Draws a line from values stored in buffer.
75 | """
76 | if len(self.buffer) == 0:
77 | return
78 |
79 | if self.first_packet:
80 | self.y_offset = self.buffer[0][0]
81 | self.first_packet = False
82 | pos = self.x_offset, self.calc_y(self.buffer[0][0]) + self.y
83 | for i, (value, quality, old_model) in enumerate(self.buffer):
84 | y = self.calc_y(value) + self.y
85 | if old_model:
86 | color = old_quality_color[str(quality)]
87 | else:
88 | color = quality_color[str(quality)]
89 | pygame.draw.line(self.screen, color, pos, (self.x_offset + i, y))
90 | pos = (self.x_offset + i, y)
91 | self.screen.blit(self.text, self.text_pos)
92 |
93 |
94 | def main():
95 | """
96 | Creates pygame window and graph drawing workers for each sensor.
97 | """
98 | global gheight
99 | pygame.init()
100 | screen = pygame.display.set_mode((800, 600))
101 | graphers = []
102 | recordings = []
103 | recording = False
104 | record_packets = []
105 | updated = False
106 | cursor_x, cursor_y = 400, 300
107 | for name in 'AF3 F7 F3 FC5 T7 P7 O1 O2 P8 T8 FC6 F4 F8 AF4'.split(' '):
108 | graphers.append(Grapher(screen, name, len(graphers)))
109 | fullscreen = False
110 | emotiv = Emotiv(display_output=True)
111 | gevent.spawn(emotiv.setup)
112 | gevent.sleep(0)
113 | while emotiv.running:
114 | for event in pygame.event.get():
115 | if event.type == pygame.QUIT:
116 | emotiv.close()
117 | return
118 | if event.type == pygame.KEYDOWN:
119 | if event.key == pygame.K_ESCAPE:
120 | emotiv.close()
121 | return
122 | elif event.key == pygame.K_f:
123 | if fullscreen:
124 | screen = pygame.display.set_mode((800, 600))
125 | fullscreen = False
126 | else:
127 | screen = pygame.display.set_mode((800, 600), FULLSCREEN, 16)
128 | fullscreen = True
129 | elif event.key == pygame.K_r:
130 | if not recording:
131 | record_packets = []
132 | recording = True
133 | else:
134 | recording = False
135 | recordings.append(list(record_packets))
136 | record_packets = None
137 | packets_in_queue = 0
138 | try:
139 | while packets_in_queue < 8:
140 | packet = emotiv.dequeue()
141 | if abs(packet.gyro_x) > 1:
142 | cursor_x = max(0, min(cursor_x, 800))
143 | cursor_x -= packet.gyro_x
144 | if abs(packet.gyro_y) > 1:
145 | cursor_y += packet.gyro_y
146 | cursor_y = max(0, min(cursor_y, 600))
147 | map(lambda x: x.update(packet), graphers)
148 | if recording:
149 | record_packets.append(packet)
150 | updated = True
151 | packets_in_queue += 1
152 | except Exception, ex:
153 | print ex
154 |
155 | if updated:
156 | screen.fill((75, 75, 75))
157 | map(lambda x: x.draw(), graphers)
158 | pygame.draw.rect(screen, (255, 255, 255), (cursor_x - 5, cursor_y - 5, 10, 10), 0)
159 | pygame.display.flip()
160 | updated = False
161 | gevent.sleep(0)
162 |
163 | try:
164 | gheight = 580 / 14
165 | main()
166 |
167 | except Exception, e:
168 | print e
169 |
--------------------------------------------------------------------------------
/emokit/python/requirements.txt:
--------------------------------------------------------------------------------
1 | gevent
2 | pycrypto
3 |
--------------------------------------------------------------------------------
/emokit/python/setup.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from setuptools import setup
3 | import os
4 |
5 | import emokit
6 |
7 | long_description = None
8 |
9 | packages = [
10 | "emokit",
11 | ]
12 |
13 | requirements = open("requirements.txt", "r").read().split("\n")
14 |
15 | setup(
16 | name="emokit",
17 | version=emokit.__version__,
18 | url="https://github.com/kanzure/emokit",
19 | license="",
20 | author="Bryan Bishop",
21 | author_email="kanzure@gmail.com",
22 | maintainer="Bryan Bishop",
23 | maintainer_email="kanzure@gmail.com",
24 | description="emotiv epoc eeg headset sdk",
25 | long_description=long_description,
26 | packages=packages,
27 | install_requires=requirements,
28 | scripts=[],
29 | platforms="any",
30 | zip_safe=False,
31 | classifiers=[
32 | "Operating System :: OS Independent",
33 | "Programming Language :: Python",
34 | ]
35 | )
36 |
--------------------------------------------------------------------------------
/emokit/python/tests/test_emokit.py:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 | from emokit.emotiv import Emotiv
3 |
4 | import unittest
5 |
6 | class TestEmotiv(unittest.TestCase):
7 | def test_emotiv(self):
8 | emotiv = Emotiv()
9 |
10 |
--------------------------------------------------------------------------------
/emokit/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ##########################################
2 | ## libemokit ###
3 | ##########################################
4 |
5 | # Create a library called "libemokit"
6 | ADD_LIBRARY (emokit emokit.c)
7 | target_link_libraries (emokit ${LIBS})
8 |
9 | INSTALL (TARGETS emokit
10 | LIBRARY DESTINATION lib
11 | ARCHIVE DESTINATION lib
12 | )
13 |
14 | IF(BUILD_SHARED_LIBS)
15 | INSTALL (FILES
16 | ${LIBEMOKIT_HEADERS}
17 | DESTINATION include/emokit
18 | )
19 | ENDIF()
20 |
21 |
--------------------------------------------------------------------------------
/scripts/brainwaves-script:
--------------------------------------------------------------------------------
1 | open /Users/Nikhil/Projects/Development/AAR/scripts/ngrok
2 | python /Users/Nikhil/Projects/Development/AAR/emokit/python/emokit/emotiv.py
3 |
--------------------------------------------------------------------------------
/scripts/data.txt:
--------------------------------------------------------------------------------
1 | {"Y": {"quality": 0, "value": -6}, "F3": {"quality": 0, "value": -111}, "F4": {"quality": 0, "value": 576}, "P7": {"quality": 0, "value": -1272}, "FC6": {"quality": 0, "value": 177}, "F7": {"quality": 0, "value": 246}, "F8": {"quality": 0, "value": -154}, "T7": {"quality": 0, "value": -78}, "P8": {"quality": 0, "value": 384}, "FC5": {"quality": 0, "value": 294}, "Battery": {"value": 32}, "AF4": {"quality": 0, "value": -187}, "Unknown": {"quality": 0, "value": 30}, "T8": {"quality": 0, "value": 186}, "X": {"quality": 0, "value": 5}, "O2": {"quality": 0, "value": 2}, "O1": {"quality": 0, "value": -150}, "AF3": {"quality": 0, "value": 370}}
--------------------------------------------------------------------------------
/scripts/ngrok:
--------------------------------------------------------------------------------
1 | cd
2 | ./ngrok http 8000
3 |
--------------------------------------------------------------------------------