ongoing projects | ||||||||
#
XScreen 1992+ | A huge collection of free screen savers for X11, macOS, iOS and Android. The collection is over three decades old, and still growing! For X11, it is also the only secure way to lock your screen. | |||||||
#
Dali Clock 1991+ | A melting digital clock for Unix, macOS, iOS, Android, PalmOS, WebOS, JavaScript, and more. If I have used an OS, I have probably ported Dali Clock to it. | |||||||
#
jwzlyrics 2013+ | Displays the lyrics for the currently-playing track in iTunes or Spotify. Can also bulk-download lyrics for multiple tracks. There are many like it. This one is mine. | |||||||
#
jwztv 2017+ | We play music videos all day long at DNA Pizza, and on the DNA Lounge webcast when the club is not open, and take online requests. This software is how we do that. | |||||||
#
youtube 2007+ | Command-line tool to download YouTube, Vimeo, Tumblr or Instagram videos. Or, install the youtubedown.cgi bookmarklet to download the video you are watching from your browser. | |||||||
#
resize.pl 2004+ | All-purpose image and video resizer command line script. Resizes images or videos to fit within maximum and minimum sizes and aspect ratios; truncates videos to a maximum duration; de-rotates image EXIF; reduces the frame rate of anim-GIFs; converts anim-GIFs or HLS/M3U8 to MP4s; converts MP4s to anim-GIFs; extracts thumbnail images from videos; removes letterbox padding; normalizes audio volume; has presets for the various social media sites. | |||||||
historically significant | ||||||||
Lucid Emacs 1991-1994 | I was the primary developer of Lucid Emacs, the first variant of GNU Emacs with a real GUI and modern desktop integration. It eventually became XEmacs. (As per longstanding tradition: "why cooperation with RMS is impossible".) | |||||||
Mosaic Netscape 1994-1995 | I was one of the initial employees of Mosaic Communications Corporation, later known as Netscape. I was responsible for the Unix versions of Netscape Navigator through release 1.1. I came up with the name "Mozilla". | |||||||
Netscape Mail & News 1995-1996 |
I designed, and
Terry Weissman and I implemented, the Netscape Mail and News
clients, versions 2.0 through 3.0. HTML email is
probably my fault.
Netscape Mail was our contribution to the proof of the
Law of Software Envelopment:
"Every program attempts to expand until it can read mail. Those programs which cannot so expand are replaced by ones which can." | |||||||
S/MIME 1996-1997 | Netscape 4.0 was not my fault. During that dark period, I worked with Lisa Repka on S/MIME in an attempt to keep everyone's email encrypted and secure from the prying eyes of the government and other snoops. That didn't really work out. | |||||||
Grendel 1997 | Terry, Will Scullin and I re-wrote Netscape Mail in Java, as Grendel. That didn't really work out either: the project was cancelled before we could finish it. But we threw the source over the wall in 1998 anyway. (Here's a browsable copy.) | |||||||
Mozilla Dot Org 1998-1999 |
I was the accidental impetus for Netscape's decision to release
the browser source code, and I was one of the creators and curators
of the Mozilla Organization
during the first year of its life. We coordinated the
open source development
of the browser, which eventually became Firefox.
I resigned from both mozilla.org and from (what came to be known as) the Netscape division of America Online just before AOL took over. | |||||||
DNA Lounge 1999+ | I am the proprietor of the world famous DNA Lounge, one of San Francisco's most popular and award-winning nightclubs. It turns out that it takes quite a lot of software to run a nightclub, particularly since we have audio and video webcasts which have been running 24/7 for more than two decades. I've published bunch of my DNA Lounge-related software as well. | |||||||
smaller yet still kinda large projects | ||||||||
#
The Cyberizer 2020 | This takes a bunch of videos, finds the scene breaks in them, shuffles them randomly, and appends them back together with a burst of static between. Exterminate All Rational Thought. | |||||||
#
DNA IRC 2020 | The DNA Lounge live stream has a realtime chat component. This is that. It's not really IRC, but is a JavaScript front end talking to a trivial backend WebSocket server. | |||||||
#
Waybackify 2019 | Rewrite the links in an HTML file to point to the Wayback Machine instead of the original site. Attempts to use a contemporaneous version from the archive based on the file date (or earliest git date) of the HTML file. | |||||||
#
websock/ 2018 | A simple, very small Web Socket server. | |||||||
#
/images/scaled/ 2017 |
Resizes images for web pages on first demand, and caches the result.
There are many like it; this one is mine.
If your large images look like
"/images/A/B/ | |||||||
#
Payphone 2016 | I took an old payphone and turned it into a fun toy by putting a small computer inside of it. | |||||||
#
AAA-60 2016 | I stuck a small Linux computer inside a vintage-1982 Ann Arbor Ambassador 60 dumb terminal. | |||||||
#
streamtest 2014 | An application for testing the behavior of various streaming-network-audio players. It creates a test MP3 stream that produces metadata in various ways, to let you see which variations work with which players. | |||||||
#
Curtain 2012, 2016 | I built an Arduino-based controller so that I can open and close my apartment's curtains from the command line. This is the source code and a description of the hardware. | |||||||
#
http10proxy 2008 | Have you ever wanted to run a really, really old web browser, like one from 1994? I have. If you have, you may have discovered that they don't work with most modern web servers, because they spoke HTTP/1.0 instead of HTTP/1.1. Specifically, they don't send a "Host" header, and don't understand the "charset" parameter in "Content-Type". However, if you point one of these antique browsers at this proxy server, it will translate. (To run those old browsers on modern Linux systems, you'll also need some old libraries.) | |||||||
#
slowcat 2000-2014 |
This program reads files and copies their contents to stdout at an
arbitrary bitrate, along with other bells and whistles. It's basically
the heart of a streaming audio server: you want to serve data at
audio rates, not full network rates.
Other features include: inserting metadata either in Icecast/Shoutcast style, or with a synthetic ID3 tag; limiting the output to a byte range across the whole set of files to implement HTTP "Byte-Range" audio seeking; and bursting out the first few seconds of the output to fill the client's first buffer quickly. | |||||||
#
Web 1999+ |
A program (and web page) that generates collages from
randomly- | |||||||
#
Dada 1997-2003 | A dissociator: a program that collects statistics on bodies of text, and then generates random text based on those numbers. (There is a web version here, too.) | |||||||
wordpress plugins | ||||||||
I have a blog. It's pretty popular.
Here's some code I wrote related to that.
| ||||||||
#
WYSIWYG Comments 2022 | A WordPress plugin that replaces the standard comment submission form with a WYSIWYG rich-text editor (Trix). It includes a toolbar for bold, italic, links, embeds, blockquotes, code, and lists. | |||||||
#
Geolocate Comments 2022 | A WordPress plugin to save and display the geolocation of each commenter's IP address. Hello to all my friends in the Russian bot farm industry! | |||||||
#
Mirror Gravatar 2022 | A WordPress plugin to locally mirror commenters' Gravatars and serve them locally, rather than loading them from gravatar.com on each page load, thus both speeding things up and eliminating an off-site webbug. | |||||||
#
Base64 Shortlinks 2011 | A WordPress plugin that makes your shortlinks shorter, by encoding 7+ digit post IDs into 4 characters, and using a shorter URL prefix. | |||||||
#
Herp Derp 2012 | A WordPress plugin that herps all the derps. All comments are replaced with "herp derp". You may find that this makes my blog easier to read. You may find that it makes your blog easier to read. | |||||||
marginal hacks | ||||||||
The following are mostly small utility scripts, rather than
full-fledged applications. These are tools that I wrote for myself
to fill a personal need. This means that they are not necessarily
very polished, but possibly you'll find some of them useful. Please
take most them in the context of "one-hour hacks that have lived on
far longer than expected."
| ||||||||
#
saville 2023 | Implements Peter Saville's cryptosystem as seen on FAC73, FAC75 and FAC93. | |||||||
#
mastodon- 2023 | If you post links to your WordPress blog on Mastodon, this script will download all of the Mastodon comments and re-post them on the corresponding WordPress blog post. This is unidirectional and not realtime: it is not an ActivityPub implementation. | |||||||
#
mastodon- 2022 | Post text and images to a Mastodon account. It can also do a simple incremental backup of your own posts. | |||||||
#
mastodon- 2022 | Make "@you@yourdomain" work an alias for your Mastodon account elsewhere. (Not as useful as it sounds.) | |||||||
#
srcset-tester 2021 | IMG SRCSETs, how do they work? | |||||||
#
iTunes XML 2021 |
iTunes used to auto-update the "iTunes Music Library | |||||||
#
icbu2ics 2021 | Convert a macOS Calendar archive file (.icbu) to a standard set of .ics files (one per calendar rather than one per event). | |||||||
#
covidate 2020 | "The date is now Tuesday, March 178th, 2020." | |||||||
#
youtube 2019 | A few years back, someone hired me to port youtubedown to JavaScript. | |||||||
#
tumblr- 2017 | Upload things to Tumblr. Remember Tumblr? | |||||||
#
instagram- 2017-2022 | The official Instagram API has no mechanism for uploading photos. YOU HAD ONE JOB. This program fixes that omission. I reverse-engineered the secret, internal protocol that the Instagram mobile apps speak. It was a huge pain in the ass. Instagram Hates The Internet. | |||||||
#
facebook- 2023 | This is a stripped-down descendant of my earlier Facebook uploader that kinda-sorta still works. It can also kinda-sorta post to Instagram through the official API instead of the unofficial one. But only if the Instagram account is attached to a Facebook Business page (not a user account) and it can only post to the feed, not stories. | |||||||
#
exif- 2015-2022 | Scan a directory to find any photos taken near a given latitude/longitude, or print out the distance of each photo. | |||||||
#
jwz- 2015 | This does some simple static analysis of PHP programs to detect errors like using variables before they are initialized, undeclared globals and so on. PHP is terrible. This program is also terrible. | |||||||
#
youtube- 2014-2021 | Edit your Youtube playlists and favorites from the command line. | |||||||
#
youtube- 2014-2015 | Create a Youtube playlist from an iTunes playlist of music videos, assuming those videos contain metadata that says which Youtube URL they originally came from. | |||||||
#
youtube 2013 | Reads a list of RSS feeds and download every Youtube or Vimeo video mentioned in them, using youtubedown. It keeps a list of already-downloaded URLs to avoid repeats. Also has a killfile. | |||||||
#
ics-diff 2013 | Compare two .ics (iCal) files, and emit one with the events that are in the first but not the second. | |||||||
#
ics-handler .scpt 2012 | Many sites (like Facebook) let you export events as .ics files which you can import into iCal; however, sometimes those imported events are not editable. This application will munge them into editability prior to importing them into iCal. Open the .scpt file in the AppleScript Editor, save it as an Application, and make that application be the default application for .ics documents. | |||||||
#
itunes-rsync 2011 | For doing a partial one-way sync of iTunes libraries, using rsync, ssh and AppleScript. This script gets the contents of a playlist in the local iTunes, and ensure that those tracks (and only those tracks) exist in the library of the remote iTunes, with identical metadata. | |||||||
#
sms-backup -iphone 2010-2017 | A perl script that extracts the log of SMS messages from an iPhone (actually, from the iPhone's backups inside iTunes) and logs the messages to text files, with one file per conversation per month (analagously to the way most AIM and IRC clients archive things, instead of just dumping it all into one file). It's careful to never delete old archived messages, even if the phone's SMS log has shrunk or vanished. | |||||||
#
wppost.php 2010 | This is a command-line utility for posting to a WordPress blog. Unlike the XMLRPC interface, this does not necessitate storing the clear-text password of a WP user in a file; it relies on normal Unix access control instead. | |||||||
#
fbmirror 2010-2021 | This script can mirror posts to your Twitter account into your Facebook and Instagram accounts. There are other ways to accomplish this, using Facebook apps or other commercial offerings, but this one is mine. Longer explanation on my blog. | |||||||
#
munge videos .scpt 2008-2021 | This is an iTunes AppleScript to process newly-imported music videos. Among other things, it: marks the track as being a "Music Video"; sets the "Comments" field to the resolution in pixels of the video; sets the "Volume Adjustment" based on the video's overall audio volume; copies the year, genre, rating, and capitalization from older versions of this same track; and adds this new track to the playlists of an old track that it appears to be intended to replace; and the old version is marked as to-be-deleted. | |||||||
#
ljpost 2008-2021 | This is how I post to my blog via email. It takes an incoming mail message, extracts the images and saves them to a directory of your choice, then constructs HTML from those images and the rest of the message, and posts that to WordPress, Twitter and/or Livejournal. If there are images and they have location data in them, it marks the post with that location. It also allows you to write your text using Markdown instead of HTML. | |||||||
#
mp3dir 2007-2017 | This is a CGI that gives your web server prettier directory listings for directories full of MP3 files: instead of just listing the file names, the directory listing will include the ID3 data for name, artist, album, etc. It will also include a link to generate a zip file for each directory. | |||||||
#
id3-clean 2007 | This perl script walks through a directory of MP3 files and deletes any ID3v2 frames that aren't used by iTunes. I found that I had a lot of useless crap in my MP3 metadata, left there by whatever software happened to rip them or touch them in the past. This removes all the cruft that iTunes can't edit (since if iTunes can't edit or display it, it might as well not exist). | |||||||
#
id3-check 2007 | This perl script walks through a directory of MP3 files and points out trivial spelling differences in band names, e.g., if sometimes you used "Pixies" and sometimes used "The Pixies". | |||||||
#
tuner 2006 | This script provides remote control of Denon tuners (e.g., Denon AVR 2805, 2313CI, X2000 and similar) via their ethernet or serial port. It speaks the AVR/AVC control protocol language, and lets me, among other things, change the volume on my stereo by typing things like "tuner volume=-30dB". | |||||||
#
google-itunes 2006 | There are a zillion programs out there that will try to automatically download album artwork for iTunes tracks, mostly by searching Amazon or the Apple store, but I've found that just feeding the artist and album name into Google Images and dragging the images in by hand is the most reliable way. This script gets the list of selected tracks from iTunes, and opens multiple browser windows running Google image searches. | |||||||
#
itunes-recent 2006 | Generates a static HTML page listing the music that has been added to your iTunes library in the last 90 days. It does this by interrogating the running iTunes via AppleScript. (It's possible to generate such a list manually from iTunes by creating an "added in the last 90 days" smart playlist and exporting the list; but this script is suitable for use from cron.) | |||||||
#
picture 2005 | This program takes a bunch of images and randomly tiles them into one large image. The images need not be of the same size or aspect ratio. Back when I used a film camera, I used to cover one of my walls with snapshots, but now that I use a digital camera, I no longer have prints lying around. I wrote this program to make it easy to cover my wall with digital prints in the form of large posters. | |||||||
#
emlx 2005 | A parser for the (undocumented) .emlx mailbox files used by Mail.app on macOS X 10.4+. You can use this to convert Mail.app mailboxes back into standard BSD "mbox" files, for importing into other software. | |||||||
#
bookmark 2004-2017 |
A few bookmarklets (clickable JavaScript functions) that manipulate
the URL of the page you're looking at:
| |||||||
#
pf-mode.el 2004 | An Emacs mode for editing OpenBSD "pf.conf" files, with font-lock highlighting. | |||||||
#
multalt 2002 |
This script converts an HTML document into a multipart/alternative
mail message, with a text/plain first part, and a text/html second
part. It produces very readable text/plain parts.
The most interesting part of this script is that it contains a simple HTML parser that does a reasonable conversion of HTML to plain text. It handles most interesting tags: it does nested indentation for UL, OL, BLOCKQUOTE, etc; it handles PRE; it handles character entities; it wraps paragraphs. (It does not, however, handle TABLEs.) Quoted-printable encoding will be used when necessary. When QP is used, lines are broken at word boundaries instead of merely every 72 characters: this means that the QP-encoded text will be highly readable in raw form, unlike most QP text you've probably run across in the past. | |||||||
#
gallery 2001+ | This generates static HTML photo galleries with thumbnails. For an example of what it looks like, see the DNA Lounge photo galleries. | |||||||
#
irc2html 2000-2015 | Paste your raw chat logs into this web page, and it will convert them to pretty HTML with wrapped lines, clickable links, inlined images and so on. Works with IRC, AIM, text messages, whatever. Can produce HTML that looks like iPhone-like chat bubbles. | |||||||
#
check-links 2000-2003 | I guess everybody has written their own version of this; well, here's mine. This script checks for dead and/or moved links in the given HTML files. It parses the HREFs out of the HTML, then does a GET on each of them (not a HEAD, because that doesn't work with all sites) and prints out a list of URLs that were not retrievable, or that redirected to elsewhere. | |||||||
#
jwz-html-mode.el 1997 |
A dead-simple HTML-editing mode for Emacs. I hate the HTML mode that
XEmacs uses by default: it does too much second- | |||||||
#
gdb-highlight.el 1997 | This is a package that makes Emacs's gdb-mode much more usable by making almost everything that shows up in the *gdb* buffer be clickable, and have a context-sensitive pop-up menu of commands on the object that have been printed. (Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.) | |||||||
#
nntp-to-mbox 1997 | Have you ever wanted to convert the contents of a newsgroup into a mail folder? I did once, and so that's what this script does. Point it at your news server, tell it what group you want, and optionally, what message to start at, and it will write out a properly-quoted mbox file (the kind used by Netscape, Eudora, and just about all of the Unix mail readers.) | |||||||
#
folder 1997 | This is a script that prints out some statistics about the messages in an mbox folder, e.g., to show who the most prolific posters to a mailing list are. It prints out a table of stats sorted several different ways. | |||||||
long obsolete | ||||||||
Some old stuff that history has passed by. I've been at this a while.
| ||||||||
#
fb-to-wp- 2014-2017 | (No longer works.) If you mirror your WordPress blog to your Facebook account, this script will download all the comments posted on your Facebook account and copy them to the corresponding WordPress post. | |||||||
#
twit-backup 2014 | (I think this stopped working some time around 2018.) Backs up your Twitter direct-message conversations to the local disk, one text file per person with whom you have conversed. (Note that while Twitter provides a way to download an archive of your public posts, that archive does not include your DMs.) | |||||||
#
scrape-sxsw 2012-2015 | Reads the schedule for the SXSW Music festival, intersects it against highly-rated tracks in your iTunes, and generates an iCal calendar file of bands of interest. | |||||||
#
file-receiver 2011 |
Let's say someone has mailed you an attachment, and you need to move
that file up to your web server. Let's say you're reading your mail
on an iPhone or iPad. Since Mobile Safari | |||||||
#
ljgrabber 2010 | This script downloads an archive of your Livejournal and its comments. It can be used to import your LJ into a WordPress blog. It can also be used to set all of your posts older than a certain age to "no new comments allowed". | |||||||
#
facebook- 2010-2019 | (This mostly doesn't work any more. Delete your Facebook.) This script can create an RSS feed of your Facebook stream, your friends' photos, etc. This indignity is necessary because the RSS feeds that Facebook provides barely work. Also includes a killfile for users or apps. Can also back up your Facebook private messages to the local disk. | |||||||
#
fbcomments 2010 | This script can create an RSS feed of your Facebook stream, your friends' photos, etc. This indignity is necessary because the RSS feeds that Facebook provides barely work. | |||||||
#
Tip Calcu 2009 | My first (and last) Palm Pre application, a restaurant tip calculator. | |||||||
#
galdown 2006-2017 | (This almost certainly doesn't work at all any more.) Given a URL of a photo gallery, this downloads the largest versions of all of the photos. It understands the gallery formats used on Flickr, Facebook, Tumblr, Picasa, OvaHere, Google Drive, SF Weekly (and related sites), Instagram, and sites using SmugMug or Zen Folio. It's easily extensible for new idiosyncratic gallery formats. | |||||||
#
sms-backup 2006 | A perl script that runs sms2csv to extract the log of SMS messages from a Palm Treo and logs the messages to text files. | |||||||
#
mvpix 2005-2008 | When I used Linux, this script was how I got pictures off of my digital camera. It files each image that it moves from the card into an appropriate directory of the form YYYY-MM-DD, and does some clever tricks to divide multiple "sessions" on the same day into different directories: e.g., when 30+ minutes has passed between photos, it starts a new directory. It worked on both Linux and macOS, though these days I use Lightroom. | |||||||
#
wgetn 2004 |
A wrapper for wget to
download numerically contiguous URLs based on a format string; for example,
"wgetn https://host/ | |||||||
#
mork 2004 | This script lets you extract the URLs from your Mozilla history file, sorted by last access time. There were scripts to do this with every version of Netscape Navigator, because it stored history in a straightforward Berkeley DBM file. Sadly, the Mozilla folks saw fit to replace that with a brand new database called "Mork" for which no tools exist. So I wrote this to parse Mork and spit out the URLs. Mork sucks. | |||||||
#
validate 2003-2015 | A small HTML validator: really all this does is make sure your tags are balanced, that your tables aren't missing TRs around the TDs, and that the local files that any relative URLs point to exist. There are much more fully-featured validators out there, but I haven't found them very useful: when all I want to know is "you left out a </UL>", they tend to spend their time whining at me about "where's your DTD?" and similar nonsense. | |||||||
#
scrmable 2003 |
I raed a scrmabled-up peice of text taht cliamed that
| |||||||
#
Cheese 2002-2004 | A selection of tools for "screen-scraping" web pages to create RSS feeds. Back in the days before every web site provided an RSS feed, this was useful for creating your own feeds from their HTML. | |||||||
#
lightlab 2002 | X11 only. This is a hybrid GTK/OpenGL program for experimenting with the OpenGL lighting model. It lets you set colors and positions of lights and see what effect they have on a textured, rotating teapot. | |||||||
#
Gronk 2001-2005 | (Now-obsolete) MP3 Jukebox software for Unix, from the days before I used iTunes. | |||||||
#
Linux Kiosks 2000-2009 | For many years, DNA Lounge included public internet kiosks; this page explains how I constructed and secured them. | |||||||
#
gsend 2000-2004 | X11 only. Obsolete. This is a simple standalone GUI mail composition tool for Unix. The 4.0-era versions of Netscape and early versions of Mozilla and Firefox didn't do anything sensible by default when you clicked on a mailto: link. This program could be used as the handler for those URLs. | |||||||
#
jack 1997 |
A predecessor of the XJack hack from
XScreenSaver;
I won't spoil the joke, but will instead just tell you:
| |||||||
#
worth 1996-1998 |
Do you hate your job? Are you only still there because you're waiting
to vest? I feel your pain, brother. The only thing that kept me from
leaving Netscape in 1997 and walking away from a dumptruck full of cash
in frustration was this script. I ran this every morning for at least
a year: it prints out the following motivational message:
Hang in there, little trooper! Only As I'm not maintaining this any more, you may also be interested it a descendant of it over on dzm's site. He's added more features. | |||||||
#
XKey 1992-2005 | A (now-obsolete) program for re-mapping your keyboard on Unix. | |||||||
#
BBDB 1991-1995 | In 1991, I wrote this program, "The Insidious Big Brother Database", which was an address-book and note-taking system that was tightly integrated with the Emacs mail and news readers. It was pretty popular until 1997 or so when even the last hold-outs stopped reading their mail in Emacs. | |||||||
#
MOST-POSITIVE-BIGNUM 1990 | It is 1,223,146 decimal digits (which is 1.0e1223146) and the object representing it consumes 524 KB of RAM. | |||||||
#
audio-tape.ps 1988-1994 | This prints j-cards for cassettes, cartridge tapes, 8mm tapes, DATs and CD jewel cases. It does all kinds of automagic font scaling and has the ability to include graphics. It is implemented completely in PostScript. This was one of the first popular programs I ever distributed online, way back in 1988. I haven't touched this since 1994, when I stopped using cassette tapes. | |||||||
#
video-tape.ps 1988-1991 | The companion PostScript program for printing labels for VHS video cassettes. Last modified: 1991. | |||||||
#
Lisp Machines 1985-1993 | Back before the Computing Dark Ages of the Nineties began, I hacked on Lisp Machines. If you've still got an Explorer or Symbolics, you might find some of the stuff I wrote in the good old days useful. It's archived in the CMU AI Repository. |