{"id":572,"date":"2007-08-27T15:24:15","date_gmt":"2007-08-27T22:24:15","guid":{"rendered":"http:\/\/www.latenightsw.com\/blogfs5\/?p=46"},"modified":"2012-05-05T18:25:34","modified_gmt":"2012-05-06T01:25:34","slug":"lamencoder-spawn-of-facespan","status":"publish","type":"post","link":"http:\/\/markalldritt.com\/?p=572","title":{"rendered":"LAMEncoder, Spawn of FaceSpan!"},"content":{"rendered":"<p>FaceSpan 5 is under development. That means it isn&#8217;t finished. But it also means that to some degree \u00e2\u20ac\u201d indeed, to a rather impressive degree \u00e2\u20ac\u201d it <em>is<\/em> finished. It isn\u00e2\u20ac\u2122t all there, but there is certainly <em>something<\/em> there. And that something is remarkably viable. To illustrate this, I took advantage of FaceSpan 5 to do the very thing FaceSpan 5 is intended to do \u00e2\u20ac\u201d to write a complete, useful, \u00e2\u20ac\u0153shippable\u00e2\u20ac\u009d application. In fact, I\u00e2\u20ac\u2122ve actually \u00e2\u20ac\u0153shipped\u00e2\u20ac\u009d this application, which is called LAMEncoder, and you can download it (<a href=\"http:\/\/pages.sbcglobal.net\/mattneub\/downloads\/LAMEncoder.zip\">here<\/a>) and try it out.<\/p>\n\n<p>The very fact that I was able to do this should serve as an indication of just how rich and how powerful FaceSpan 5 is already, even in its current state.<\/p>\n\n<h3 id=\"glasshalfemptyglasshalffull\">Glass half empty, glass half full<\/h3>\n\n<p>There are actually two main areas in which FaceSpan 5 isn\u00e2\u20ac\u2122t finished yet:<\/p>\n\n<ul>\n<li><p><strong>The IDE<\/strong>. By this I mean the environment in which you work as you develop your application. For example, you can drag a button into a window to tell FaceSpan that there should be a button at this location in this window. But, so far in FaceSpan\u00e2\u20ac\u2122s growth, no guidelines appear to show you when the button is at the correct position (a certain number of pixels from the edge of the window, or aligned with other widgets in the window), and you can\u00e2\u20ac\u2122t yet double-click on the button to change its title (you have to work in FaceSpan\u00e2\u20ac\u2122s \u00e2\u20ac\u0153inspector\u00e2\u20ac\u009d palettes). Also, when you\u00e2\u20ac\u2122re debugging, certain powerful Script Debugger features, such as breakpoints, aren\u00e2\u20ac\u2122t yet implemented in FaceSpan.<\/p><\/li>\n<li><p><strong>The \u00e2\u20ac\u0153widget\u00e2\u20ac\u009d repertoire<\/strong>. Certain standard interface elements that lots of people would like to use just aren\u00e2\u20ac\u2122t there yet, or are present only in rudimentary form. <\/p><\/li>\n<\/ul>\n\n<p>Despite these current limitations, the actual process of developing LAMEncoder was wonderfully fast and easy. In fact, I\u00e2\u20ac\u2122d have to say (not without a certain amount of prejudice, to be sure) that FaceSpan 5 is already shaping up to be the best application development environment I\u00e2\u20ac\u2122ve ever used. The IDE has <em>enough<\/em> functionality, and we have <em>enough<\/em> interface widgets in place, that we\u00e2\u20ac\u2122ve passed a certain tipping point of usability and usefulness.<\/p>\n\n<p>Indeed, I can specify for you quite precisely what tipping point it is. Very early on, when FaceSpan 5 was just a gleam in Mark\u00e2\u20ac\u2122s eye, he posed me a challenge: At some point, he hoped, there would come a day when I would tell him that I\u00e2\u20ac\u2122d rather develop using FaceSpan than any other development environment. That day is here. Not since HyperCard has an IDE felt so satisfying and easy to me. In a future article, I\u00e2\u20ac\u2122d like to write more about that, using the organization and development of the LAMEncoder code to illustrate.<\/p>\n\n<p>In <em>this<\/em> article, though, I\u00e2\u20ac\u2122ll just describe the finished product, LAMEncoder itself, particularly with regard to its interface. This (and using LAMEncoder itself, of course) should give you an idea of just how powerful FaceSpan is, even now.<\/p>\n\n<h3 id=\"thelamegame\">The LAME game<\/h3>\n\n<p>So. What does LAMEncoder do? It encodes WAV and AIFF files to MP3 using the freeware LAME encoding engine. I prefer LAME to iTunes\u00e2\u20ac\u2122 MP3 encoding engine. But LAME is a command-line tool, and I can never remember the commands. LAMEncoder\u00e2\u20ac\u2122s purpose is to remember and construct those commands for you. You hand it some WAV or AIFF files, and set the parameters the way you want them. Then you press the Convert button, and LAMEncoder uses the LAME engine to encode the files to MP3.<\/p>\n\n<p>If this sounds familiar, it should. The idea comes straight from the LAME Encode Automator action developed starting on p. 452 of my <a href=\"http:\/\/www.oreilly.com\/catalog\/applescpttdg2\/\">AppleScript book<\/a>. That Automator action wraps an AppleScript script in \u00e2\u20ac\u0153just enough interface\u00e2\u20ac\u009d to make it convenient and powerful. LAMEncoder wraps the same functionality in even more interface \u00e2\u20ac\u201d enough interface to constitute a full-fledged, stand-alone application.<\/p>\n\n<p>Here\u00e2\u20ac\u2122s the main window:<\/p>\n\n<p><img id=\"shot1\" src=\"http:\/\/pages.sbcglobal.net\/mattneub\/LAMEncoder\/lameEncoder1.png\" alt=\"shot1\" title=\"\" \/><\/p>\n\n<p>In the screen shot above, notice the tooltip. All the interface widgets have tooltips, and, like this one, many of them are dynamic &#8211; they change depending on the situation. Here, the tooltip is explaining why the file list area is blank. Once we hand LAMEncoder some files to convert, the tooltip will automatically read differently (as we shall see later).<\/p>\n\n<p>There are three ways to hand LAMEncoder some files to convert. One way is to press the Add File button in the toolbar at the top of the window. When you do, a standard Open File dialog appears:<\/p>\n\n<p><img id=\"shot2\" src=\"http:\/\/pages.sbcglobal.net\/mattneub\/LAMEncoder\/lameEncoder2.png\" alt=\"shot2\" title=\"\" \/><\/p>\n\n<p>In the above screen shot, I\u00e2\u20ac\u2122ve selected an AIFF file. Now I\u00e2\u20ac\u2122ll press Add. The Open File dialog closes and the selected file appears in the list:<\/p>\n\n<p><img id=\"shot3\" src=\"http:\/\/pages.sbcglobal.net\/mattneub\/LAMEncoder\/lameEncoder3.png\" alt=\"shot3\" title=\"\" \/><\/p>\n\n<p>Notice that the Clear and Convert buttons have become enabled as well. They were disabled before, because, with nothing in the file list, there was nothing useful they could do.<\/p>\n\n<p>Another way to add files to the list is to press the Add Folder button in the toolbar. When you do this, a standard Choose Folder dialog appears:<\/p>\n\n<p><img id=\"shot4\" src=\"http:\/\/pages.sbcglobal.net\/mattneub\/LAMEncoder\/lameEncoder4.png\" alt=\"shot4\" title=\"\" \/><\/p>\n\n<p>When I choose the \u00e2\u20ac\u0153wavs\u00e2\u20ac\u009d folder and click Add, any AIFF or WAV files in that folder are added to the list:<\/p>\n\n<p><img id=\"shot5\" src=\"http:\/\/pages.sbcglobal.net\/mattneub\/LAMEncoder\/lameEncoder5.png\" alt=\"shot5\" title=\"\" \/><\/p>\n\n<p>Naturally, the toolbar isn\u00e2\u20ac\u2122t the only place to access the Add File and Add Folder functionality; after all, the user could hide the toolbar, or even customize it to remove those buttons. So the same functionality is also present in the menu, complete with keyboard shortcuts:<\/p>\n\n<p><img id=\"shot10\" src=\"http:\/\/pages.sbcglobal.net\/mattneub\/LAMEncoder\/lameEncoder10.png\" alt=\"shot10\" title=\"\" \/><\/p>\n\n<p>The third way of adding files, not illustrated here, is to drag them from the Finder into the list.<\/p>\n\n<h3 id=\"htmlviewbenefits\">HTML View benefits<\/h3>\n\n<p>At this point we should pause to answer a burning question that I\u00e2\u20ac\u2122m sure you\u00e2\u20ac\u2122re racking your brains over right now: what the heck is this interface widget in which the file list appears? It clearly is not a standard Table View. And that makes sense, because the Table View is one of the important interface widgets that hasn\u00e2\u20ac\u2122t been written into FaceSpan 5 yet.<\/p>\n\n<p>This was probably the biggest limitation of the FaceSpan 5&#8217;s current state that I faced when writing LAMEncoder. It meant that I had to find a workaround means of displaying a scrolling list of the files the user wanted to encode. The workaround was to use FaceSpan\u00e2\u20ac\u2122s HTML View widget. Yes, that area in the middle of the window is actually a Web browser! LAMEncoder structures the list of files as HTML and hands that HTML to the HTML View widget.<\/p>\n\n<p>An HTML View widget is a powerful animal in FaceSpan. To see how powerful, take a look at this next screen shot:<\/p>\n\n<p><img id=\"shot6\" src=\"http:\/\/pages.sbcglobal.net\/mattneub\/LAMEncoder\/lameEncoder6.png\" alt=\"shot6\" title=\"\" \/><\/p>\n\n<p>The above screen shot displays the tooltip for the HTML View when the list actually contains some files. Notice that it has changed from the tooltip we saw earlier. Notice also that it claims we can click on a file name to play that file. Let\u00e2\u20ac\u2122s try it! We click on the last file in the list, and a dialog appears:<\/p>\n\n<p><img id=\"shot7\" src=\"http:\/\/pages.sbcglobal.net\/mattneub\/LAMEncoder\/lameEncoder7.png\" alt=\"shot7\" title=\"\" \/><\/p>\n\n<p>You can\u00e2\u20ac\u2122t hear it, of course, but in that screen shot the dialog really is playing the WAV file. That part is easy, because FaceSpan has a Movie View widget; the dialog\u00e2\u20ac\u2122s interface is nothing but a movie controller, and QuickTime knows how to play AIFF and WAV files. But how is it possible that you can click in the list of files in order to play a file? Well, as I said, an HTML View widget is a powerful thing in FaceSpan. One of the powerful things it can do is intercept the user\u00e2\u20ac\u2122s request to navigate to a link. The names of the files are links. So when the user clicks on the name of a file, that\u00e2\u20ac\u2122s a link navigation request; the HTML View hears about this, and instead of actually navigating to anything, it hands the information about the link over to the file-playing dialog, which opens and plays the file.<\/p>\n\n<p>Incidentally, the power of an HTML View is also why we can drag and drop a file from the Finder in order to add it to the list. This is quite remarkable, because in general, drag-and-drop is one of the things that isn\u00e2\u20ac\u2122t implemented yet in FaceSpan! But an HTML View is its own little world, and it already knows how to respond to drag-and-drop. When it does, this counts as navigation (basically, it counts as an attempt to open a file). In LAMEncoder, the HTML View intercepts this attempt, and instead of navigating anywhere, it effectively hands the file over to the Add File button.<\/p>\n\n<h3 id=\"encodinginaction\">Encoding in action<\/h3>\n\n<p>So now that we\u00e2\u20ac\u2122ve created a list of files to convert, let\u00e2\u20ac\u2122s actually convert the files in the list. First, we use the \u00e2\u20ac\u0153Conversion parameters\u00e2\u20ac\u009d area of the window to set up how the conversion will be performed. In this next screen shot, I\u00e2\u20ac\u2122ve decided to use CBR (constant bitrate) encoding, and I\u00e2\u20ac\u2122ve entered a bitrate value of 320 for very high quality:<\/p>\n\n<p><img id=\"shot8\" src=\"http:\/\/pages.sbcglobal.net\/mattneub\/LAMEncoder\/lameEncoder8.png\" alt=\"shot8\" title=\"\" \/><\/p>\n\n<p>Notice that the text above the popup menu has changed from <code>lame --preset standard<\/code> to <code>lame --preset cbr 320<\/code>. That text represents the command-line parameters that will actually be sent to LAME to perform the encoding. The change in the text happens automatically as you play with the \u00e2\u20ac\u0153Conversion parameters\u00e2\u20ac\u009d interface.<\/p>\n\n<p>Furthermore, however you set the \u00e2\u20ac\u0153Conversion parameters\u00e2\u20ac\u009d interface is automatically remembered by LAMEncoder when you quit, by being written into the application\u00e2\u20ac\u2122s user defaults (its Preferences .plist file); when you start up LAMEncoder again, that information is fetched from the user defaults and the \u00e2\u20ac\u0153Conversion parameters\u00e2\u20ac\u009d interface appears just the way you left it when you quit. That sort of thing, which adds a nice professional touch to our application, is extremely easy in FaceSpan.<\/p>\n\n<p>Anyway, now we press the Convert button. The Terminal opens and LAME is started, with the files and conversion parameters that we specified in LAMEncoder\u00e2\u20ac\u2122s window:<\/p>\n\n<p><img id=\"shot9\" src=\"http:\/\/pages.sbcglobal.net\/mattneub\/LAMEncoder\/lameEncoder9.png\" alt=\"shot9\" title=\"\" \/><\/p>\n\n<p>That may seem a little nerdy, but for that very reason I like it. LAME provides nice progress feedback as it runs in the Terminal, so it makes sense to me to hand over the actual conversion process to the Terminal and let LAME do its thing. Meanwhile, LAMEncoder itself is free for further use; having handed off the correct command to the Terminal, it returns instantly and sits idle. The user can even quit LAMEncoder at this point, while the Terminal chugs merrily along, encoding the files.<\/p>\n\n<h3 id=\"finishingtouches\">Finishing touches<\/h3>\n\n<p>Now I\u00e2\u20ac\u2122d like to point out a few of the finishing touches in the LAMEncoder interface that give it a full-fledged, \u00e2\u20ac\u0153professional\u00e2\u20ac\u009d application quality. First, there\u00e2\u20ac\u2122s a standard About dialog:<\/p>\n\n<p><img id=\"shot11\" src=\"http:\/\/pages.sbcglobal.net\/mattneub\/LAMEncoder\/lameEncoder11.png\" alt=\"shot11\" title=\"\" \/><\/p>\n\n<p>All the underlined blue terms are links that the user can click to go to the relevant Web pages. <\/p>\n\n<p>LAMEncoder also has a second About dialog, which properly attributes the LAME engine and provides the text of the LGPL agreement under which it can be used in an application. That\u00e2\u20ac\u2122s required, because LAMEncoder actually includes a copy of the LAME engine inside itself:<\/p>\n\n<p><img id=\"shot12\" src=\"http:\/\/pages.sbcglobal.net\/mattneub\/LAMEncoder\/lameEncoder12.png\" alt=\"shot12\" title=\"\" \/><\/p>\n\n<p>(Incidentally, the above window is the only part of LAMEncoder containing an interface widget that isn\u00e2\u20ac\u2122t really built into FaceSpan. The scrolling Text View containing the text of the LGPL is implemented through a \u00e2\u20ac\u0153plug-in\u00e2\u20ac\u009d, which is essentially a bundle of Objective-C code. Eventually, the Text View will be a native FaceSpan widget.)<\/p>\n\n<p>Next, LAMEncoder has some preferences that the user can set. When you choose Preferences from the LAMEncoder menu, the preferences dialog appears:<\/p>\n\n<p><img id=\"shot13\" src=\"http:\/\/pages.sbcglobal.net\/mattneub\/LAMEncoder\/lameEncoder13.png\" alt=\"shot13\" title=\"\" \/><\/p>\n\n<p>As you can see, we have two preferences here.<\/p>\n\n<ul>\n<li><p>First, using radio buttons, the user can decide whether to use the LAME engine built into LAMEncoder, or to use a copy of the LAME engine that may already be installed on the user\u00e2\u20ac\u2122s computer. This is because it\u00e2\u20ac\u2122s possible to compile LAME yourself, possibly using settings optimized for your processor, and we wouldn\u00e2\u20ac\u2122t want to prevent a user who has done so from using that specially compiled LAME.<\/p><\/li>\n<li><p>Second, having chosen the second radio button, it is also necessary to press the Set button and tell LAMEncoder where that on-disk copy of the LAME engine is. In this case, I\u00e2\u20ac\u2122ve specified a bogus location; there is no copy of LAME on my desktop. If I press the second radio button and try to dismiss the preferences dialog, I\u00e2\u20ac\u2122ll get an error alert:<\/p>\n\n<p><img id=\"shot14\" src=\"http:\/\/pages.sbcglobal.net\/mattneub\/LAMEncoder\/lameEncoder14.png\" alt=\"shot14\" title=\"\" \/><\/p>\n\n<p>The preferences dialog then opens again, forcing me either to use LAMEncoder\u00e2\u20ac\u2122s internally provided LAME engine or to specify a location where there really is a copy of the LAME engine on my hard disk.<\/p><\/li>\n<\/ul>\n\n<p>Finally, like any good application, LAMEncoder provides online help:<\/p>\n\n<p><img id=\"shot15\" src=\"http:\/\/pages.sbcglobal.net\/mattneub\/LAMEncoder\/lameEncoder15.png\" alt=\"shot15\" title=\"\" \/><\/p>\n\n<p>The user chooses from the Help menu, and the online help appears (in this case, it\u00e2\u20ac\u2122s a page of HTML, and opens in the user\u00e2\u20ac\u2122s default browser).<\/p>\n\n<h3 id=\"futuredirections\">Future directions<\/h3>\n\n<p>So much for LAMEncoder itself. There are two kinds of future directions I\u00e2\u20ac\u2122d like you to be thinking about.<\/p>\n\n<p>First, there are future directions for LAMEncoder. Now that this version of LAMEncoder is finished, it\u00e2\u20ac\u2122s easy to add further features. For example, right now LAMEncoder implements only the <code>--preset<\/code> subset of LAME commands (because those are the only ones I really use). It would be easy to add even more LAME commands, making LAMEncoder an even more powerful, complete front-end interface to LAME.<\/p>\n\n<p>Second, there are future directions for FaceSpan 5 \u00e2\u20ac\u201d and for you. If LAMEncoder is the kind of application FaceSpan 5 can create right now, think what kinds of application it will be able to generate in the future. Clearly, this is an application development tool worth watching. Stay tuned!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>FaceSpan 5 is under development. That means it isn&#8217;t finished. But it also means that to some degree \u00e2\u20ac\u201d indeed, to a rather impressive degree&#8230;<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"http:\/\/markalldritt.com\/?p=572\">Continue Reading<span class=\"screen-reader-text\">LAMEncoder, Spawn of FaceSpan!<\/span><\/a><\/div><\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[10],"tags":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p7AQk-9e","_links":{"self":[{"href":"http:\/\/markalldritt.com\/index.php?rest_route=\/wp\/v2\/posts\/572"}],"collection":[{"href":"http:\/\/markalldritt.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/markalldritt.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/markalldritt.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/markalldritt.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=572"}],"version-history":[{"count":2,"href":"http:\/\/markalldritt.com\/index.php?rest_route=\/wp\/v2\/posts\/572\/revisions"}],"predecessor-version":[{"id":604,"href":"http:\/\/markalldritt.com\/index.php?rest_route=\/wp\/v2\/posts\/572\/revisions\/604"}],"wp:attachment":[{"href":"http:\/\/markalldritt.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=572"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/markalldritt.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=572"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/markalldritt.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=572"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}