Ind.ie is now Small Technology Foundation.
Commit 82ed8c2e authored by Aral Balkan's avatar Aral Balkan

Added NodeSocket.

parent c510bbdf
This diff is collapsed.
......@@ -9,18 +9,36 @@
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
class AppDelegate: NSObject, NSApplicationDelegate, NodeSocketDelegate {
var nodeSocket: NodeSocket!
func applicationDidFinishLaunching(aNotification: NSNotification) {
//
// Start NodeSocket.
//
self.nodeSocket = NodeSocket()
self.nodeSocket.delegate = self
func applicationDidFinishLaunching(aNotification: NSNotification) {
// Insert code here to initialize your application
}
func applicationWillTerminate(aNotification: NSNotification) {
// Insert code here to tear down your application
}
//
// Stop NodeSocket.
//
self.nodeSocket.shutdown()
}
//
// MARK: NodeSocketDelegate methods
//
func nodeSocketIsReady(socket:WebSocket)
{
println("🐭\t\tNode Socket is ready")
socket.writeString("isFirstRun")
}
}
//
// File.swift
// Heartbeat
//
// Created by Aral Balkan on 25/09/2014.
// Copyright (c) 2014 ind.ie. All rights reserved.
//
import Foundation
//
// Helpers
//
func delay(delay:Double, closure:()->())
{
//
// Run the passed closure after a given number of seconds.
//
// Courtesy: http://stackoverflow.com/questions/24034544/dispatch-after-gcd-in-swift
//
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), closure)
}
{
"images" : [
{
"idiom" : "mac",
"size" : "16x16",
"idiom" : "mac",
"filename" : "icon16.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "16x16",
"idiom" : "mac",
"filename" : "icon16@2x.png",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "32x32",
"idiom" : "mac",
"filename" : "icon32.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "32x32",
"idiom" : "mac",
"filename" : "icon32@2x.png",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "128x128",
"idiom" : "mac",
"filename" : "icon128.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "128x128",
"idiom" : "mac",
"filename" : "icon128@2x.png",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "256x256",
"idiom" : "mac",
"filename" : "icon256.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "256x256",
"idiom" : "mac",
"filename" : "icon256@2x.png",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "512x512",
"idiom" : "mac",
"filename" : "icon512.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "512x512",
"idiom" : "mac",
"filename" : "icon512@2x.png",
"scale" : "2x"
}
],
......
//
// NodeSocket.swift
// Heartbeat
//
// Created by Aral Balkan on 24/09/2014.
// Copyright (c) 2014 ind.ie. All rights reserved.
//
import Cocoa
protocol NodeSocketDelegate
{
func nodeSocketIsReady(socket:WebSocket)
}
class NodeSocket: NSObject, WebSocketDelegate
{
var nodeTask:NSTask
var socket:WebSocket?
var fileHandle:NSFileHandle?
var delegate:NodeSocketDelegate?
override init()
{
//
// Launch node task.
//
let mainBundle = NSBundle.mainBundle()
// If any of these fail, we need a runtime error.
let pathToNodeApp = mainBundle.pathForResource("boot", ofType: "js", inDirectory: "node.js")!
let pathToNode = mainBundle.pathForResource("node", ofType: "")!
let pathToIndieAppFolder = pathToNodeApp.stringByDeletingLastPathComponent
//
// Create a pipe for reading the Node.js output
// (We use this as another interface for the Node app to communicate with us.)
// (This is a crude interface so I am going to limit its use to getting notified
// about the initial launch of the node.js process for now.)
//
let pipe = NSPipe()
//
// Configure and launch the Node.js task.
//
self.nodeTask = NSTask()
self.nodeTask.currentDirectoryPath = pathToIndieAppFolder
self.nodeTask.launchPath = pathToNode
self.nodeTask.arguments = [pathToNodeApp]
self.nodeTask.standardOutput = pipe
super.init()
// Listen for notifications on the pipe.
NSNotificationCenter.defaultCenter().addObserver(self, selector: "pipeHasOutput:", name: NSFileHandleReadCompletionNotification, object: nil)
self.nodeTask.standardOutput.fileHandleForReading.readInBackgroundAndNotify()
self.nodeTask.launch()
// Display key for easier debugging.
println("NodeSocket running. Key to symbols:\n")
println("\t📡 Node socket message.\n")
println("\t\t💻 Message from remote console (standard out).")
println("\t\t📃 Data received.")
println("\t\t💬 Message received.")
println("\t\t😩 Error received.")
println("\t\t🌏 Message from Pulse.")
println("\n")
}
func pipeHasOutput(notification: NSNotification)
{
//
// Called when there is console (standard out) output from the node task.
//
var data: NSData
var text: NSString
if let data = notification.userInfo![NSFileHandleNotificationDataItem] as? NSData
{
text = NSString(data: data, encoding: NSUTF8StringEncoding)!.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
if text.containsString("ns:started")
{
println("📡 \t\tNode.js web socket is ready. Connecting…")
self.socket = WebSocket(url: NSURL(string: "ws://localhost:8000")!)
self.socket!.delegate = self
self.socket!.connect()
} else {
// Indend the console text so that it is easier to delianate successive chunks visually.
text = text.stringByReplacingOccurrencesOfString("\n", withString: "\n\t\t")
text = text.stringByReplacingOccurrencesOfString("\n\n", withString: "\n")
text = "\t" + text //+ "\n"
println("📡 💻 \(text)")
}
}
// Ask the fileHandle to read in background again (this doesn’t happen automatically)
self.nodeTask.standardOutput.fileHandleForReading.readInBackgroundAndNotify()
}
func shutdown()
{
println("📡 \tShutting down. Closing web socket and terminating the node.js process.")
// Send shutdown message to Node so it can gracefully terminate Pulse, etc.
self.socket?.writeString("shutdown")
self.socket?.disconnect()
self.nodeTask.terminate()
}
//
// WebSocketDelegate methods
//
func websocketDidConnect()
{
println("📡 \t\tConnected.")
self.delegate?.nodeSocketIsReady(self.socket!)
}
func websocketDidDisconnect(error: NSError?)
{
if let theError = error
{
println("📡 \tDisconnected with error: \(theError)")
}
else
{
println("📡 \tDisconnected without an error.")
}
// Terminate the task so that the pipe doesn’t go nuts.
self.nodeTask.standardOutput.fileHandleForReading.closeFile()
self.nodeTask.terminate()
}
func websocketDidReceiveData(data: NSData)
{
let dataAsString = NSString(data: data, encoding: NSUTF8StringEncoding)?.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
println("📡 📃 \t\(dataAsString)")
}
func websocketDidWriteError(error: NSError?)
{
if let theError = error
{
println("📡 😩 \t\(theError)")
}
}
func websocketDidReceiveMessage(text: String)
{
println("📡 💬 \t\(text)")
}
}
This diff is collapsed.
File added
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment