Make MacOS keys familiar to Windows

Standard

I have recently started using a OSX installed macbook pro work for my work. It is a performance beast but the main environment I’m used to up to this point was Windows. I had a hard time getting used to the key layout, especially the command key. I’m using Macs occasionally for mobile Safari debugging etc. and could handle short periods of Mac use without a problem (Don’t want to remember closing the app when trying to make an “@” on a Turkish keyboard by trying right-ALT (which is apparently not) + Q). Having it as the main environment on the other hand is troublesome for me.

I did a quick online search and found a great tool called Karabiner (https://pqrs.org/osx/karabiner/). You prepare an XML file that defines the key binding and it handles the rest. I’m mainly using IntelliJ products which provide a Visual Studio key binding. It works very good for most of the part but cannot properly bind CTRL + actions such as word selection and navigation. Although the bindings are correct they refuse to work with CTRL key only (an OS level low level binding maybe?) so I’ve used different binding for such cases and redefined them in IntelliJ keymap.

I’ve tried to bring as much as possible to the Karabiner XML to make reconfiguration easier (It is possible to make some binding on OSX level as well). I hope the bindings I’m using become useful to others that are planning to switch to OSX. At least it will provide a starting point for simple Karabiner configuration. You can get it on github: https://github.com/anacierdem/MacWinKeys/

Simple Proxy Server Using Node.js to Bypass CORS

Standard

Node.js is a javascript runtime based on Chromium’s V8 javascript engine. It is really simple to create a basic HTTP server using the node.js API and a web based proxy is just an HTTP server that relays incoming requests back to the original recipient. So we will capture the requests and forward them using a an http.request.

There are already programs to be used as debugging proxies (such as Charles, Fiddler, mitmproxy) but they are often limited and it is hard/complicated when it comes to composing a little bit complicated rules. For example once I needed a simple rule that repeats the origin of the orginal request in the proxied response to be able to circumvent CORS restrictions whentesting a web application. Sometimesit is easier to write a little bit of javascript code if you know how.

#!/usr/bin/env node
//Import the http module
var http = require("http");

//Create the server listening on port 8888
http.createServer(function(request, response) {
	//Log the URL for debugging etc.
	console.log(request.url);

	//Create a new http request with the data at hand
	var parsedURL = require("url").parse(request.url);
	var proxyRequest = http.request({
		port: request.port, 
		host: request.headers["host"],
		method: request.method,
		headers: request.headers,
		path: parsedURL.pathname + (parsedURL.search ? parsedURL.search : "")
	})

	//When there is a response;
	proxyRequest.addListener("response", function (proxyResponse) {
		proxyResponse.on("data", function(chunk) {
			response.write(chunk, "binary");
		});

		//End the response
		proxyResponse.on("end", function() {
			response.end();
		});

		//Manipulate some headers - Here we repeat the original requests origin to the fake response
		if(request.headers["origin"]) {
			proxyResponse.headers["access-control-allow-origin"] = request.headers["origin"];
			//Set any other headers you need
			//proxyResponse.headers["access-control-allow-credentials"] = "true";
		}
		response.writeHead(proxyResponse.statusCode, proxyResponse.headers);
	});

	//return a 404 when the forwarded request throws an error
	proxyRequest.on("error", function(err) {
		response.statusCode = "404";
		response.end();
	});

	//Copy any data in the original request to the forwarded request
	request.addListener("data", function(chunk) {
		proxyRequest.write(chunk, "binary");
	});

	//End the proxy request
	request.addListener("end", function() {
		proxyRequest.end();
	});
}).listen(8888);

I have also included a shebang to be able to start the proxy server from the command line (on unix like systems) easily. This short script only requires that node.js is installed on the system and will immediately start working as you run it. Then all you need to do is to direct your traffic to http://localhost:8888 (I am using SwitchyOmega extension on Chrome).

This simple example does not support a secure connection so you should not redirect HTTPS traffic to this proxy. It will not be possible to do so without registering a certificate with your end-point (e.g browser) and handling secure connection on node.js. Now, I use this basic proxy server whenever I need a fairly complicated response rule or a very simple proxy. Other than that, to view request/response details regular debugging proxies will work just fine.

Standalone Javascript Application With Chromium

Standard

JavaScript is becoming more and more popular every day and I was wondering if I could make a standalone javaScript App. I knew that a Chromium (http://www.chromium.org/) portable package has a “kiosk” mode which disables many of the integrated UI.

Next I decided to use a Chrome App together with Chromium (Portable version) and managed (after several fails and testing) to make it run locally (without a custom build) with full NaCl (Native Client) support.

The generated app can also be published on Chrome Web store and many UI functionality can easily be programmed using Javascript like developing a web page. NaCl opens the possibility of using low level stuff when needed. The Chromium App allows some customizations via a “.ini” file named exactly as the main executable (mine was in App\AppInfo\Launcher) and mine looks something like this; (Documented at portableapps.com)

[Launch]
ProgramExecutable=Chromium\32\Chrome.exe
DirectoryMoveOK=yes
MinOS=XP
SingleAppInstance=false
CommandLineArguments=--enable-local-file-accesses "../../../start.html" --load-extension="../../../Main"
SplashTime=0

There is a folder named “Main” alongside the main executable. Above commands disable the splash screen, enable local (file:\\\) accesses, load the application who’s manifest is in Main folder and starts the browser from “start.html”.

The manifest is;

{
    "key": "***",
    "name": "Test App",
    "description": "",
    "version": "0.1",
    "manifest_version": 2,
    "app": {
        "launch": {
            "local_path": "index.html"
        }
     },
    "permissions": [
        "tabs"
    ]
}

We need tabs access to be able to close the application. “start.html” is there to be able to start our Chrome App in the first tab opened by Chromium and reads:

window.location = "chrome-extension://apdfllckaahabafndbhieahigkjlhalf/index.html";

Here, “apdfllckaahabafndbhieahigkjlhalf” is the AppId corresponding to the key in the App’s manifest.

In “index.html”, I have;

//disable context menu
document.addEventListener("contextmenu", function(e) {
    e.preventDefault();
});
//close new tabs
chrome.tabs.query({},function(a) {
    if(a.length > 1)
        chrome.tabs.remove(a[a.length-1].id);
});
//exit button
document.getElementById('exit_btn').onclick = function () {
chrome.tabs.getCurrent(function(a){
    chrome.tabs.remove(a.id);
})};

“exit_btn” successfully exits the app by closing the single available tab and the above code block prevents opening of new tabs when the application is re-executed while running.

Chromium shows the API key warning if none set and to prevent this I use an AutoHotKey script to set some Environment variables and start the application;

EnvSet, GOOGLE_API_KEY, no
EnvSet, GOOGLE_DEFAULT_CLIENT_ID, no
EnvSet, GOOGLE_DEFAULT_CLIENT_SECRET, no
Run App.exe

Finally, to disable developer tools, the “Preferences” file that is located under “Data\Profiles\Default” is edited and

"devtools": {
    "disabled": true,
    "split_location": 256
}

is added if not existant.

With these configuration, I’m able to start a custom web app fullscreen without any pre-installed software on Windows. I did not have time to test the same concept on any other operating system but I’m pretty sure that it’ll work similarly. Whit this tool at hand, using naCl and WebGl, even high (relatively) performance games can be made… Currently the only drawback is that chromium continues to run in the background indefinitely. Dev channel have a processes API to solve this problem here.

Raspberry Pi Film Camera

Standard

Found an old (actually late 70s) TV camera and did my own mod. Removed most of its guts. Removed the lens on the picamera and mounted the camera module on the lens of this monster. Writes videos to an external USB card reader. It is fully programmable so I can make timelapse, stop-motion and stuff.

Since the cost of a quality raspberry pi sound card is a little too expensive, I decided not to use this for daily shooting, instead I’ll use an external audio recorder with a clapperboard etc.

Runs on a Li-Po battery and can be used as long as 2 hr with 1500 mAh capacity. The old analogue iris mechanism was replaced with a mechanical one which can be seen in the upper part of the lens right integrated on the handle.

I’ve used many of the camera’s original switches and interfaces to control the pi over GPIOs.

Thinking of replacing the CRT viewfinder with an LCD screen which is on its way from china. Focusing with the onboard CRT is really hard. I’ll update as the new screen is mounted. (This modification is done, I’ll update soon)

One of the hardest part on the software side of matters was to make sure there are no dropped frames in the output. I’ve tried many methods to detect dropped frames without much success. Picamera firmware reports minus infinity integer occasionally as DTS and even getting hold of a good timestamp information was not possible at the time. Finally I’m rather convinced that picamera will not drop frames as long as the media write speed is sufficient. Haven’t tested it for long-time recording and a separate audio track but I’ll report the results as soon as I do.

As a final note, since the pi’s image sensor is so small the image output compared to a 35mm film, corresponds to about 120-130mm lens. Happily a wide angle adapter that fits the 57mm filter diameter is also on its way, which will widen the output to 60mm. (wider lens atapter get very pricy very quickly) (This modification is also done and I’ll update soon)

To summerize, this was a fun and challenging process and I’m rather impressed with the results. I’ll post any when I have time to shoot something meaningful.