Tuesday, May 14, 2013

converting wonky wavs to mp3s in the osx terminal commandline via sox and lame

SoX (Sound eXchange) is a promising, mutliplatform commandline tool but like too many open source projects it makes life a pain in the ass if you want to output MP3s (because of potential licensing blah blah blah). (Audacity, the general standard for audio editing for cheapskates, has a cleaner way of enabling MP3 support but it's not really usable as a commandline tool.)

Trying to get SoX running with MP3 support proved beyond me:
1. The default download doesn't have it.
2. "Sox Wrap", a UI for withs own version of SoX won't do it, outputting a 0-byte file
3. I installed "Homebrew", a tool for installing extra software on OSX. I hoped "brew install sox --with-libmp3lame" or "brew install sox --with-mad --with-lame" might do it, but no. (troublingly, I can put --with-anystupidname and homebrew doesn't report that as a problem, so I have no way of knowing if the '--with's are working.)
4 I tried to follow the instructions at http://ggkarman.de/tech/building-sox-with-mp3-support-on-osx/ I'm not 100% sure I'm downloading the right tarballs, but when I tried to compile the sox part with --with-mad --with-lame it tells me can't find libmad, and I haven't done enough with compiling to know what I'm doing wrong.

So, the solution turned out to be downloading LAME (which besides providing libraries for other programs also has its own commandline tool) and then doing a two step process:
sox wonky.wav -b 16 better.wav
lame better.wav --preset medium better.mp3
(Sox is  much better at reading the wonky wav file, so it still has to be in the loop.)



minimal soundmanager2 quickstart

I'm proud of lowLag.js but sometimes it's overkill when you just want the flexibility SoundManager2 provides. I think I've isolated the 2 files and boilerplate code you need to just play a sound.

Copies of the files are available here: one .js and the Flash fallback. (I admit I've had some problems trying to specify alternate locations for the Flash, so it's safest to put that file in the same directory as the page itself.) So put "soundmanager2.js" and "soundmanager2_debug.swf" in the folder as the file, add
<script src="soundmanager2.js"></script>
and then in add something like
<script>
soundManager.setup({
    useHighPerformance:true, 
    onready:sm2Ready ,
    debugMode: true,
}
);

function sm2Ready(){
    soundManager.createSound({
        id: "asphault",
        autoLoad: true,
        url: "asphault.mp3"
    });
};

function sm2play(){
    soundManager.play("asphault");
}
</script>
That's it! You can see it in action. The code is a little complex because you need a callback to create the sounds after SM2 says it's ready. (There's also an "experimental feature" where the argument to url in createSound({}); can be an array of different files, if you're trying to support browsers that might not support every file format.)

(Of course for real work you should probably go to the SoundManager2 website and grab the latest files and read the documentation... this page is just for when you're in a hurry.)

Friday, May 10, 2013

OSX PROTIP: mouse-based cursor positioning in Terminal

One of the drawbacks to, say, running emacs on a remote system to edit a file via ssh was that you lost cursor positioning via mouse. NOT TRUE! On OSX, holding the option key and clicking is able to reposition the cursor, even in a crazy beast like emacs.

webscraping in PHP 101

Recently I had to make a "webscraper" web service to present a simple interface to a rather complex login and settings change for a 3rd party website that was not set up as a webservice.

A few things learned: one is http://www.hurl.it/  is a pretty cool tool for hitting faking web requests. It had some options to view each step of a login process that had a lot of redirects, and we could see where automated javascript even got in the mix.

The key turned out to be grepping out the jsessionid and using that, and the other key was not trying to skips steps in the redirection, even if they seemed like they shouldn't affect attempting to login (also, clearly printing out the response at each step was helpful, being a bit formal about it.)

We selected PHP for this. Initially I tried to get us to Perl, where I wouldn't have to look up how to do every simple task, but the LWP library was segfaulting (maybe confused by having to make the https requests? Not sure, but it wasn't worth dwelling on)

I don't like PHP... I first tried to use it in the early-2000s, where it was kind of a beta-feeling project, and it has never felt fully baked to me. Unlike Perl which has odd syntaxes that reflect its history but always feels rock-solid and with damn few "oh, Perl is this way because that was easier for the implementor of Perl to write it", PHP still feels like the Preprocessor-for-Perl that it started as. It also has a "Guess What I Mean" philosophy I don't trust... for example, the standard curl functions I used by default blast the result of the request to stdout. While I admit this may be a fairly common use case, the more Unix-ish way of doing it would be to just return the value, and then the programmer can trivially print out that result if they want.

Anyway, for future reference, here's what a POST ended up looking like in PHP
function doPOST($url,$payload){
  print "<h1>POST to $url with $payload</h1>\n";
  //open connection
  $ch = curl_init();
  //set the url, number of POST vars, POST data
  curl_setopt($ch,CURLOPT_URL, $url);
  curl_setopt($ch,CURLOPT_POST, 1);
  curl_setopt($ch,CURLOPT_POSTFIELDS, $payload);
  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
#  curl_setopt($ch, CURLOPT_VERBOSE, 1);
  curl_setopt($ch, CURLOPT_HEADER, 1);

  $response = curl_exec($ch);
//get the header as separate from the body
  $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
  $header = substr($response, 0, $header_size);
  $body = substr($response, $header_size);
  curl_close($ch);
  print "<hr>$header<hr>".htmlentities($body)."<hr><hr>";
  return $header;
}
The $payload param should be url encoded key1=val1&key2=val2 type data.... (In both iOS programming and here, I'm surprised making the coders do the encoding themselves and sending the POST raw like that is the more common option.)

Tuesday, May 7, 2013

quick ref for future self: old school servet and jsp pairing

The other week I was converting some servlets that had a lot of embedded HTML to Servlet/JSP pairs (a preferred mutant MVC variant I like called "Model 2 Plus".) So a few notes to when I have to do that again (these were from a sticky I left to make a blog entry about, hence less haphazard nature of the examples.)

In the servlet, I wanted to put some information (a ContactList instance named contacts) into the request for later retrieval:

req.setAttribute("contacts", contacts);
RequestDispatcher dispatcher = 
        getServletContext().getRequestDispatcher("/admin/test.jsp");

dispatcher.forward(req,resp);

Then telling the JSP about the object:
 <%@ page import="com.mycompany.util.ContactList" %>
and later to loop over it:
<TABLE>
<%
ContactsList contacts = (ContactsList)request.getAttribute("contacts");
for (int i=0;i<contacts.size();i++) {
Contact contact = contacts.get(i);
%>
<TR>
<TD><%= contact.getID() %></TD>
<TD><%= contact.getName() %></TD>
</TR>
<% } %>

I guess I felt more comfortable with the "do flaps" ( <% %> that execute code) and the "show flaps" ( <%=  %> that show a value) then using one of the taglibs-- yeah, having code embedded in HTML is a bit rough and less "pure", but A. I actually LIKE that my code looks/smells different than my looping markup, B. I kind of dislike having two ways of saying something, and C. I prefer to have fewer moving parts... I really liked how old school JSPs got precompiled directly into servlets, and how you could even crack open the intermediate generated servlets and see how things got translated.

Tuesday, April 30, 2013

fun with osx: "dictation & speech"

Just for fun...

OSX has a built in speech synthesizer... Macs have been "talking" for a long time, but until fairly recently I didn't realize you could just open up a terminal and type
say This is what I am saying
I knew there was a fair selection of voices (try
say -vz droid
for example) but yesterday I found out they have a bunch of accents as well! Go to "System Preferences | Dictation & Speech | Text to Speech", then under System Voice hit "Customize..." You may have to download the new voices, but some of them are a lot of fun... I like Sangeeta who speaks India-accented English. Also, some of the ones that are geared for foreign languages, like the German-speaking Anna, are cool to hear as well. (Though they will read numbers in their native tongue.)

I don't know why I find it mildly surprising that a computer voice geared at reading a foreign language speaks English with the same accent as a human who grew up speaking that language, but it's pretty cool.

Monday, April 22, 2013

java quickie: launching webpage inside chrome, specifically

I needed to open a webpage from a Java app. Some code I inherited did this:
java.awt.Desktop.getDesktop().browse(new java.net.URI(WEBAPP_URL));

Not bad but it launches the default web browser (usually Safari on OSX). Luckily this app was OSX only, so I could rely on the open command. I ended up with:

String cmds[] = {"open","-a","Google Chrome",WEBAPP_URL};
Process p = Runtime.getRuntime().exec(cmds);
p.waitFor();
if(p.exitValue() != 0){
     //show message, then try old method:                         
      java.awt.Desktop.getDesktop().browse(new java.net.URI(WEBAPP_URL));
 }

The tricky bit was breaking up the command into an array; without that, the space in "Google Chrome" was messing things up and I couldn't figure out how to make a single big command String that respect that space.

One the command runs we wait for it to finish and then go to the old behavior if it seemed to fail, according to the process exit value.