Saturday, November 2, 2013

Sound Forge 11: no FX chain apply?

I’m a long time Sound Forge user, since the golden pre-Sony Sonic Foundry days, when the horrendous .NET Framework, a toy for script kiddies, was not needed. I’ve been following the version upgrades until today, when I gladly installed version 11. One of my most used options – applying the FX chain right away – simply disappeared. I’ve been searching around, and I found that I’m not the only one who complains about this.

There’s an alternative way to apply the FX chain through the FX Favorites menu, but it’s cumbersome and you cannot work upon the waveform while it’s open. Ironically, the new FX chain window is one of the “new” things Sony is marketing about. Well, congratulations for messing it out, Sony. I’ll pass.

I rolled back to Sound Forge 10, and I’m keeping it. Let’s see if a future Sound Forge 12 will bring that facility back.

Saturday, August 31, 2013

Plotting icons in OpenStreetMap with GPS coordinates

I’ve been working on a project with GPS data, where a map plotting would be handy. At first I thought about using Google Maps, but it’s always better go open source, and since I’m an enthusiast of OpenStreetMap, I started searching a way to do it, and I found the OpenLayers project, which is insanely cool.

My goal: plot some small images on the map (icons), and when the cursor goes over an image, a popup would appear. On my way to make it happen, I had to develop some interesting things, that I share now with everyone, in the hope that it can be useful.

The first difficulty I found was to make OpenLayers understand GPS coordinates without much fuss. To do so, you must have a coordinate transformation, which is not exactly trivial. Below is a function to make this conversion trivial, yes, so that you’ll never need to worry about it again. The map argument is the map object you’re working upon, and lon and lat are floating point numbers.
function Geo(map, lat, lon) {
	return new OpenLayers.LonLat(lon, lat)
		.transform(new OpenLayers.Projection('EPSG:4326'),
			map.getProjectionObject());
}

// Example usage:
var map = new OpenLayers.Map('myMapDivId');
map.addLayer(new OpenLayers.Layer.OSM());
var coor = Geo(map, -5.773274, -35.204948);
map.setCenter(coor, 8);
Second, the image (icon) plotting. When you plot an image at a given point, this image is centered at that point. I wanted to plot an image of a pushpin, which points at the wrong location if centered – the very end of the pushpin will point to a location below the center of the image. It had to be moved above, so that the bottom of the image was exactly over the point.

The function below creates the image and plots it with a bottom offset, if needed. The img argument is a valid image URL, cx and cy are the size of the image in pixels, and bottomOffset is a boolean value. The function is asychronous and waits the image to be loaded; use the onDone callback, which receives the new marker as argument.
function PlotMarker(map, img, lat, lon, bottomOffset, onDone) {
	var imgObj = new Image();
	imgObj.src = img;
	imgObj.onload = function() {
		var sz = new OpenLayers.Size(imgObj.width, imgObj.height);
		var off = new OpenLayers.Pixel(-(sz.w / 2),
			bottomOffset ? -sz.h : -(sz.w / 2));
		var ico = new OpenLayers.Icon(img, sz, off);
		if(onDone !== undefined && onDone !== null)
			onDone(new OpenLayers.Marker(Geo(map, lat, lon), ico));
	};
}

// Example usage:
var map = new OpenLayers.Map('myMapDivId');
map.addLayer(new OpenLayers.Layer.OSM());
var markers = new OpenLayers.Layer.Markers('Markers');
map.addLayer(markers);
PlotMarker(map, 'pushpin.png', -5.773274, -35.204948,
	true, // it's a pushpin, I want it bottom-aligned
	function(mk) {
		markers.addMarker(mk);
	});
Below you have a fully functional web application composed of three files, which displays an OpenStreetMap map at the whole page, loads points from a separated JSON file, and renders it accordingly. There’s no server-side processing involved, but the JSON file could easily be something processed by the server, which would load the data from some sort of database. I used jQuery library to handle the mouseover event which shows the popup over the images, but it’s not really necessary if you want to use something else.

1) index.html
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8"/>
	<title>Rodrigo's map</title>
	<style>
	* { -moz-box-sizing:border-box; -webkit-box-sizing:border-box; box-sizing:border-box; }
	body { margin:0; font:10pt Arial; color:#242424; }
	#mapArea { position:absolute; width:100%; height:100%; }
	</style>
	<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.0.3.min.js"></script>
	<script src="http://openlayers.org/api/2.13.1/OpenLayers.js"></script>
	<script src="index.js"></script>
</head>
<body>
	<div id="mapArea"></div>
</body>
</html>
2) index.js
function PlotData(divId, data) {
	function Geo(map, lat, lon) {
		return new OpenLayers.LonLat(lon, lat)
			.transform(new OpenLayers.Projection('EPSG:4326'), map.getProjectionObject());
	}
	function PlotMarker(map, img, lat, lon, bottomOffset, onDone) {
		var imgObj = new Image();
		imgObj.src = img;
		imgObj.onload = function() {
			var sz = new OpenLayers.Size(imgObj.width, imgObj.height);
			var off = new OpenLayers.Pixel(-(sz.w / 2),
				bottomOffset ? -sz.h : -(sz.w / 2));
			var ico = new OpenLayers.Icon(img, sz, off);
			if(onDone !== undefined && onDone !== null)
				onDone(new OpenLayers.Marker(Geo(map, lat, lon), ico));
		};
	}

	var map = new OpenLayers.Map(divId);
	map.addLayer(new OpenLayers.Layer.OSM());
	map.setCenter(Geo(map, data.center[0], data.center[1]), data.zoom);

	var markers = new OpenLayers.Layer.Markers('Markers');
	map.addLayer(markers);

	var $map = $('#'+divId),
	$det = $('<div></div>').css({
			'position':'absolute',
			'padding':'0 4px',
			'display':'none',
			'box-shadow':'2px 2px 3px #999',
			'background-color':'rgba(255,255,255,.85)',
			'border':'1px solid #AAA'
		}).appendTo('body');
	$.each(data.points, function(i, pt) {
		PlotMarker(map, pt.icon, pt.coor[0], pt.coor[1], true, function(mk) {
			markers.addMarker(mk);
			mk.events.on({
				mouseover: function(ev) {
					$det.html(pt.text).css({
						left: (ev.pageX < $(document).width() / 2) ?
							ev.pageX+'px' : (ev.pageX - $det.outerWidth())+'px',
						top: (ev.pageY < $(document).height() / 2) ?
							ev.pageY+'px' : (ev.pageY - $det.outerHeight())+'px',
						display: 'block'
					});
					$map.css('cursor', 'pointer');
				},
				mouseout: function(ev) {
					$det.empty().css('display', 'none');
					$map.css('cursor', 'auto');
				}
			});
		});
	});
}

$(document).ready(function() {
	$.getJSON('data.json', function(data) {
		PlotData('mapArea', data);
	});
});
3) data.json – assumes image “pushpin.png” exists
{
	"center": [ -5.797942,-35.211782 ],
	"zoom": 14,
	"points": [
		{
			"coor": [ -5.799500,-35.21951 ],
			"icon": "pushpin.png",
			"text": "First point<br/>Anything here"
		},
		{
			"coor": [ -5.790982,-35.19409 ],
			"icon": "pushpin.png",
			"text": "Other <b>point</b> here"
		},
		{
			"coor": [ -5.802083,-35.20877 ],
			"icon": "pushpin.png",
			"text": "Something else<br/>placed here"
		}
	]
}
Enjoy.

Thursday, August 8, 2013

Firefox 23 is slower than Firefox 22

In last June, I’ve been amazed with the Firefox 22 launching. It featured a new JavaScript engine called OdinMonkey, and particularly on Linux, the browser became really fast and smooth. The upgrade was instantly noticeable with Firebug, which became a lot more responsive.

Yesterday, however, Mozilla rolled out Firefox 23 – with a horrible new logo, without contrast and which looks blurry at small size. But mainly, to my dismay, right after upgrade, everything became slower. It felt like last year’s versions, with a sluggish performance, and essentially a pain to use. On Firebug, this is felt very strongly.

I forgot to backup my profile, but luckily the profile structure was not modified, and I was able to downgrade, download Firefox 22 again and removing this horrible Firefox 23, in the hope that they can fix it on the next version.

Update, Sep. 19:
I’ve just tested Firefox 24, and it seems to be even slower than 23. So, I’m still keeping Firefox 22.

Update, Nov. 7:
Apparently the slowness is fixed on Firefox 25, which I’m testing right now. Finally.

Tuesday, July 30, 2013

PHP and JavaScript internationalization

These days I’ve been working on a PHP/JavaScript project which needed to be translated from English into other languages. I made a search and the results were pretty disappointing. All the solutions I’ve came across were either too complicated, too heavy or too messy. I wanted something more hygienic, that could be easily integrated into any project, so I ended up writing my own.

Basically, all you have to do is add a subdirectory called “i18n” (or any other name you want) and copy the “i18n.php” file there, then create a file to each language you need. One of those language files will be your default – probably the English one –, where the strings will also serve as the mapping keys. The other language files will simply have all the lines, one by one, translated.

Once the “i18n.php” file is included into your PHP script, you’ll have to set up the translation by calling i18n_set_map(), choosing the source (the default) language file, and the target language. And it’s done. Every string passed to the I() function will be translated, both in PHP and JavaScript.

There is a comprehensive example on the GitHub repository, where I published everything under the MIT license, in the hope that it can be useful to someone else. The repository is at github.com/rodrigocfd/php-js-i18n.

Saturday, July 20, 2013

Sibelius 7 sucks

As a musician with classical training, I love sheet music. They are not only beautiful pieces of graphic art, but also great repositories of musical knowledge, which are always ready to have music pulled out of them. And music writing is universal: sheet music written in China is the same written in Canada.

Obviously, when it comes to computers, I always was interested in sheet music editors. My first editor was Encore, a very simple one. But soon I moved to a more powerful editor: Sibelius 2. And since then, I’ve been a faithful Sibelius user. Well, up to version 6.

Sibelius Software was acquired by Avid, know for its sluggish Pro Tools. Unfortunately, Sibelius 7 suffered a huge shift in development direction, jumping on the ribbon bandwagon – the single worst thing ever invented in computer user interface history – and bringing up a very confusing and keyboard-unfriendly screen. Now, all the actions and option dialogs – previously organized into regular menus, easy to reach with keyboard shortcuts only – are spread among the ribbon tabs, with distracting and childish icons, wasting precious screen space and requiring you to execute many, many additional mouse clicks while searching for something among that mess. Oh, and there’s still a File ribbon tab, with even more additional tabs at left and options distributed like mucus dropped from a strong sneeze!

But Sibelius 7 didn’t change only the interface, they also brought improvements, right? Wrong. There is only one improvement, relative to text flowing inside textboxes. Everything else is insignificant for music writing. I felt really ashamed by watching the what's new videos from Sibelius Software, with nothing new to show besides that horrible user interface. Don’t they have some critical sense, at least?

So it seems that I’m stuck with Sibelius 6, which is a bit slow, but it’s usable. Well, until some other company comes out with something better. And without a ribbon.

Friday, June 7, 2013

Command line password prompt in PHP

These days I’ve been writing a quick command line script in PHP, and at some point I needed the user to type username and password to authenticate in some remote account. The standard way to prompt for a password in Linux is to hide the characters as the person goes typing, and I wanted that feeling on the script.

I assembled some code from here and here and I wrote a small function which prompts for username and password and returns an stdClass, which I share here:
function PromptUsrPwd()
{
	fwrite(STDOUT, 'Enter user name: ');
	$usr = trim(fgets(STDIN));
	$command = "/usr/bin/env bash -c 'echo OK'";
	if(rtrim(shell_exec($command)) !== 'OK') {
		die("Can't invoke bash.\n");
		return null;
	}
	$command = "/usr/bin/env bash -c 'read -s -p \"".
		addslashes("Password for $usr:").
		"\" mypassword && echo \$mypassword'";
	$pwd = rtrim(shell_exec($command));
	echo "\n";
	return (object)array('usr' => $usr, 'pwd' => $pwd);
}
This is an usage example. Run it on command line to see it in action:
$credentials = PromptUsrPwd();
echo 'Your name is '.$credentials->usr."\n";
echo 'Your password is '.$credentials->pwd."\n";

Monday, May 6, 2013

Brazilian progressive music

Well-made progressive music is just amazing. There’s not much to write about this one – lyrics (see here and here), arrangements, actual playing, mixing – there are no flaws I can spot. I’ll just leave this here and appreciate:



Unfortunately the other songs of the band are not good as this one – not even close, actually. But this very one song is so exceptionally good that the guys can die in peace.