Little Things #

Made the 8-way flood fill in the CapturedImage class (which is used to find connected changed pixels) use an in-place vectorinstead of recursive calls for performance/scalability reasons.

I had previously noticed that thin vertical lines were not being picked up by the frame-to-frame difference algorithm. This turned out to be not because of the algorithm itself, but because of the despeckling that I did immediately after. The despeckling would remove any pixel which didn't have at least two non-background neighbors. In the case of a vertical line, since we'd start the scanning from the top, we'd remove the end-point since it only had a non-background pixel right below it. On the next scan-line, the same thing would happen, since this pixel had now become the end-point. The fix was to make the despeckling a two pass process. On the first pass, we simply count how many non-background neighbors each pixel has. On the second pass we remove those whose neighbor count is below the threshold of two and don't have any neighbors that satisfy the threshold. I also tweaked the despeckling so that if a background pixel was completely surrounded by non-background ones, it would be replaced with the average color of its neighbors. This removed one pixel "holes" that would throw off the thinning and stroke algorithms.

As previously mentioned, one problem with counting crossings to see how many times a pixel can be visited (in the case of stroke intersections) was that, even when the image is thinned, there can be pixels that, in their 8x8 neighborhood, don't have enough black-to-white transitions to be flagged as a crossing. Based on the Liu paper, I came up with an alternative criterion that also includes neighbors. Basically, for a pixel to be marked as supporting two visits, it must pass at least one of these tests:

  • 4 or more black to white transitions
  • 3 black to white transitions and 4 or more black neighbors
  • 2 black to white transitions and 5 or more black neighbors

When following pixels to determine which ones make up a stroke, to make sure that we went through a crossing in the right direction, we would first look for the next pixel in the same direction as the previous one that had been found. So for example, in the case on the left, the two strokes would be separated "naturally" (red and green denote the two strokes, yellow pixels are shared):

  1      1
  1      1
11111 111111
  1     1
  1     1

However, in the case of the pattern on the right, the stroke has no choice but to make a turn, and then it continues along that path, with the net separation being two unnatural strokes that each make a sudden turn.

Despite being on my third paragraph describing the problem, the actual fix was two lines long. If we keep track of the average direction for the past several points, then local changes in the direction will not have such disproportionate impact. Given some decay constant K, the new direction D' and the average direction D, the update function is D = D * K + D' * (1.0 - K)

Putting it together #

Thor in actionTo commemorate achieving a milestone of sorts, I'm including this screenshot of the four current phases that the program goes through. They are capture, differences, thinning (and separation into sub images) and stroke extraction. In the stroke images, control points are in red, strokes in random colors to help differentiate them.

As was mentioned yesterday, fixing the stroke collapsing required changing the error function to measure deltas instead of overall errors. Currently, given a point P, we find the active ones preceding and succeeding it (A and B), and compute the difference in the error function as it sampled A to P and P to B versus directly A to B (which would be the case if P were removed). Sampling is uniform, some constant K times along A to P and P to B, and 2K along A to B.

One issue is to know when to stop. Absolute error boundaries won't work since bigger strokes can have much more error and still look OK whereas smaller ones won't. Perhaps some normalization by stroke length will work.


Queueing up is in my blood #

Worked on the actual stroke simplification/collapsing today. Ported over collapse queue from mesh simplification assignment (turned it into a real C++ object finally) and made it use an STL vector for its storage instead of a hand-rolled chunked array. Collapsing seems to work to some extent, but a) it's slow and b) it's not quite right.

The speed issues seem to stem from the fact that my error function computes error across the entire stroke (overlap between it and the original thinned pixels). At each point then I store this error value assuming that that point had been removed. What I really need to store is the delta in the function when it is removed, and that way when I remove a completely unrelated point, I shouldn't have to worry this one. Not handling this updating properly is also what I think is causing the correctness issues - when I do the most thorough updating possible (update all other entries after one is removed, regardless of connectivity) I get better results.

Stroke junction, what's your [error] function? #

Working on stroke extraction. First step is to build up the unsimplified stroke, which has a control point per pixel. This isn't quite that simple, since we want to handle intersecting and forking strokes too. I decided to use an extended "visited" image, where instead of storing a boolean per pixel, we have the total number of times a pixel can be visited (for crossings this can be more than one obviously). Since we're dealing with a thinned image, this is as simple as counting the number of dark to white transitions as the neighbors are walked clockwise, and dividing by two (rounding down). This works almost all the time, with the exception of cases such as:

101
111
101

Here the center "1" has only two such transitions, but it's still at a crossing. The Liu paper (it might be useful after all) attempts to deal with such points (and other similar patterns) by also counting neighbors, so this may be something that's worth looking into when tweaking this further. For the actual walking along a stroke's pixels, we keep track of the direction that we previously went in, and look in that direction first for the next step. This lets us continue through intersections with the same stroke rather than suddenly branch off.

Implemented my error metric. Right now it regularly samples the stroke (number of strokes is based on length), adding up the sum of square differences between the current pixel and the background (so I would in fact try to maximize the value of this function). My regular sampling right now is based on distances between control points, which works OK when all I'm doing is linear interpolation for the actual stroke, but may be error inducing if I switch to Catmull-Rom splines or another interpolation method.

I also got around to trying out my old Nikon CoolPix 990, and it doesn't seem to support the kICAMessageCameraCaptureNewImage Image Capture framework message either (had also tried a Pentax Optio 550 and a Casio Exilim EX-S2). This article has a list of cameras that should support this functionality (the "Remote Monitor" feature is based on it), but I've yet to track one down.

Who needs presents when you've got a thesis #

It turned out both of those problems (certain diagonal lines not being thinned, others being removed completely) were caused by the same thing, a bug in the aforementioned c functions. It turns out that it checks of the following patterns (*'s can be of any value, red is the current pixel around which the pattern is centered):

* 0 0      0 1 *      * 1 0      0 0 *
1 1 0  or  1 1 0  or  0 1 1  or  0 1 1
0 1 *      * 0 0      0 0 *      * 1 0

These patterns look for two pixel thick diagonal lines, which although would satisfy the other criteria for not being thinned (e.g. have more than one white to dark transition as their neighborhood is traversed), they should in fact be gotten rid of. What is interesting is that the Wang paper only uses the first two patterns, even though the latter are clearly valid as well. Adding them improved results even further.

It's now tempting to try and improve the thinning even further (e.g. do a king of reverse despeckling, so that holes in an otherwise solid area are filled so they can be thinned away) or to tweak the stroke sub-image extraction (e.g. remove very small ones, but not all of them, since periods and what not get to be pretty small when they're thinned too -- maybe only those not near any big sub-images). But such refinements can wait, it is now time for stroke extraction.

However, the Liu paper is beginning to seem increasingly dubious, since it's pretty elaborate and somewhat skimpy on some details (parts of it reference another paper by the author that I can't seem to find). Another approach to consider is to mimic the method used for the mesh simplification assignment. I can build up strokes based on the thinned image that initially use every single pixel as a control point. Then, defining the collapse operation as a vertex removal, I can remove as many as I deem necessary in order of increasing error (my error metric will be pixel overlap of stroke and original thinned image). I can play around with different stroke interpolation methods (I have code for linear and Catmull-Rom from 426).

The Thinning Continues #

The annoying thing about the Wang paper is that it's not very detailed. I can't tell if it's because of space limitations when it was published (it is part of the IEEE Transactions - maybe there's a more detailed version out there), but it leaves a lot of things "as an exercise for the reader" as it were.

For example, one of the things that it requires is the number of "contour loops" (e.g. a line would have one, a hollow circle two, a figure eight three, and so on) present in the image, and their starting points. My first approach was to find an edge pixel in the image, walk along it (the paper's successor function is, given the current and previous edge pixels, walk along clockwise in the neighborhood, starting with the previous pixel, and pick the first dark pixel encountered) and mark all other edge pixels encountered as visited, and to then repeat the process until there's no more edge pixels left. However, this didn't work, because some edge pixels would be skipped over when walking along. For example, in the picture below, the red pixels would be marked off on the first pass, but the green one, though considered an edge pixel, would have to wait for another pass, causing the creation of a spurious "loop".


1100
1110
1110

The better way of doing this was to pick any background pixel, do a flood-fill (marking off any background pixels as visited) and pick any of the edge pixels encountered as the starting point. Then repeat this until there are no more background pixels left.

The paper is also cryptic in that it provides pseudo-code for the algorithm, but it doesn't say anything about why or how it works. For example, there's a function c that, from my best guess, appears to check for diagonal cases, but I'm not really sure why. It's also not very clear on the termination function when iterating. Just seeing if you pass the same point twice isn't good enough, since you can encounter it from two directions, and not in fact have completed a loop. Testing for a point plus its predecessor (to incorporate direction) seems fundamentally like a good idea, but there's still problems since points can get deleted, and what used to be its predecessor may not be there at all in the next iteration, and then we're stuck in an infinite loop.

The net result of all this is that the thinning seems to mostly work, except it doesn't sometimes thin two pixel thick diagonal lines, and it entirely decimates another type of diagonal lines (not very even/regular ones). The former I think I've tracked to bugs in the mysterious c function, but for the latter I have no idea.

Just like the Stephen King novel #

Decided yesterday that my haphazard "intuitive" approach to stroke extraction (convolution with that positive/negative kernel, stroke extraction as outlined in my presentation) wasn't really going to work. The next step was to turn to the literature that I had accumulated. Hew99 (Strokes from Pen-Opposed Extended Edges) seemed promising, but his approach of extracting opposed edges and trying to infer stroke direction seemed overly complex and not very well described in any case. He did however mention other approaches, one being the thinning-based Liu97 (Robust Stroke Segmentation Method for Handwritten Chinese Character Recognition). His results looked good, but he didn't provide any details on the thinning part of his algorithm, instead he pointed to Wang89 (A Fast and Flexible Thinning Algorithm). The paper was somewhat cryptic and/or entertaining due to its age (ooo, we shall describe the image as a matrix of pixels, quelle nouvelle idee), but the idea seemed workable.

Before I could get to the thinning, I first had to split up the difference image into sub-images, one per future set of strokes (each being a subset of 8-way connected pixels). In my quest to learn more, I decided to use the STL for a few classes that I'd need for this (hash_set and vector). The idea was fundamentally sound, but using hash_set took longer than expected, since it's not part of the standard STL (SGI extension apparently), and using it requires one to use the __gnu_cxx namespace. What with Xcode's error messages about this not being very clear, it took a while.

Thinning requires one to worry about edge pixels, and this also gives us an easy way to compute stroke thicknesses (2 * shape area/share perimeter length). This can be used to throw out differences that aren't really strokes (e.g. people), though right now this only works if strokes aren't partially obscured (i.e. not connected). I may have to add color distance to my connectivity criteria (right now it just being "is not a background pixel").

Monkey see, monkey do #

It turns out that GUI Scripting isn't quite the way to go. It relies on the accessibility APIs for its functionality. iTunes doesn't support them, beyond the menus and the scrollbars of the main window. I don't know whether this is intentional, or if this is just a remnant of iTunes' lineage as a Mac OS 9 app (presumably it doesn't use HIViews yet). In any case, GUI Scripting isn't completely useless, I can use the menu-bar to disconnect from shares when I'm done with them, and the scrollbars will allow me to move through the list of shares (though this is hard to test since I'm not on campus at the moment, so I have access to a grand total of two shared libraries). For the actual connection to each library, I am reduced to resizing the iTunes window to a known size and putting in a known location, and then programatically clicking in various places (using XTool for this). Seems to work pretty well so far, though I'm not sure how I'll handle password protected shares yet.

Also wrote a small CLI program to count how many iTunes shares there are out there (the alternative was to a screen capture and analyze it programatically or query the scrollbar (if any), but this seems less brittle). CFNetServices (the non-Cocoa way of getting at Rendezvous functionality) is pretty neat and easy to use.

P.S. The title is in reference to Apple's testing methodology for GUI software.

Good news and bad news #

Good news: I've finally gotten around to using the Jakarta Commons Project's HttpClient user-agent, and it seems to do persistent connections properly (e.g. the succession of /server-info, /login, and /update URL requests are done on the same socket).

Bad news: The thus-modified iLeech still can't connect to an iTunes 4.2 server. There's an HTTP header, Client-DAAP-Validation, followed by 32 hex digits, which is suspiciously MD5 hash like. Unfortunately, I don't know that they're hashing, and no one else on the net seems to have figured it out either.

Good news: Inspired by MyTunes, I've come with a different approach. Script iTunes (using the new GUI scripting add-ons), to sequentially connect to all of the shares. Use tcpflow or its ilk to capture the traffic. Use the existing daap parsing library to extract the music library contents for each client, and then dump all of the results into a database. Since this uses iTunes for the actual crawling, there's no danger of Apple breaking the system by changing the API.

New look #

Convoluted Operations #

- Added i_stroke_set data type in preparation for stroke computation.
- Added convolution of difference images to extract strokes better (kernel has positive values for pixels within the stroke radius, negative values for those between 1x and 2x of the radius away from the center, and 0 elsewhere). Kernel is normalized such that values add up to 1.
- Result is somewhat promising (insides of solid areas (e.g. people) are removed, but borders remain).
- Attempts to use local non-maxima suppression don't behave quite right since we can't just scan a N x N neighborhood to remove non-maximum pixels. Ideally we want to know in which directions to scan (normal to the stroke), but we don't have normals here. Time to convolve with X and Y derivatives?

More WIMPification #

- Decided that backend and UI should be loosely coupled (UI does no processing in and of itself, but it directly invokes (and is aware of) the backend).
- Made UI display images as they are loaded (for originals) or processed (differences)
- Added menu commands and key shortcuts for UI to display different versions of the image and to navigate between images.
- Did crude stroke rendering of strokes (lines and points), but for dummy strokes only (no actual stroke computation done).

Visually yours #

- Added a GLUT-based GUI so that images can be viewed directly in the program. Currently pondering whether to do a callback-style system (more generic/more tedious) or to integrate the GUI with the rest of the code (more direct/kludgy).

How else would I be spending my vacation? #

- Added CapturedImage class, encapsulating it_image, the path and the average luminance (presumably there will be more later)
- Tried to normalize luminance across range of images. Doesn't quite work (precision issues?) but also may not be worthwhile, the reason why I'm seeing fake diffs for the last few images in the "Third Floor" set is because of scale differences. I should fix the focus from now on.

Last minute work #

- Added despeckling filter for deltas (pixel must have at least two neighbors of non-background color).
- Tweaked deltas (must be less than or equal to 3x of range in order to be counted as being the same).
- Added background image creation (average of calibration image).
- Made deltas take into account background (removal of strokes reveals background).
- Gave presentation.

My travails begin... #

- Switched over to ImgStar.
- Added i_op_n_images command to ImgStar lib.
- Added basic range image creation.
- Added offset compensation for calibration images.
- Added blurring for range image creation (currently unused).
- Basic deltas based on range image.

iLeech + Eclipse = almost there #

In my quest to find a working DAAP implementation, I decided to give the Java version of iLeech a try. I knew that it wouldn't work out of the box, but I figured that Java's networking classes may be more useful/robust than Perl's.

To actually build iLeech, I decided to give Eclipse a try (iLeech uses an extensive package hierarchy that I didn't feel like setting up by hand). It's pretty nice, at least on XP, I've yet to try the OS X build.

Once I got iLeech to build, I first tweaked a couple of things (default to "localhost" for host field, hook up the return key to the connect button, make the "Exit" menu item work) to familiarize myself with both the IDE and the code. Then I tried to enable HTTP 1.1 connection reuse, since that's what seems to prevent current DAAP implementations from connecting to iTunes 4.1. There's supposedly a Java environment variable, http.keepalive, which if set to true will take care of things, but it doesn't seem to work. The current plan is to use the Jakarta Commons HttpClient (part of the Apache project), which seems to be more robust.

Oh, and for the longest time I couldn't connect at all with iLeech to beria, but once I did a traceroute I realized I was past the TTL of 2 limit that iTunes imposes.

Efficient Movie Piracy #

Tweaked LRC/DMC movie archive to RSS Perl script to support GUIDs so that NetNewsWire will display deltas when movies are added removed.

dap. daap. daaap. #

Considering ressurecting pTunes as a searching for the campus iTunes Rendezvous sharing community (number of people sharing seems to have doubled since I last checked).

Sounds easy enough, given the existence of OpenDAAP, right? Well, I can't seem to get any of the Perl based tools to work (dapple and a stand-alone script that I found). The Java tools aren't having much luck either.

Hacker interest seems to have dropped since the initial iTunes 4 release in April. I've seen a few references to 4.0.1 requiring a bumped version number, and the necessity of keeping the HTTP/1.1 connection alive (LWP seems to be ignoring my request for this), but then others claim that existing tools should just work as is with 4.1.

Boo.

Mythical Something or Other #

So there's a (presumably) emprically proven rule within the coder community that there's a 10x difference in productivity between a mediocre programmer and a really good one. I wonder how much of this is due to procrastination/inability to focus. Once I get started, I like to think I do pretty well for myself, but it's the 90% of the time that I spend reading news sites, doing random Google searches, etc. that really kills me.

Temporal Discontinuity #

I'm importing all of the entries from all the various programming journals that I've kept, and since they tend to come from raw text files, they're solely lacking in the metadata section. I've started to assign titles to all of them, but of course I can't quite have them reflect the mood/context of the time. This results in things like entries from 98/99 having titles that refer to the Matrix, hax0r speak, etc.

Here's to hoping that I'll come across like a modern-day Nostradamus to any future journal archaeologist :p

Hello World! #

Well, what else would I say? Oh, editing from NetNewsWire is cool.

Progress Report #

  • Can now have mutliple matches in ASIN search for pretty names in recommendations list (see recommends for essential mix, esp. MMII), and in those cases replace artist name with replace with "Various Artists")
  • Added "original soundtrack" to normalization list
  • "Varios" is way of saying "Various Artists" too (see "Woman on Top" soundtrack)
  • Don't normalize capitalization for words under three letters (e.g. ATB/ATC/BT)
  • Normalized special chars better (see the two bjorks)
  • Comma support for normalization (e.g. "Cash, Johnny" vs. "Johnny Cash")
  • Don't specify cover image size anymore, due to variations (see "Politics of Dancing")

Progress Report #

  • Changed Amazon importing code to work with compilations better (don't specify artist in search if album has more than 4 artists) and also do fuzzy string match to make sure that we get the right thing back (no more 'Blank ∓ Jones' matching 'Grosse Point Blanke')

Progress Report #

  • Redirect Netscape 4.x to upgrade page
  • Added stripping of parentheses from titles/names when they enclose the entire string (e.g. "(aerosmith)")

Progress Report #

  • Got Amazon web services kit & token
  • Added selective info bar for testing
  • Wrote XSLT to get only album covers back from Amazon
  • Did initial overnight cover crawling

Progress Report #

  • Switcing genre now clears out album list
  • Randomized ordering of user popup
  • Turned title into download link
  • Removed non-alpha numeric characters from query terms
  • Added links for top 10 songs
  • Returned faster from searches with zero results (don't do LIKE search if terms look reasonable (no special chars, length > 5))
  • Zero results prints message accordingly
  • Imported march FreeDB, evaluate improvements
  • Added selecting all albums for a genre (optimized with STRAIGHT_JOIN)

Progress Report #

  • Fixed searching for stuff like "you said" and "zero 7" and other multi-word queries where MATCH...AGAINST didn't work
  • Made sure the "&x=0&y=0" addition to the search string (done by mozilla) doesn't mess things up
  • Made stats display

Progress Report #

  • Use gray for unfocused frame hilight colors
  • Speedup searches by creating fulltext index
  • Fixed duplicates, see Bachelor Number One
  • Make artist/album name pretty version choosing based on popularity, not just first item returned
  • Fixed Experimental Noise -> Black Rebel Motorcycle Club -> Unknown Album error
  • '<Album name< single' should now strips out 'single' when normalizing

Un-perfect #

Just map image tweaking today. Added a couple of new buildings, and then spent a lot of time cleaning up the text that had been used to label buildings for the past 7+ years. Of course, the irony of all this is that Facilities actually has a very up to date map (i.e. it was last modified on 1/16/2003), in PDF form, all digitized. It's cases like this that make me realize why Arlo is such a perfectionist with his own projects.

Under-promise, Over-deliver #

Looks like Arlo over-hyped K after all, mainly because the main konfabulator.com server seemed to melt under the load til late this afternoon. Considering that ChainShot had around 6,000 downloads, I wonder how much the main app got. There were other launch issues too, some people seemed to have trouble installing, especially if they had moved their Documents directory. I started to compulsively answer questions in the forum (which means I'm in the top ten posters now) til Arlo woke up from his zombified state. Though that was fun and all, I should probably take a break, I've overstaturated my system with K stuff over the past couple of days.

Oh, and I tweaked NetPulse to support preferences for which window layer it should display at and for tab positioning (h/vRegistrationPoint and rotation are my personal enemies).

Genre Work #

Added hiding for unused canonical genres (though it's not perfect yet, e.g. Salsa's parent is hidden but it shows up indented twice) and fixed the JavaScript so that genres with quotes in them like "Drum 'n' Bass" work now.

Should probably group Rock, Modern Rock and Punk Rock under the same category (and other things like that, such as merging the two Ska's) but I'm scared of messing up the genre mappings, and there's no way in hell I'm redoing all 2356 of them.

Spit 'n' Polish #

Final polishing today, so that I can release my widgets alongside K. No fun to make up two .dmg backgrounds, two about boxes, two icons, two readme's, two small previews and two large previews, but now it's all done. Still not sure if I should put stuff up on mscape.com; probably will, just not today.

Ego Boosting++ #

Yet more ego boosting for pTunes. Yesterday for Prohibition Night we sat next to some sophmores, and when we introduced ourselves, one kid was like "Mihai...pTunes?" Made my night, even if it turned out to be the same person who mailed me the other day. Also got a mail today about pTunes, with another kid saying that he liked it and also wanting access to the source code so that he could hack up a movie equivalent.

Finishing Up #

Made up the ChainShot blobs, and a copy of 1.0fc2 that Perry sent me takes care of the lingering bugs that I had. Started to do a .dmg background for NetPulse and an icon too.

Building Things For Myself #

Finished up the map administrator over the past few days, it now handles adding/removing of buildings/departments too. I also made a cool link checking page that verifies all of the department URLs by looking at status codes (not just 404's, but also 301/302 (moved)) and things like META refresh tags (again for sites that have moved) and displays everything in a nice graphical color-coded list. Spent the afternoon fixing 70 or so broken links, and realized that it's sort of fun to use your own tool and have it work exactly as you intended (minus the minor bugs that I fixed as I went along).

Blobby Stuff #

Arlo's too busy to finish up the tiles, so it looks like I'll be doing them myself. Assuming that I can set up some nice actions, 80 images shouldn't be too hard to handle. Also got version 1.0fc1 of K today, and it's still a bit flaky about shadow updates. I wish them luck, since they have to iron everything out by Monday.

Mac Integration #

Got a mail from a Princeton kid (the first!) about pTunes file links not working on Macs, and realized that this is something I'm gonna have to deal with, if only for my sake. For now I just sniff Mac browsers and spit out instructions on how to connect to a SMB share and then navigate to the right directory. Eventually though, I'd like to have a small helper app that registers itself as handling the smb protocol, and then takes care of the mounting and navigation.

IW Options #

Talked with Cook about turning pTunes into an independent work project and using his Phd student's classification code to help with genre determination. He seemed somewhat interested, but in the decided that it wasn't gonna happen because:
1. The classification code is basically done, it's unlikely that I could improve on something George had been working on for 5 years. What remains is more of database-ish and metadata stuff, which isn't really his focus.
2. He's busy anyway with three classes and lots of other kids to advise.
Then I went to see Kernighan, and pitched pTunes from a web service angle (i.e. using other web services like freedb and Amazon to get extra information and in turn exposing my dataset as a web service). He seemed pretty interested, and very willing to serve as my advisor. This is probably the route that I'll choose, because adding an extra project (e.g. if I were to do the projector/whiteboard stuff with Szymon) to my workload would mean that something has to give.

LDAP-ulous #

Bit of work today, added LDAP-based authentication to the admin script, and made it so that a backup file is created every single time a change is made, instead of once per day.

Genre Mappings #

So there are 5097 distinct genre strings in the database. Started by first mapping the more manageable 500 or so that have turned up in ID3 tags. Made up reasonably pretty web interface for this to make my life easier. Seems to work well enough, with reasonable performance. Later on added about half of the freedb genres (so up to 2356 mappings), with the net result being that 38% of artists are still uncategorized. I seem to have hit the point of diminishing returns, i.e. the last 1,000 mappings that I added only resulted in the categorization of 150 (out of 14,000) artists. Will probably finish up mappings anyway, but should look into obtaining even more datasets (Amazon?) and/or cleaning up the artist list (e.g. collapsing "A with B", "A vs. B" and so on). Should also make genre estimation merge more generic estimations with more specific ones, though have to figure out risk of one (or a few) bad (specific) mapping screwing things up.

Kills Bugs Dead #

Finally fixed annoying bug that made palettes show up as hidden at startup, but very sporadically. Turned out that it only happened when quitting Iconographer from the Dock context menu while it was placed in the background, because then the palettes were nominally hidden (but not really).

Too Much Publicity Perhaps... #

Now MacPlus and Insanely Great Mac have little blurbs and are linking to pTunes too, so I've turned off all outside accesses to avoid things getting out of hand. Canonical genre list now displays in newly made column; thinking about ways of doing mappings.

Genre Work Continues #

Extraction worked well enough, modified genreEstimator.pl to use freedb as source too. Still have no data for some artists though, will have to be more ruthless with collapsing of things like "artist A with artist B".

Came up with a canonical genre list, mostly stolen from AudioGalaxy, with some embelishments by me to the Electronic section. Will have to map everything else to one of those. Dreading to count number of distinct genres in the database.

Build Me Up... #

Stats project was thankfully put off by boss. Started work on web interface to campus map administration. Delete buildings file by mistake. Twice. Had to sheepishly ask boss to restore from backups each time. Have viewer and editor of buildings done (but with no add/removing or rebuilding of databases).

'And on the left, we have "Parparita Hall"' #

Map admin project is nastier than I thought. The framework I'm working on is terrible, but I can't change it since it's a stopgap measure (supposedly at some point the facilities people will get off their asses and use the data they already have). Right now it works with three text files which are imported into a MySQL database, which is then used as the backend of the map script. Why not work with MySQL directly, I don't know. And then there's gems like having URLs for departments in a completely separate file, even though they could be just another field in the departments one. Anyway, it's mostly done, all that's left is adding/removing, but given that I have editing working, this shouldn't be that hard.

Edwards was "Parparita Hall" and the stadium was Jiang Stadium for a few minutes today. Tempting to do more since I'm logged into hulk :p

Responsibility Shifting #

Got initial take on tiles from Arlo. Pretty, but still have issues, so more waiting on him. Also got early access to K 1.0b2, NetPulse has issues with updating, and shadow updating is still flaky (neither is my fault).

FreeDB Overnight #

More work on genre indexing. Downloaded and expanded freedb database. Starting to extract genre info from there, thinking of ways of picking genre hierarchy. Left overnight to extract genre info from 850,322 discs and stuff in MySQL database for later processing.

Was inadvertently mentioned on MacSlash by friend of Norair's. Tempting to just block non-Princeton IPs to prevent Apple legal and their ilk from seeing, but also curious what people have to say. Leaving it up for now, with only download links disabled.

Quickies Rock #

Whipped up quickie script to restrict number of analog instances allowed to be running on web server. Started to look into stats project, but specs are so vague I have no idea where to begin.

Chaining Things Up #

More work on ChainShot. Got stats, end of game messages, "connected" neighbors working. Sent off to Arlo to get pretty tiles.

It's really that simple... #

Import/export done and tested on OS X, but crashes in Classic. Must investigate.

Match Me Up #

Match-up dialog work. Was initially too tall to fit even on 1600 x 1200 screen, went with two column layout and small controls to make it work at 800 x 600.

Get Me Out Of Here #

Multi-file (entire icon) exporting works too, with things getting named properly, enclosing folder being made, etc. Had idea for import matchup dialog.

Seinfeld Rocks #

Started to work on import/export (a.k.a. the Art Vandelay release). Got basic (single file) importing/export working.

Faster, Faster #

Added full-text indexing for searches. Get 2x speed boost, but could be a lot more since there's still overhead for database connections and HTML generation.