Vote for Noteflight (and come to FITC 09/Toronto)
March 31, 2009 on 1:46 pm | In Flex, Programming | No CommentsI’ll be speaking at FITC ‘09 in Toronto later this month, which I’m really excited about. I will be talking about building graphical editors on the Flash platform (using Noteflight as well as other non-music-related editors as examples) and showing how to do this on top of the open-source Moccasin framework.
Anyway, I just returned from biking in Arizona to find that Noteflight had been nominated as a Finalist in the FITC 09 award category of Technical Excellence. FITC has a popular-vote aspect of these awards in which people can vote for a set of “People’s Choice” winners, separate from the judging process.
I hereby shamelessly ask for your vote at:
If elected, I promise there will be a chicken in every pot, plus a quick, painless end to the recession through a new government-mandated sedation program.
Oops, I’m Speaking Again (at Boston Flex UG)
March 5, 2009 on 8:24 pm | In Flex, Programming | 1 CommentI’ll be talking on Tuesday, March 10 (that’s in 5 days) at the Boston Flex User Group’s monthly meeting. The subject: building graphical editors!
I’ll be talking about the architectural adventures encountered in building Noteflight, the first full-featured online music notation editor. I’ll then talk about how some of the ideas used there have been distilled into the Moccasin open source framework in Flex. I expect that we’ll build a new feature into a sample graphical editor right on the spot, as a live coding example. Finally, I’ll show a little bit of RedLine, a new interactive site-building tool based on Moccasin that I created with others at Infrared5.
Hope to see you there!
Why Music Notation is Free Now
February 26, 2009 on 2:23 pm | In Music, Programming | 2 Comments(This is a cross-post from blog.noteflight.com.)
I was thinking the other day about Noteflight, and the most frequently asked question of all — so frequent, it should probably go in our FAQ: “How can you make money if your notation software is free”?
I’ll answer that question somewhat indirectly, with an observation followed by another question.
There is a constant trend in the evolution of software. Our expectations of software value received per dollar spent are constantly being raised, whether we are aware of it or not, and online use has a lot to do with it. Part of that process is a shift in perspective that I’ll summarize this way: “Yesterday’s application is tomorrow’s component.”
Let’s look at a familiar example: word processing. Way back when, there was a program called Microsoft Word. Hey, there still is — and it still ain’t cheap! But I’m talking about Word 2000 right now, not MS Office 2008. Its main toolbar looked like this at the time:
And here’s a toolbar from one of those ubiquitous online “rich text editors” that you see in your browser all the time now, everywhere from blogs to email programs to content management systems:
So, back to the original proposition: do you pay anything for an editor like this, that you use in an application whose main purpose is to do something else, that’s larger-scale and more important to you?
Of course you don’t pay for that. You unthinkingly click the “B” button to make your text bold, never giving a thought to the fact that Microsoft used to charge a steep price for functionality like that, back in the day. As you do this, you are not thinking, “wow, I’m doing word processing!” You are using the editor to write your friend an e-mail, or to create some course content for your students, or to make up a document that you are storing online in Adobe Buzzword, Google Docs, etc.
This neatly sums up what Noteflight is all about. What you should pay for isn’t the raw ability to compose and edit music notation on a computer: it’s the software around the editor that matters. Music notation software is going to be free now.
Flash 10 Audio in IE7 Recovers Consciousness
February 25, 2009 on 1:57 am | In Flex, Programming | No CommentsAdobe released their long-awaited fix to the dreaded FP-985 crasher bug in today’s Flash Player 10 update release, a/k/a Nemo (see my previous post on the subject). The new player seems not to have broken anything else audio-related either. Thanks, Flash team! (Can we developers get a debug player, please?)
As to the other problems plaguing Flash 10 audio on Windows, well, the jury is still out on whether those have improved with the new player. We at Noteflight have been receiving a regular stream of support emails complaining about output not working on Windows. We have typically been asking these folks to turn on a configuration setting that reverts the audio output approach to Flash 9-based APIs, which always makes their problem go away. Now that the new player’s been released, we’re going to try a different approach and ask our users to upgrade to the new Flash Player. If this works, we’ll be really happy that Adobe fixed some bugs affecting configurations found in the field, but not in our lab. If this doesn’t work, well… brace yourselves for some more long, dissatisfied posts here. I’m hoping for the best, though.
Flash Audio IE7 Bug: Open Letter to Adobe
January 10, 2009 on 2:08 am | In Flex, Programming | 1 CommentHi, Adobe Flash Player Development Team. Let me open with a positive statement that is not at all token in nature: you people rock. Both in general and in the specifics. Really, you do. You have created something that has changed the world for the better, and has allowed some great software to be built. Needless to say, I couldn’t do what I’m doing without you. I thank you for that.
Nothing’s perfect, though, eh? That’s why we all have bug databases. And I further applaud you for opening yours up to the public, which takes a real dedication to openness and also some serious resources to maintain. Now, about that nasty FP-985 bug…
FP-nine-eighty… what? What’s that one, you say? It’s all right. I understand. You have many bugs and many important customers. Let me remind you, all the while retaining my pleasant, smiling demeanor.
It’s the one that crashes IE7 if you have Flash applications in more than one window which use the wonderful brand-spanking-new dynamic audio API that was rolled into Flash 10 at the eleventh hour. You know, the bug that cripples the API which finally allows Flash applications (like mine and many others) to synthesize sound, not just play back canned audio clips. The bug that cripples the API which begins to put the audible on a par with the visible in the Flash platform.
Yeah, that bug.
Please fix this crasher. I’m asking nicely. Please.
If the Bitmap class crashed IE, I know you’d be all over it. If ColorTransforms crashed IE, you’d be all over it. Well, Sounds crash IE. So…
…thanking you in advance…
... . . . j
Talk on Flex Automation Framework at Boston Flex UG
January 8, 2009 on 6:20 pm | In Flex, Programming | 3 CommentsMy friend Eric Hilfer of Tom Snyder Productions is going to be giving the next Boston Flex User Group talk on Tuesday January 13, and I honestly expect this to be one of the most useful and informative talks that we’ve had so far in the UG. This is partly because Eric combines brilliance with a talent for communicating ideas, and he’d be worth seeing even if he was talking about something everyday. However, he is not talking about an everyday subject: he’s presenting on one of the most useful and (unfortunately) most obscure aspects of Flex, namely the Flex Automation Framework. This framework is a set of capabilities built into Flex that allow automated operation (and hence, repeatable testing) of a Flex-based user interface. How many people do you know who have built real, working test suites for complex applications using this mechanism? I know exactly one: Eric. So… my point is: if you’re building something in Flex and you care about its quality, you should come see this talk!
Live (or not so live) on The Flex Show
December 19, 2008 on 1:48 am | In Flex, Music, Programming | 1 CommentStarting today, you can catch me on episode 63 of The Flex Show, in which the effervescent John Wilker and Jeffry Houser interview yours truly about Noteflight, Flex, and I forget what else — it was taped a few weeks ago, which feels more like several years given the wealth of activity that was packed into it. I think I might take a listen right now, to find out the exact manner in which I embarrassed myself.
A Flash “Clipboard” using Local Shared Objects
December 12, 2008 on 5:48 pm | In Flex, Programming | 6 CommentsI spent a good part of yesterday implementing a new global clipboard feature for Noteflight using local shared objects or LSOs. These cookie-like constructs are often used to persist application-specific data across multiple sessions, so that when you close an application down and then restart it later, it resumes in the same state you left it. What I haven’t seen much of (and haven’t done before myself) is use LSOs to communicate data between completely different instances of the same application running at the same time. It does work, and seems to work well.
Noteflight is a Flash-based music notation editor, and one of the most often-requested features has been the ability to cut, copy and paste between different documents. These “clipboard” operations already worked within a single session editing a single document. However, the clipboard contents did not survive across edits to a series of documents, nor could they transfer between different documents open in different windows. In effect, each copy of the application had its own private copy of the clipboard, initialized to emptiness. Not surprisingly, users don’t like these limitations.
It seemed clear that LSOs would be a good vehicle for this enhancement. We would write the clipboard to an LSO on every cut or copy, and read it out of the same LSO before every paste. This would not be exactly like a real native system clipboard (since it would be separate from the system clip that contains text, images, etc.) but for the purposes of Noteflight it would seem a lot like one. The challenges we expected to solve (and did) were as follows: serialization, keeping LSOs small, handling LSO failure gracefully, and application version skew. There were of course a couple of major surprises, too!
Serialization. All LSOs are stored in files, and must serialize their data. They do so using the AMF3 protocol. ActionScript 3 defines how one can manage the serialization of arbitrary Objects using the [RemoteClass] and [Transient] metadata tags (be sure to look those up if you are thinking of serializing objects in a Flex application). I’ve used them before, but the special problem here was that the clipboard data structures had already been designed and were quite complex, with a number of potential references to objects sitting “out in the application”. Serializing any of those would result in lots of irrelevant data getting “dragged in” to the LSO and bloating it, so they’d have to be marked as transient. It would be also necessary to make sure that each and every class requiring a [RemoteClass] tag received it. Getting all this right in a short amount of time seemed unlikely.
Fortunately I had plenty of existing code to serialize the objects in the clipboard to XML and back, since Noteflight persists musical scores as XML. So I used Flash’s handy IExternalizable interface to take advantage of this. This is a great technique that allows you to decide how your objects will be serialized. Basically, what I did was kind of like this:
[RemoteClass]
public class AppClipboard implements IExternalizable
{
private var _data:AppData; // contents of the clipboard...
public function writeExternal(output:IDataOutput):void
{
output.writeObject(XmlWriter.toXML(_data).toXMLString());
}
public function readExternal(input:IDataInput):void
{
_data = XMLReader.fromXml(new XML(input.readObject()))
}
}
(Note the [RemoteClass] tag — you still need it even if you use IExternalizable, or Flash won’t reconsititute the class of your object when you read it back in again.)
With this code written, when you setting one of your shared object’s data properties to an AppClipboard, like this:
mySO.data.contents = myAppClipboard;
then the writeExternal() method is implicitly used to serialize that object. Same deal goes when reading the shared object back in: readExternal() gets used.
Next challenge:
Keeping the data size low. since there is a default 100K limit on LSO storage. XML has its disadvantages, and verbosity is certainly one of them. I needed to compress my serialized objects somehow. I found a nice way to do that, which works for any serializable objects at all (whether you use IExternalizable or not). Here’s the “write side” of the technique:
var so:SharedObject = getClipboardSO(); var bytes:ByteArray = new ByteArray(); bytes.writeObject(_clipboard); // write our object to a ByteArray bytes.compress(); // compress the ByteArray so.data.contents = bytes; // and write the ByteArray instead so.data.version = NotationXmlReader.CURRENT_VERSION; so.data.creationTime = _clipboardCreationTime; so.flush();
The “read side” works similarly:
var so:SharedObject = getClipboardSO();
if (so != null
&& so.data.version == CURRENT_VERSION
&& (_clipboard == null
|| _clipboardCreationTime < so.data.creationTime))
{
var bytes:ByteArray = so.data.contents as ByteArray;
bytes.uncompress();
_clipboard = bytes.readObject() as AppClipboard;
_clipboardCreationTime = new Date().getTime();
// Flush the object after reading it so it doesn't get cached!
so.flush();
}
Here you can see the version skew detection, as well as a guard against using a "stale" shared clipboard that is actually older than the local version. That can happen if the "write side" fails to save an LSO due to size limitations, in which case we have to degrade gracefully and use the local clipboard instead of the stale shared one. This means that a single instance will still behave consistently even if it fails to transfer data to other instances.
Surprise #2: note the call to so.flush() on the read side. I did not expect to have to flush() a SharedObject after reading it. However, before putting this flush in, I found that the player would cache the SharedObject and refuse to check to see if it had been updated when reloading it by calling SharedObject.getLocal(). This caused clipboard-style transfer of data between different application windows to fail sporadically. It took a long time to figure this one out.
Minimal Apache/Rails configuration on small virtual server
November 23, 2008 on 3:31 pm | In Programming | No CommentsAs I’ve mentioned before I’m running a couple of WordPress blogs and a Rails application on Slicehost, using the smallest slice size of 256 MB RAM. Apart from Rails, this is a typical LAMP setup with Ubuntu Hardy Heron, Apache2-prefork, MySQL 5.x, PHP5. It took a little while for me to find a robust Apache and Rails configuration, though. The out of the box Apache2 config would periodically eat up all the swap space and die. So my hope here is to save others some newbie-sysadmin headaches.
Apache2. Apache2 prefork is configured to keep a certain number of processes running to respond to HTTP requests that come in. These processes are reused across a number of requests and thus tend to grow over time in their memory consumption to reach the largest amount of RAM demanded by any page served. When using mod_php, the RAM consumption is related to PHP application resources, in this case WordPress. I found that my Apache processes generally were in the 20m range for resident memory size (the RSS column in the ‘top’ display). With the out-of-box Apache2 configuration allowing as many as 15-20 processes, that meant that any large batch of concurrent requests (such as those originating from a search bot) would totally nail my machine. So the most important change I wound up making was to reduce the number of processes:
<IfModule mpm_prefork_module>
StartServers 3
MinSpareServers 3
MaxSpareServers 3
ServerLimit 10
MaxClients 10
MaxRequestsPerChild 1000
</IfModule>
This generally causes me to see around 5-6 processes running, with the possibility of as many as 10.
A number of folks have suggested I run nginx or lighttpd, which I’m sure would be a great idea, but I was strapped for time and in a mood to stick with things that have lots of online recipes and that I already somewhat understood.
Rails. Various approaches are available here as well. At first I was running the mod_passenger module, but I found this gave me a few 30m processes as opposed to the single 50m process I could get by running a single mongrel. So now I’m running a single mongrel and it’s working fine.
MySQL. Haven’t tuned this much yet, but I’m not seeing any problems.
WordPress. Caching is enabled on the advice of a number of people that this will decrease MySQL resource consumption.
Flexcover 0.81 is out
November 18, 2008 on 3:12 pm | In Flex, Programming | No CommentsA quick update: Alex Uhlmann and I have just released the latest Flexcover edition on our Google Code Project. This release supports the newly announced Flex 3.2 SDK, Flex Builder 3.0.2 and AIR 1.5.
Entries and comments feeds.
Valid XHTML and CSS.
All content copyright (c) 2006-2007 Joseph Berkovitz. All Rights Reserved.
