Guffaw

Reading a Wired article about Ubuntu’s latest attempt to do things its own way, by developing a display server of it’s own, there’s a hilarious quote in there:

“This isn’t the first time the Ubuntu team has decided to go its own way. They’ve been catching flak ever since the company created the distribution by forking the Debian distribution. But the most significant example is Unity, a user-interface shell that runs on top of GNOME in place of the traditional GNOME shell. Unity was met with mixed reactions from users.

Unity may make more sense to users now that Ubuntu Touch has been unveiled. The trouble is Ubuntu is venturing further and further from the Linux tools used by the greater community.

What’s the problem with this? Isn’t freedom of choice a part of the spirit of open source development? Yes, but duplication of effort also flies in the face of the open source ethos. (emphasis mine) One phrase regarding the creation of Mir that came up over and over again in comment threads and discussion boards is “not invented here syndrome,” a term for “reinventing the wheel” when there is no compelling technical reason to do so. Rather than improve an existing project that does what Canonical wants, the company is investing resources in its own pet project.”

I call shenanigans on that.

It’s actually, unfortunately, a truth that petty factionalism is one of the underpinnings of the open source ethos and has been since the beginning. It’s why there’s KDE (“Experience Freedom!”) and GNOME (“Freedom for Everybody”), and why there were at some point a half dozen different audio daemons, two different audio driver architectures (OSS vs ALSA), and why there’s glibc and eglibc. It’s why a binary compiled for glibc won’t “just run” on any Linux system you throw it at. It’s why binary incompatibilities exist, even though the source code is exactly the same. It’s why I don’t, generally speaking, run Linux on a desktop anymore. Because “it just works” usually isn’t the first thing I think of when I reach for a Linux desktop anymore, I worry more about the cases where it doesn’t, and I end up blowing a weekend googling to find out why. Of course, the server stuff runs pretty well and serves its niche incredibly well, and if your favorite time is spent in emacs, or coding to a webserver, it’s fine.

But that quote is just awesome, because it’s just not true. Even in the early days, actually probably even now, Richard Stallman was always bitching and moaning (mostly, it seemed, out of jealousy) about the uptake of the Linus Torvalds’ Linux kernel versus his vaporware (but “free” as in freedom) Hurd microkernel. It’s the reason Debian switched from glibc, when the maintainer of glibc continuously and persistently refused to allow / derided superior open-source code contributions to that library or even allow people to really participate in the process. Another example is the LLVM compiler ecosystem versus the GNU Compiler Collection, showing that after years of stalling, and the fact that actually extending the GCC Objective-C compiler was made technically more difficult by GCC’s poor software architecture, Apple finally got fed up with the direction of GCC and decided to fund a clean-room implementation that now runs faster and produces more efficient compilation on common hardware.

Ultimately, the argument over freedom in open source development is misplaced, what developers (me) really want is stable, well-tested Application Programming Interfaces (APIs) and the three-clause BSD license. We don’t necessarily (nor do our employers, usually) want (L)GPL libraries or the baggage that comes with them, when that baggage doesn’t guarantee API stability, or the fact that those libraries have no support guarantees or unit tests, and could turn their users into alpha testers. We don’t want to use or write autoconf/automake scripts, or read caveats about building something for our systems.

At this point, duplication of effort is actually what I think open source is all about. It’s why there are countless web frameworks, without clear winners that actually do have batteries included (I’m looking at you, Django). It’s why there are so many libraries that only have subsets of a complete functionality that I’d actually like to have. It’s why these two guides are still so hilarious. So I’m not a true believer, but it doesn’t matter, because with all the infighting, nobody’s side is winning.

The only solution to this mess is more cooperation. If open source wants to win, the number of code libraries it produces needs to stop bifurcating, and instead shift into reverse, consolidate, and stabilize, with more effort being focused on fewer projects and clear winners. But that probably won’t ever happen (with one exception that I’m aware of), because although code is ultimately rational, egos are not.

Gamifying Reading

Something I’ve noticed recently about my reading habits, since I started using my Kindle again: It’s had the effect of gamifying my reading habits. For relatively-light readers like myself, I notice that I’ve been paying attention to the percentage-status bar at the bottom of the page a lot more as I read. So I do the quick math now, if I’ve read 20% of a book in a night, I’ll be done in 5 nights.

Kindle Location Bar

Playing to my self-competive side, I’d love to have that percentage change per night be ever larger, and read ever faster. It’s not something you consciously think about perhaps, but, like the progress bar on a computer, you always want it to move to the end as fast as possible. And, of course, that helps Amazon’s bottom line.

This isn’t new, you could do this with a paper book with dog-eared pages and bookmarks, but not as easily or precisely. Having that little number there, within sight as you’re reading, is akin to whispering, “Hey, you’re not done yet, you want to finish this task, don’t you?” which is incentive enough for task-oriented people.

Digitizing Cassette Tapes

So I’m trying to get some audio digitized off of tape. Unfortunately the old-school Audiograbber software that I used to use (uhh, circa 1998, when I was leaving high school) pulled the record-direct-to-MP3 feature out of their software. So, yeah, since I have a ton of RAM in my laptop (2 orders of magnitude more than I had back then!), I figured I’d just use Audacity and trade memory for time and record to uncompressed PCM, then compress. It’s a step backwards, but ho hum, that’s the rechtslage that we find ourselves in.

Of course, Audacity doesn’t come with an MP3 encoder due to royalty issues. And I didn’t really feel like downloading some random DLL from the site they link to in Brazil (where presumably the MPEG-LA doesn’t have much authority).

So I built LAME myself on Windows 8, using Microsoft Visual Studio 2012 Express, and a copy of NASM.

To get the build working, there were some tweaks that needed to be made to the Makefile.MSVC file that comes with the package. Since Audacity is a 32-bit executable, the tweaks tune it for a 32-bit output DLL.

First up, lib.exe command options at the top of the file:

MACHINE = /machine:I386
LIB_OPTS = /nologo $(MACHINE)

should be, adding Link Time Code Generation (ASLR and DEP get enabled by default, so you don’t need the /DYNAMICBASE /NXCOMPAT options):

MACHINE = /machine:X86
LIB_OPTS = /nologo $(MACHINE) /LTCG

There’s some detection of the Visual Studio 2012 environment variables you can add (you MUST use the uppercase version of the environment variable name, or nmake won’t resolve it!):

!	 ELSEIF "$(VISUALSTUDIOVERSION)" == "11.0"
!	  MESSAGE + using MSVC 11.0 32-Bit Compiler
!	  IF "$(CPU)" == "P1"
!	   MESSAGE + optimizing for Pentium (MMX) (may slow down PIII a few percent)
!	  ELSE
!	   MESSAGE + optimizing for Pentium II/III
!	  ENDIF

And then use the same sort of ELSEIF block to define some compiler optimizations:

!	ELSEIF "$(VISUALSTUDIOVERSION)" == "11.0"
CC_OPTS = /nologo /O2 /Ob2 /Oitxy /favor:blend /fp:precise /Qfast_transcendentals /Qpar /GL /GA /arch:SSE2

There’re two lines defining linker options that need to be changed from:

LN_OPTS = /nologo /opt:NOWIN98 /pdb:none
LN_DLL = /nologo /DLL /opt:NOWIN98

to:

LN_OPTS = /nologo /pdb:none /LTCG
LN_DLL = /nologo /DLL /LTCG

There’s the line defining the NASM command line to assemble certain objects, you need to change the “nasmw” command to be “nasm”, since that’s what the NASM executable is now called:

.nas.obj:
	@echo $

Then I ran the whole thing with:

nmake -f Makefile.MSVC all

And get the following error:

--- COMMON FRONTEND STUFF UPTODATE ---

Microsoft (R) Windows (R) Resource Compiler Version 6.2.9200.16384
Copyright (C) Microsoft Corporation.  All rights reserved.

libmp3lame-static.lib(psymodel.obj) : error LNK2001: unresolved external symbol
_static_assert_tab_mask_add_delta
.outputlame.exe : fatal error LNK1120: 1 unresolved externals
NMAKE : fatal error U1077: '"C:Program Files (x86)Microsoft Visual Studio 11.0
VCBINlink.EXE"' : return code '0x460'
Stop.

The offending code looks like this:

Which makes me hate the C preprocessor.

So I comment out the define's expansion. I guess it's useful, if those things ever have a size mismatch in the foreseeable future. The WTF-factor on that one feels pretty high, though, especially the preprocessor macro abuse and the fact that the two definitions are right next to each other, lending themselves to quick inspection. If they were cross-modules, or in separate files, I'd understand. (C needs to die, or learn from D)

Anyway, after that issue is removed, huzzah, it all builds:

--- COMMON FRONTEND STUFF UPTODATE ---

Microsoft (R) Windows (R) Resource Compiler Version 6.2.9200.16384
Copyright (C) Microsoft Corporation.  All rights reserved.

Generating code
Finished generating code

--=* .outputlame.exe ready *=--

rtp.c
mp3rtp.c
Microsoft (R) Windows (R) Resource Compiler Version 6.2.9200.16384
Copyright (C) Microsoft Corporation.  All rights reserved.

Generating code
Finished generating code

--=* .outputmp3rtp.exe ready *=--

   Creating library .outputlibmp3lame.lib and object .outputlibmp3lame.exp
Generating code
Finished generating code

--=* .outputlibmp3lame.dll ready *=--

BladeMP3EncDll.c
Microsoft (R) Windows (R) Resource Compiler Version 6.2.9200.16384
Copyright (C) Microsoft Corporation.  All rights reserved.

   Creating library .outputlame_enc.lib and object .outputlame_enc.exp
Generating code
Finished generating code

--=* .outputlame_enc.dll ready *=--


--=* all uptodate *=--

And there you go! Now just copy the libmp3lame.dll file into Audacity's plugins directory, select it via the Audacity preferences, and it should work.

Update: Here's the Makefile.msvc.