Too Much About Paul

Various things I'm saying and doing in various places

January 28, 2012

Recent IE View Commits

maxVersion upped

m src/install.rdf.in
maxVersion upped

by Paul Roub at January 28, 2012 03:52 AM

January 22, 2012

My Flickr photos

So... very... good

Paul Roub posted a photo:

So... very... good

A little butter, a little smoked sea salt... and fresh whole wheat bread from my dutch oven, per Michael Ruhlman's "Bread Baking Basics" iPad app.

And good lord, that was easy.

by Paul Roub (nobody@flickr.com) at January 22, 2012 10:06 PM

January 21, 2012

Personal Blog

Straps and Buttons

I recently lucked into a Takamine G-335 12-string in a well-timed eBay bid.  I'm very happy with it, but sitting down? On stage? This will not do. But there's just the one strap button at the butt end, and I'm not tying a strap to the headstock; that maybe looked cool on Elvis. Maybe.

I'd been meaning to put strap locks on my Strat, which would leave me with a spare strap button or two.

So:

And then...

Safety first...

Et voilà.

It is at this point that I realize I don't yet have a strap for this guitar.

So close...

by Paul Roub at January 21, 2012 11:00 PM

My Flickr photos

January 19, 2012

openmikes.org blog

Where did openmikes.org go yesterday?

If you visited openmikes.org on March 18, 2012 (just barely yesterday in my time zone, as I write this), you noticed that the site was missing. Unless openmikes.org is the only site you visited that day, you are probably aware that this was not an isolated incident. Wikipedia, Boing Boing and numerous others went “dark” to protest the SOPA and PIPA bills being considered by the US Congress.

Sorry for the inconvenience, but this site reaches more people in a day than my personal blog does in a month. Far more. If I was going to make a point, this was the place.

As a musician, a songwriter, a creator of works I do want protected… SOPA isn’t the way to do it.

I heartily recommend reading this interview with publisher Tim O’Reilly for an excellent explanation of what SOPA is, and why it’s more dangerous than any problem it would allegedly solve.

by Paul Roub at January 19, 2012 05:44 AM

January 16, 2012

My Flickr photos

January 07, 2012

Recent IE View Commits

migrated preferences from ieview.* to extensions.ieview.* per #26

m src/.gitignore
m src/chrome/content/ieviewOverlay.js
m src/chrome/content/ieviewsettings.xul
m src/chrome/content/reloaded.html
migrated preferences from ieview.* to extensions.ieview.* per #26

by Paul Roub at January 07, 2012 07:13 PM

January 06, 2012

My Flickr photos

Serial 84770

Paul Roub posted a photo:

Serial 84770

Serial numbers were running 3 or 4 years ahead at this point. It's most likely an '81, but might be an '80.

by Paul Roub (nobody@flickr.com) at January 06, 2012 05:48 PM

All original but the strap locks

Paul Roub posted a photo:

All original but the strap locks

OK, the pickup switch knob was swapped out the day I bought it, from the Eagle hanging next to it. The original was cream, I thought black looked better. :-)

by Paul Roub (nobody@flickr.com) at January 06, 2012 05:48 PM

Love the burst on the back

Paul Roub posted a photo:

Love the burst on the back

There's a bit more buckle rash than is shown, almost all of it from the month between the guitar's theft and recovery in '84.

by Paul Roub (nobody@flickr.com) at January 06, 2012 05:47 PM

January 03, 2012

My Upcoming Gigs

December 20, 2011

Paul's Work Blog

Veracity 1.5 Released

Just a quick post to note that we’ve released Veracity 1.5.

The most-visible new features:

  • A Tortoise-style extension for Windows users. Jeremy gives you an illustrated once over on the Veracity Q and A site.

Alt text

  • The afore-blogged wiki module is now installed by default, and brings a variety of bug fixes and improvements.

More details to come soon, but I have a race condition to bang my head against.

Meantime, checkout the release notes and downloads.

December 20, 2011 09:27 PM

December 15, 2011

That Thing I Was Telling You About

Mechanically Obfuscated Ad Spam Copy of Link bait-Hacker News Slash Dot cancer Considered Request To call to action


Considered harmful

Declarative statement opening statement blog. Stand back a little declarative statement, then double-pivot down with even more controversial declarative statement. Insult programming language beloved aesthetic idioms and assert more recent versions as superior. Including the statistics support that lack the Y-axis labels to shore up weak link bait, including declarative statement. Linus reference, invoke Dijkstra. Oh, everything looks bad if you remember it.

Benchmarks biased

While supporting misguided statement. Weak marginally misleading statement because I want to be on TechCrunch. Farmville.

If 1, then A
  
else if 2 then B
  
else if 3 then C
  
else / D otherwise
K & RC Support cite page references induction with reference to non sequitur Mythical Man Month.

Use the right tool for the right job. Grep more difficult. Appeal to authority. Fowler invocation stating Turing completeness. This is not NP complete. Try harder to grok.

UR doing it wrong

I suggest you try again. This time, let go your conscious self and act on instinct. Finding a needle in a haystack is not difficult when each straw is computerized. Spare me your space age technobabble, Attila the Hun! Soothe us with sweet lies.

There is one cat on the computer. He is running a custom Mint Distro. This is a meme!

 

Use the right tool for the right job. Srsly. Down-voted into oblivion. Spolsky obscure link justifying the opposite position .. Atwoodian is a tautology.

Accusations of intellectual dishonesty



Off-handed reference to FizzBuzz reminiscent of the dream of pearls programming reference for my first Altair and frustration with the status quo.

CmdrTaco name down, dig in Digg, Y-Combinator sour grapes. I do not think it was physically possible but this both sucks and blows * *. Yes, if you make it look like an electrical fire. It is a kart, powered by my own sense of self-satisfaction.

Reference to the diagram of useless and misplaced frustration at Large Companies.Comments directed to patent trolls combined with witty acerbic statement concerning the uselessness Lessig and software patents.

Random bold concluding sentence.

Follow me. Read my blog. I have opinions.

December 15, 2011 10:03 PM

December 14, 2011

Recent IE View Commits

rebuild ieview.xpi per modern extension standards

+ old-src/Makefile
+ old-src/adjustbuild.pl
+ old-src/bt
+ old-src/bumpbuild
+ old-src/checklocale.pl
+ old-src/checkversion.pl
+ old-src/creditgen
+ old-src/creditgen.pl
+ old-src/newver
+ old-src/skin/contents.rdf
+ old-src/testlocale
+ old-src/xmlcheck.pl
+ src/Makefile
+ src/chrome.manifest.in
m src/chrome/content/ieviewOverlay.js
m src/chrome/content/ieviewOverlay.xul
+ src/chrome/content/ieviewsettings.xul
+ src/chrome/content/reloaded.html
+ src/chrome/locale/bg-BG/ieview.dtd
+ src/chrome/locale/bg-BG/ieview.properties
+ src/chrome/locale/ca-AD/ieview.dtd
+ src/chrome/locale/ca-AD/ieview.properties
+ src/chrome/locale/cs-CZ/ieview.dtd
+ src/chrome/locale/cs-CZ/ieview.properties
+ src/chrome/locale/da-DK/ieview.dtd
+ src/chrome/locale/da-DK/ieview.properties
+ src/chrome/locale/de-DE/ieview.dtd
+ src/chrome/locale/de-DE/ieview.properties
+ src/chrome/locale/el-GR/ieview.dtd
+ src/chrome/locale/el-GR/ieview.properties
+ src/chrome/locale/en-US/ieview.dtd
+ src/chrome/locale/en-US/ieview.properties
+ src/chrome/locale/es-AR/ieview.dtd
+ src/chrome/locale/es-AR/ieview.properties
+ src/chrome/locale/es-ES/ieview.dtd
+ src/chrome/locale/es-ES/ieview.properties
+ src/chrome/locale/eu-ES/ieview.dtd
+ src/chrome/locale/eu-ES/ieview.properties
+ src/chrome/locale/eu/ieview.dtd
+ src/chrome/locale/eu/ieview.properties
+ src/chrome/locale/fi-FI/ieview.dtd
+ src/chrome/locale/fi-FI/ieview.properties
+ src/chrome/locale/fr-FR/ieview.dtd
+ src/chrome/locale/fr-FR/ieview.properties
+ src/chrome/locale/fy-NL/ieview.dtd
+ src/chrome/locale/fy-NL/ieview.properties
+ src/chrome/locale/he-IL/ieview.dtd
+ src/chrome/locale/he-IL/ieview.properties
+ src/chrome/locale/hr-HR/ieview.dtd
+ src/chrome/locale/hr-HR/ieview.properties
+ src/chrome/locale/hu-HU/ieview.dtd
+ src/chrome/locale/hu-HU/ieview.properties
+ src/chrome/locale/it-IT/ieview.dtd
+ src/chrome/locale/it-IT/ieview.properties
+ src/chrome/locale/ja-JP/ieview.dtd
+ src/chrome/locale/ja-JP/ieview.properties
+ src/chrome/locale/km-KH/ieview.dtd
+ src/chrome/locale/km-KH/ieview.properties
+ src/chrome/locale/ko-KR/ieview.dtd
+ src/chrome/locale/ko-KR/ieview.properties
+ src/chrome/locale/lt-LT/ieview.dtd
+ src/chrome/locale/lt-LT/ieview.properties
+ src/chrome/locale/nb-NO/ieview.dtd
+ src/chrome/locale/nb-NO/ieview.properties
+ src/chrome/locale/nl-NL/ieview.dtd
+ src/chrome/locale/nl-NL/ieview.properties
+ src/chrome/locale/pl-PL/ieview.dtd
+ src/chrome/locale/pl-PL/ieview.properties
+ src/chrome/locale/pt-BR/ieview.dtd
+ src/chrome/locale/pt-BR/ieview.properties
+ src/chrome/locale/pt-PT/ieview.dtd
+ src/chrome/locale/pt-PT/ieview.properties
+ src/chrome/locale/ru-RU/ieview.dtd
+ src/chrome/locale/ru-RU/ieview.properties
+ src/chrome/locale/sk-SK/ieview.dtd
+ src/chrome/locale/sk-SK/ieview.properties
+ src/chrome/locale/sl-SI/ieview.dtd
+ src/chrome/locale/sl-SI/ieview.properties
+ src/chrome/locale/sr-RS/ieview.dtd
+ src/chrome/locale/sr-RS/ieview.properties
+ src/chrome/locale/sr-YU/ieview.dtd
+ src/chrome/locale/sr-YU/ieview.properties
+ src/chrome/locale/sv-SE/ieview.dtd
+ src/chrome/locale/sv-SE/ieview.properties
+ src/chrome/locale/th-TH/ieview.dtd
+ src/chrome/locale/th-TH/ieview.properties
+ src/chrome/locale/tr-TR/ieview.dtd
+ src/chrome/locale/tr-TR/ieview.properties
+ src/chrome/locale/uk-UA/ieview.dtd
+ src/chrome/locale/uk-UA/ieview.properties
+ src/chrome/locale/vi-VN/ieview.dtd
+ src/chrome/locale/vi-VN/ieview.properties
+ src/chrome/locale/zh-CN/ieview.dtd
+ src/chrome/locale/zh-CN/ieview.properties
+ src/chrome/locale/zh-TW/ieview.dtd
+ src/chrome/locale/zh-TW/ieview.properties
+ src/chrome/skin/ieview-button-16px-disabled.png
+ src/chrome/skin/ieview-button-16px.png
+ src/chrome/skin/ieview-button-24px-disabled.png
+ src/chrome/skin/ieview-button-24px.png
+ src/chrome/skin/ieview-icon.png
+ src/chrome/skin/ieview-toolbar-button.css
+ src/defaults/preferences/ieview.js
+ src/inslocales.pl
+ src/install.rdf.in
+ src/makemanifest.pl
rebuild ieview.xpi per modern extension standards

by Paul Roub at December 14, 2011 08:46 PM

find tabContextMenu in recent FF versions

m src/rebuild/Makefile
m src/rebuild/chrome/content/ieviewOverlay.js
m src/rebuild/chrome/skin/ieview-button-16px-disabled.png
m src/rebuild/chrome/skin/ieview-button-16px.png
m src/rebuild/chrome/skin/ieview-button-24px-disabled.png
m src/rebuild/chrome/skin/ieview-button-24px.png
m src/rebuild/chrome/skin/ieview-icon.png
m src/rebuild/inslocales.pl
m src/rebuild/install.rdf.in
m src/rebuild/makemanifest.pl
find tabContextMenu in recent FF versions

by Paul Roub at December 14, 2011 08:46 PM

checkpoint on the way to a modernized extension layout

m src/.gitignore
- src/chrome.manifest.firefox-autogen.txt
- src/chrome/.cvsignore
- src/content/contents.rdf
- src/cvs2cl.pl
- src/install.js.in
- src/locale/.cvsignore
- src/locale/bg-BG/ieview/contents.rdf
- src/locale/ca-AD/ieview/contents.rdf
- src/locale/cs-CZ/ieview/contents.rdf
- src/locale/da-DK/ieview/contents.rdf
- src/locale/de-DE/ieview/contents.rdf
- src/locale/el-GR/ieview/contents.rdf
- src/locale/en-US/ieview/contents.rdf
- src/locale/es-AR/ieview/contents.rdf
- src/locale/es-ES/ieview/contents.rdf
- src/locale/eu-ES/ieview/contents.rdf
- src/locale/eu/ieview/contents.rdf
- src/locale/fi-FI/ieview/contents.rdf
- src/locale/fr-FR/ieview/contents.rdf
- src/locale/fy-NL/ieview/contents.rdf
- src/locale/he-IL/ieview/contents.rdf
- src/locale/hr-HR/ieview/contents.rdf
- src/locale/hu-HU/ieview/contents.rdf
- src/locale/it-IT/ieview/contents.rdf
- src/locale/ja-JP/ieview/contents.rdf
- src/locale/km-KH/ieview/contents.rdf
- src/locale/ko-KR/ieview/contents.rdf
- src/locale/lt-LT/ieview/contents.rdf
- src/locale/nb-NO/ieview/contents.rdf
- src/locale/nl-NL/ieview/contents.rdf
- src/locale/pl-PL/ieview/contents.rdf
- src/locale/pt-BR/ieview/contents.rdf
- src/locale/pt-PT/ieview/contents.rdf
- src/locale/ru-RU/ieview/contents.rdf
- src/locale/sk-SK/ieview/contents.rdf
- src/locale/sl-SI/ieview/contents.rdf
- src/locale/sr-RS/ieview/contents.rdf
- src/locale/sr-YU/ieview/contents.rdf
- src/locale/sv-SE/ieview/contents.rdf
- src/locale/th-TH/ieview/contents.rdf
- src/locale/tr-TR/ieview/contents.rdf
- src/locale/uk-UA/ieview/contents.rdf
- src/locale/vi-VN/ieview/contents.rdf
- src/locale/zh-CN/ieview/contents.rdf
- src/locale/zh-TW/ieview/contents.rdf
+ src/old/Makefile
+ src/rebuild/Makefile
m src/rebuild/chrome.manifest.in
+ src/rebuild/chrome/content/ieviewOverlay.js
+ src/rebuild/chrome/content/ieviewOverlay.xul
+ src/rebuild/chrome/content/ieviewsettings.xul
m src/rebuild/chrome/content/reloaded.html
+ src/rebuild/chrome/locale/bg-BG/ieview.dtd
+ src/rebuild/chrome/locale/bg-BG/ieview.properties
+ src/rebuild/chrome/locale/ca-AD/ieview.dtd
+ src/rebuild/chrome/locale/ca-AD/ieview.properties
+ src/rebuild/chrome/locale/cs-CZ/ieview.dtd
+ src/rebuild/chrome/locale/cs-CZ/ieview.properties
+ src/rebuild/chrome/locale/da-DK/ieview.dtd
+ src/rebuild/chrome/locale/da-DK/ieview.properties
+ src/rebuild/chrome/locale/de-DE/ieview.dtd
+ src/rebuild/chrome/locale/de-DE/ieview.properties
+ src/rebuild/chrome/locale/el-GR/ieview.dtd
+ src/rebuild/chrome/locale/el-GR/ieview.properties
+ src/rebuild/chrome/locale/en-US/ieview.dtd
+ src/rebuild/chrome/locale/en-US/ieview.properties
+ src/rebuild/chrome/locale/es-AR/ieview.dtd
+ src/rebuild/chrome/locale/es-AR/ieview.properties
+ src/rebuild/chrome/locale/es-ES/ieview.dtd
+ src/rebuild/chrome/locale/es-ES/ieview.properties
+ src/rebuild/chrome/locale/eu-ES/ieview.dtd
+ src/rebuild/chrome/locale/eu-ES/ieview.properties
+ src/rebuild/chrome/locale/eu/ieview.dtd
m src/rebuild/chrome/locale/eu/ieview.properties
+ src/rebuild/chrome/locale/fi-FI/ieview.dtd
+ src/rebuild/chrome/locale/fi-FI/ieview.properties
+ src/rebuild/chrome/locale/fr-FR/ieview.dtd
+ src/rebuild/chrome/locale/fr-FR/ieview.properties
+ src/rebuild/chrome/locale/fy-NL/ieview.dtd
+ src/rebuild/chrome/locale/fy-NL/ieview.properties
+ src/rebuild/chrome/locale/he-IL/ieview.dtd
+ src/rebuild/chrome/locale/he-IL/ieview.properties
+ src/rebuild/chrome/locale/hr-HR/ieview.dtd
+ src/rebuild/chrome/locale/hr-HR/ieview.properties
+ src/rebuild/chrome/locale/hu-HU/ieview.dtd
+ src/rebuild/chrome/locale/hu-HU/ieview.properties
+ src/rebuild/chrome/locale/it-IT/ieview.dtd
+ src/rebuild/chrome/locale/it-IT/ieview.properties
+ src/rebuild/chrome/locale/ja-JP/ieview.dtd
+ src/rebuild/chrome/locale/ja-JP/ieview.properties
+ src/rebuild/chrome/locale/km-KH/ieview.dtd
+ src/rebuild/chrome/locale/km-KH/ieview.properties
+ src/rebuild/chrome/locale/ko-KR/ieview.dtd
+ src/rebuild/chrome/locale/ko-KR/ieview.properties
+ src/rebuild/chrome/locale/lt-LT/ieview.dtd
+ src/rebuild/chrome/locale/lt-LT/ieview.properties
+ src/rebuild/chrome/locale/nb-NO/ieview.dtd
+ src/rebuild/chrome/locale/nb-NO/ieview.properties
+ src/rebuild/chrome/locale/nl-NL/ieview.dtd
+ src/rebuild/chrome/locale/nl-NL/ieview.properties
+ src/rebuild/chrome/locale/pl-PL/ieview.dtd
+ src/rebuild/chrome/locale/pl-PL/ieview.properties
+ src/rebuild/chrome/locale/pt-BR/ieview.dtd
+ src/rebuild/chrome/locale/pt-BR/ieview.properties
+ src/rebuild/chrome/locale/pt-PT/ieview.dtd
+ src/rebuild/chrome/locale/pt-PT/ieview.properties
+ src/rebuild/chrome/locale/ru-RU/ieview.dtd
+ src/rebuild/chrome/locale/ru-RU/ieview.properties
+ src/rebuild/chrome/locale/sk-SK/ieview.dtd
+ src/rebuild/chrome/locale/sk-SK/ieview.properties
+ src/rebuild/chrome/locale/sl-SI/ieview.dtd
+ src/rebuild/chrome/locale/sl-SI/ieview.properties
+ src/rebuild/chrome/locale/sr-RS/ieview.dtd
+ src/rebuild/chrome/locale/sr-RS/ieview.properties
+ src/rebuild/chrome/locale/sr-YU/ieview.dtd
+ src/rebuild/chrome/locale/sr-YU/ieview.properties
+ src/rebuild/chrome/locale/sv-SE/ieview.dtd
+ src/rebuild/chrome/locale/sv-SE/ieview.properties
+ src/rebuild/chrome/locale/th-TH/ieview.dtd
+ src/rebuild/chrome/locale/th-TH/ieview.properties
+ src/rebuild/chrome/locale/tr-TR/ieview.dtd
+ src/rebuild/chrome/locale/tr-TR/ieview.properties
+ src/rebuild/chrome/locale/uk-UA/ieview.dtd
+ src/rebuild/chrome/locale/uk-UA/ieview.properties
+ src/rebuild/chrome/locale/vi-VN/ieview.dtd
+ src/rebuild/chrome/locale/vi-VN/ieview.properties
+ src/rebuild/chrome/locale/zh-CN/ieview.dtd
+ src/rebuild/chrome/locale/zh-CN/ieview.properties
+ src/rebuild/chrome/locale/zh-TW/ieview.dtd
+ src/rebuild/chrome/locale/zh-TW/ieview.properties
+ src/rebuild/chrome/skin/ieview-button-16px-disabled.png
+ src/rebuild/chrome/skin/ieview-button-16px.png
+ src/rebuild/chrome/skin/ieview-button-24px-disabled.png
+ src/rebuild/chrome/skin/ieview-button-24px.png
+ src/rebuild/chrome/skin/ieview-icon.png
+ src/rebuild/chrome/skin/ieview-toolbar-button.css
+ src/rebuild/defaults/preferences/ieview.js
m src/rebuild/inslocales.pl
m src/rebuild/install.rdf.in
m src/rebuild/makemanifest.pl
checkpoint on the way to a modernized extension layout

by Paul Roub at December 14, 2011 08:46 PM

December 10, 2011

Recent IE View Commits

pass function object to setTimeout, re: #22

m src/content/reloaded.html
pass function object to setTimeout, re: #22

by Paul Roub at December 10, 2011 04:32 PM

December 03, 2011

Recent IE View Commits

marked Firefox 10.* compatible, minor^3 version bump

m src/Makefile
m src/content/contents.rdf
m src/install.rdf.in
marked Firefox 10.* compatible, minor^3 version bump

by Paul Roub at December 03, 2011 01:09 AM

November 09, 2011

Recent IE View Commits

upped seamonkey maxVersion, added em:type

m src/install.rdf.in
upped seamonkey maxVersion, added em:type

by Paul Roub at November 09, 2011 05:02 PM

updated compatibility list, ie view home page

m src/Makefile
m src/content/contents.rdf
m src/content/reloaded.html
m src/inslocales.pl
m src/install.js.in
m src/install.rdf.in
updated compatibility list, ie view home page

by Paul Roub at November 09, 2011 04:49 PM

October 31, 2011

My Flickr photos

October 07, 2011

My Flickr photos

October 02, 2011

Personal Blog

Tools of the Trade, iPad Edition

If more than two people ask me about something I'm using, especially if it's more than two people at one show, it seems worth the time to write it down.

Paul and Brian

It may look like my friend Brian is paying close attention, awaiting the moment when he'll add some more harmonies. Actually, he's looking past me, at my iPad, attached to a nearby stand.

Paul, Brian, iPad

It's held there by an IK Multimedia iKlip mic stand mount. There are a number of products that do this job; this is the one I happen to own, and it does its one job very well.

So why is it there? I know folks who run GarageBand onstage this way, but in my case, it's just lyric sheets and/or setlists. So when I need a memory jog on a new song, the occasional cover or (as sadly happened last night) when I blank on an older song of mine, it's right there.

There's any number of ways to get those lyrics on there, but like any good nerd, I lean toward plain text files. Something I can edit on any machine I own, view on my phone if need be, etc.

The app used for viewing the songs is GoodReader. I like that it will read almost anything I throw at it, but especially like the way it syncs with Dropbox. I have a "Lyrics" folder on my laptop:

lyricsfolder.png

and I've told GoodReader to sync that folder and its contents. If I add a new song to that folder, it will automatically be mirrored to GoodReader. Tap a song, and off I go:

Lyrics, "Disappear" by Paul Roub

If I'm feeling particularly grown-up and professional, I'll "star" some of the songs ahead of time, and let GoodReader show me just those songs as something approaching a setlist:

set list in GoodReader

That's it. No more binder of lyrics for me, and I'm pretty happy about it. I do recommend putting the iPad in airplane mode before your set, to avoid the temptation to tweet mid-song.

by Paul Roub at October 02, 2011 07:40 PM

September 26, 2011

That Thing I Was Telling You About

September 12, 2011

My Flickr photos

New Music Downloads

demos: 2. What I Just Said (demo)

Don't worry, a version with real drums is coming.

September 12, 2011 12:00 PM

September 10, 2011

My Flickr photos

That Thing I Was Telling You About

merlin: I find this photo…just…dazzlingly disturbing. Couldn’t...



merlin:

I find this photo…just…dazzlingly disturbing.

Couldn’t even say why, but this feels like the visual equivalent of being told you’re eating human flesh.

It looks like a still frame from an old Python animation; I imagine Cryer continues to rise up, knocking Ashton’s head off, which then lands on what I choose to believe is the word “FAIL”.

September 10, 2011 02:02 AM

September 09, 2011

My Flickr photos

September 08, 2011

My Flickr photos

Let... Me... Go!

Paul Roub posted a photo:

Let... Me... Go!

Really, the cat would have kicked her ass.

by Paul Roub (nobody@flickr.com) at September 08, 2011 11:08 PM

September 03, 2011

My Flickr photos

That Thing I Was Telling You About

merlin: Jerry Lewis - “Alaskan Polar Bear Heater” (The Nutty...



merlin:

Jerry Lewis - “Alaskan Polar Bear Heater” (The Nutty Professor, 1963)

“Some more scotch”

September 03, 2011 07:30 PM

New Music Downloads

demos: 1. Full of Holes (demo)

Brand new, maybe not 100% done yet, but I'm liking it.

September 03, 2011 12:00 PM

August 30, 2011

My Flickr photos

August 28, 2011

My Flickr photos

August 19, 2011

Paul's Work Blog

Building a Veracity Module - Part 4

Finishing up our Veracity module overview, let’s look at a few “fitting in” considerations.

How’d We End Up in the Menu?

If your server_files/ui/modules/yourmodule folder contains a menu.js file, that file will be loaded via a <script> tag in the footer of every Veracity web page.

Whatever you want to add/change in the Veracity menu, do it here. In our case (and most cases), we just append an item to the <ul> named topmenu, which is (surprise!) Veracity’s top-level menu:

var tm = $('#topmenu');

var mi = $("<li id='topmenuwiki'></li>");

var ln = $("<a class='menulink'>wiki</a>").
    attr('href', sgCurrentRepoUrl + "/wiki.html").
    appendTo(mi);

tm.append(mi);

Notice that you can count on jQuery being available to your code.

What About the Activity Stream?

Wiki page changes show up in Veracity’s activity stream, alongside commits, bug updates, etc. The activity stream interface is a simple one: you need to create an object supporting three methods:

  • name(): returns a string describing this particular activity component, for debug logging. Totally up to you.
  • dagsUsed(): returns an array of database DAG IDs, for caching. Include any DAGs your activity stream might query. In our case, it’s [sg.dagnum.WIKI, sg.dagnum.USERS]
  • getActivity(): where all of the work happens

getActivity() returns an array of objects, with (at least) the following members:

  • what: A short description of the object that changed, updated, etc.
  • title: Usually redundant to “what”. Used for Atom entry titles.
  • action: What happened to that thing (created, updated, deleted, fixed…)
  • who: The Veracity user ID to whom this activity should be attributed (a committer, the editor of this particular Wiki change, etc.)
  • when: The (Unix timestamp) time when this activity occurred.
  • link: Optional, a link to the object, its history, etc.

Bug updates, for example, contain (among other things):

{
    "what": "Work items that reference missing changesets can not be viewed",
    "title: "Work items that reference missing changesets can not be viewed",
"action": "Fixed X1384",
    "who":"g02d63075631e47bc8a29dad7027f59d382cff0ac413311e0838c60fb42f09aca",
    "when":1313620280696.000000,
    "link":"/workitem.html?recid=gdbb98600a5114533a0a936226f4b2efb8e381b80c91811e0b40f1c6f65d71da9"
}

You should return the most recent N items. The activity stream wrappers will sort them in with other activity sources before returning the JSON or Atom stream.

In the wiki’s case, we build records like so:

var record = {
    what: thispage.title,
    title: thispage.title,
    who: thispage.userid,
    when: thispage.timestamp
};

if (first)
    record.action = "Created Wiki page";
else
    record.action = "Edited Wiki page";

if (lastpage)
{
    if (lastpage.title != thispage.title)
    {
        record.action = "Renamed Wiki page";
        record.what += " (was " + lastpage.title + ")";
    }
}

record.link = '/wiki.html?page=' + encodeURIComponent(title);

The first time a page is seen, we report it as “created”; thereafter, as “edited”. If the title changes along the way, we note that instead.

Activity stream including wiki and bug updates

That’s about it, as module high points go. Further questions are very much welcome at the Veracity Q/A site.

August 19, 2011 07:16 PM

August 18, 2011

Paul's Work Blog

Building a Veracity Module - Part 3

So how does the Wiki module work, anyway? Pretty much the way you’d expect a web app to work.

  1. The Wiki form is displayed (and maybe pre-populated with the page’s title and text)
  2. You edit the title and text, and submit
  3. We bundle those fields up into a JSON package
  4. And send that along to the server-side Wiki code
  5. That code either
    1. Updates the page if it already existed, or
    2. Creates a new page
  6. On success, we reload the wiki page

All of the Veracity-specific stuff happens on the server side.

Retrieving a Page

We retrieve the existing page in the GET /wiki/pages/<pagename>.json route (mentioned in Part 2 the other day). Normally (q.v.), that’s as simple as:

var db = new zingdb(request.repo, sg.dagnum.WIKI);

var w = vv.where( { "title": request.pagename } );

var recs = db.query('page', ['text','title','recid'], w);

return( recs[0] );

Which translates to “Open the wiki database, find any records matching our pagename, grab their text, title and recid fields, and return the first one.” We can get away with this since our database template requires the pagename to be unique.

A JSON representation of that object is returned (you’ll also see some caching logic in there, but that’s strictly a performance measure, ignorant of the Wiki data).

Creating and Updating

Updates work like so:

var csid = newrec._csid || null;
delete newrec._csid;

ztx = db.begin_tx(csid, request.headers.From);
if (newrec.recid)
    rec = ztx.open_record('page', newrec.recid);
else
{
    rec = ztx.new_record('page');
    newrec.recid = rec.recid;
}

rec.title = newrec.title;
rec.text = newrec.text;

vv.txcommit(ztx);
  1. Get the changeset ID (if any) that this update is based on (more on this in a moment)
  2. Start a new transaction
  3. Do we already have a record ID? If so, this is an update. Open that record.
  4. If not, this is a new page. Create a record.
  5. Set the record’s title and text to those passed in from the form.
  6. Commit.

We then return OK to our caller, the page is reloaded, the circle of life continues.

Merges

So what’s up with the changeset ID, and why did we have to say “normally” before?

It’s possible that, by the time you’re saving your changes, someone else has updated the same page. Or maybe your changes are in a nice straight line locally, but a push or pull brings in someone else’s previously-unknown edits. Veracity doesn’t get to throw up its hands and fail. It needs to merge.

And to merge your changes and mine, it needs to know where we each started from. That’s why we pass the changeset IDs around; it tells Veracity “here’s my latest changes, and the last version I knew of was rev 1234”. Later, when Veracity merges that with someone else’s updates, it knows those were based on rev 1235; it finds a common ancestor, does a smart 3-way merge, and all’s well. Almost always.

“Almost always” is not “absolutely always”, though.

What if we both started with:

line 1
line 2

as our text. Then I edited it to read:

line 1
line one and a half
line 2

while off on your machine, you edited it to:

line 1
line 1.5
line 2

Then you pull my changes. Now what? Should your changes be thrown away? Should mine? Should both lines be included? Any of these are possible, but in the template we have to pick one.

The “merge strategy” the Wiki template uses is to concatenate our two texts, and let a human being sort things out. Elsewhere (e.g. in the scrum module) we use all sorts of other strategies, including automatically changing the ID of a work item when it conflicts with one created elsewhere). Since Wiki text is intended for human usage only, and is completely arbitrary, there’s no sense trying to guess the “appropriate” conflict resolution between two edits.

So in this situation, anyone opening the merged page will see:

Wiki page needing manual merge

Edit that as needed, and all’s well with the world again.

Next (and hopefully final) time: plugging into Veracity’s activity stream and cache.

August 18, 2011 03:13 PM

August 15, 2011

Paul's Work Blog

Building a Veracity Module - Part 2

Last time, we installed a Wiki module for Veracity. This time, we’ll look at the pieces that make a module work.

Veracity modules can add to several different parts of the Veracity infrastructure; not every module will touch all of these. They are:

  1. New templated data types (in our case, Wiki pages), and the database DAGs to hold them.
  2. Server-side Javascript code, run in response to either:
    1. Web server requests (creating, updating, viewing Wiki pages), or
    2. Version control hooks (not used in this example)
  3. New Veracity web pages.
  4. Client-side Javascript, run as part of Veracity’s Web UI.

The client-side Javascript is found under server_files/ui/modules/wiki; the rest lives under server_files/modules/wiki. A portion of init.js in that folder bears closer inspection:

area: "wiki",
vendor: sg.vendor.SOURCEGEAR,
grouping: 5,
dagnums: {
    "WIKI": {
        dagid: 1,
        template: 'sg_ztemplate__wiki.json'
    }
},

We’re creating a new database “area” - a group of DAGs that are related to one another. Veracity ships with areas like version_control, and the scrum module defines (not surprisingly) scrum. For modules, the area name should match the containing folder name.

Each module definition needs a vendor ID. Right now, that’s just us. sg.vendor.SOURCEGEAR == 1. If you’re adding your own areas, get in touch, and I’ll make sure you have a vendor ID that doesn’t conflict with anyone else’s.

The grouping property is the number of this area within the vendor’s space. 1-4 were already used (including Scrum), so I added 1. Clever me.

Similarly, dagid is the number of each DAG within this area. If you looked at the scrum module, you’d see the WORK_ITEMS dag has dagid == 1, and the BUILDS dag has dagid == 2.

Every DAG in Veracity needs a template - a description of its record types, their fields, and the merging rules involved for each. All rectypes must be fully, automatically mergeable - failure is, literally, not an option. This allows distributed databases and their owners to remain sane. Merge strategies include “last first”, “greatest”, “uniqify”, etc. We’ll look at the Wiki’s choice next time.

In our init file, we specify the JSON file describing each database template. The templates for core Veracity DAGs can be found in @/src/libraries/templates.

At some magical hand-wavy time that you needn’t worry about, Veracity will look at this init file and:

  1. Make sure the repo we’re playing with has this area installed
  2. Make sure that area has the DAGs we need
  3. Make sure that the DAGs have the right templates set

Once this has happened, the DAGs are available for Javascript use just like the built-in types. If you run the vscript interpreter on a wiki-enabled repo, you can see this:

vscript> sg.to_json__pretty_print( repo.list_areas() )
{
    "core" : 257,
    "version_control" : 258,
    "scrum" : 259,
    "wiki" : 261
}

vscript> sg.to_json__pretty_print(sg.dagnum)
{
    "VERSION_CONTROL" : "0000000010201001",
    "USERS" : "0000000010102062",
    "AREAS" : "0000000010101042",
    "VC_COMMENTS" : "00000000102021c2",
    "VC_TAGS" : "00000000102040c2",
    "VC_BRANCHES" : "0000000010205142",
    "VC_STAMPS" : "00000000102031c2",
    "VC_HOOKS" : "00000000102071c2",
    "TESTING_DB" : "0000000010401002",
    "TESTING2_DB" : "0000000010402002",
    "WORK_ITEMS" : "0000000010301002",
    "BUILDS" : "0000000010302002",
    "WIKI" : "0000000010501002"
}

vscript> db = new zingdb(repo, sg.dagnum.WIKI)
[object zingdb]
vscript> sg.to_json__pretty_print( db.get_template() )
{
    "version" : 1,
    "rectypes" : 
    {
        "page" : 
        {
            "merge" : 
            {
                "merge_type" : "field",
            // ...
            }
        // ...
        }
    }
    // ...
}

And after creating a page or two:

vscript> db = new zingdb(repo, sg.dagnum.WIKI)
vscript> records = db.query('page', ['*'])
[object Object],[object Object]
vscript> sg.to_json__pretty_print(records[1])
{
    "recid" : "ge9dbadde62004708abd960d58a99753f191e0f24c42b11e0a1a0c8bcc8e13b9a",
    "text" : "This is, in fact, another page entirely.  \n\n[[Yet Another Page]]",
    "title" : "Another Page"
}

Veracity will also install any URIs added by the module’s server-side Javascript. Look at server_files/modules/wiki/wiki.js to see how those are specified:

"/repos/<repoName>/wiki/page/<pagename>.json": {
    "GET": {
        onDispatch: function (request) {
           // this handles the request for a Wiki page's current contents
           // ...
       }
    }
},

"/repos/<repoName>/wiki/page": {
    "POST": {
        onJsonReceived: function (request, newrec) {
           // here we receive JSON (in newrec) describing a page to be updated or created
           // ...
        }
     } 
}        

These are used in Ajax calls from server_files/ui/modules/wiki/wiki.js. For example, when rendering links to other wiki pages, we validate those links by attempting to retrieve them:

var purl = sgCurrentRepoUrl + "/wiki/page/" + pageName + ".json";

vCore.ajax(
{
    url: purl,
    dataType: 'json',
    reportErrors: false,
    success: function(data) {
        vvWiki.setGoodPage(ln, pageName);
    },
    error: function() {
        vvWiki.setBadPage(ln, pageName);
    }
});

Next up: we follow the code through the creation, update, and merge of a Wiki page.

August 15, 2011 04:04 PM

August 12, 2011

Paul's Work Blog

Building a Veracity Module - Part 1

Veracity was built to be extensible. Not just by virtue of the source being available (although that helps), but also via the embedded JavaScript interpreter. Without writing a line of C, new HTML pages and REST urls can be added, supporting entirely new data types and functionality.

The “native” Scrum functions in Veracity (work items, build tracking, time tracking, milestones, filters, etc.) are nowhere to be found in the Veracity library code. It’s Javascript all the way down, helped out by client-side scripts and HTML. As we add new (or alternative) features ourselves, expect to see many of them show up as new “modules” of pluggable (and un-pluggable) code.

We were going to be adding a Wiki module to Veracity eventually, anyway; and since we wanted to show you how modules are built, a simple Wiki seemed like a nice place to start. This isn’t production code (yet), but it’s an instructive start.

For today, let’s just get the Wiki installed in your Veracity server and make sure everything’s up and running.

Whether you’re building from source or running from a pre-built installer, you’ll need to download the latest nightly build (1.0.1.10527 or later) to retrieve the Wiki module. If you’ve cloned from our public repository, you’ll want to pull the latest.

Within your source folder or the unpacked archive, look for .../src/modules/wiki. Within that directory, you’ll see a README file, some license material, a test directory, and the part you actually care about: a server_files folder.

You’ll want to copy the contents of that folder into Veracity’s server files folder. If you’re unsure where that is, run vv config. Towards the end, you’ll see something like:

server/files: /home/alanswann/veracity/src/server_files

in this case, from within modules/wiki, you’d say (on Unix-y systems):

[~/veracity/src/modules/wiki]
$ cp -R server_files/* /home/alanswann/veracity/src/server_files

and your Wiki code should now included with the rest of Veracity.

[~/veracity/src/modules/wiki]
$ ls ~/veracity/src/server_files/modules
scrum  wiki

Note the above-mentioned scrum module alongside the wiki.

Start (or restart) vv serve, and you should see a wiki item in the top menu.

Veracity menu with wiki

Click that. You’ll see a default home page, explaining that, hey, it’s a default home page. You can edit this page (using Markdown), or click the new page link to add another page.

As pages are created, they’ll show up in the right sidebar, to be clicked and viewed, or inserted into another page’s edit box as links.

Editing a Wiki entry

Next post, we’ll start looking at the code. The good news? All of the heavy lifting is done for us, from the flexibly-licensed editor and preview tools, to the Veracity libraries that handle saves, updates and merges (gotta have merges, it’s a distributed Wiki, after all). I just glued them together.

August 12, 2011 01:37 PM

July 19, 2011

Personal Blog

Video from the July 11th Songwriter's Showcase

"Disappear", "One Man at Best", "The Great Unknown" and "Mind of Its Own", live at the Broward Center for the Performing Arts.

"Disappear"

"One Man at Best"

"The Great Unknown"

"Mind of Its Own"

All four songs are from my album "Acrophobe", available for purchase (CD or download) at music.paulroub.com.

by Paul Roub at July 19, 2011 07:38 PM

July 15, 2011

Personal Blog

"A Little Bit Wiser", live in the WLRN studio

Had the pleasure, last Saturday, of joining Michael Stock in studio on his Folk and Acoustic Music show. This is one of the songs performed therein.

And... uh... sorry about the sunburn. It didn't look that bad on the radio.

"A Little Bit Wiser" is $0.89 at Amazon MP3 - proceeds will go towards sunscreen and common sense.

by Paul Roub at July 15, 2011 07:39 PM

July 11, 2011

Paul's Work Blog

A little merging Jiu-Jitsu

This may well be obvious to anyone bothering to read this blog, but it’s helpful enough for me that I thought I’d scribble it down, anyway.

You’ve made a minor change, just adding some validation code:

$ vv status
Modified:  @/validate.c

$ vv diff
=== ================
===   Modified: File @/validate.c
--- @/validate.c    4b8c0a0278cc18fdeb8592a6b56b81ba4c4b6841
+++ @/validate.c    2011/07/11 19:41:01.000 +0000
@@ -4,4 +4,5 @@
 void validate(const char *user)
 {
         printf("%s, you're awesome.\n", user);
+        printf("And attractive.\n");
 }

You commit, then pull the latest from your team before pushing your changes up.

There are inded some changes, so you’ll need to merge:

$ vv heads

    revision:  7:11e7676e2d8c96071d6ae6748afb29fbea291d3c
      branch:  master
         who:  otherguy@example.com
        when:  2011/07/11 15:44:24.448 -0400
     comment:  more changes you don't care about
      parent:  5:54675c9beeab003fce135282654cf36f9032f326

    revision:  6:3926e0614eb2164bb0839eb1c6ba2c4954107dcf
      branch:  master
         who:  me@example.com
        when:  2011/07/11 15:42:08.610 -0400
     comment:  additional validation
      parent:  4:55205503daa35db9fd3699473da84f49493ef03c

$ vv merge
4 updated, 0 deleted, 3 added, 0 merged, 0 unresolved

$ vv status
   Added:  @/othercode.c
   Added:  @/othercode.h
   Added:  @/whatisthisidonteven.c
Modified:  @/addsprint.js
Modified:  @/connect.js
Modified:  @/reqtest.js
Modified:  @/validate.h

Hrm. A lot of code, none of it yours. The resulting diff is so long I won’t bother to fake it up for the blog. But are you sure none of it’s yours? Skimming through hundreds of lines of diff output looking for problem code is not fun. And all for your little one-liner.

So turn the merge on its head. Starting from the other side, you should easily be able to tell if your changes are being merged in a sane fashion.

# clean slate
$ vv revert --all

# start from the other guy's changes
$ vv update -r 7

# merge in yours
$ vv merge
1 updated, 0 deleted, 0 added, 0 merged, 0 unresolved

$ vv status
Modified:  @/validate.c

$ vv diff
=== ================
===   Modified: File @/validate.c
--- @/validate.c        4b8c0a0278cc18fdeb8592a6b56b81ba4c4b6841
+++ @/validate.c        2011/07/11 19:46:21.000 +0000
@@ -4,4 +4,5 @@
 void validate(const char *user)
 {
        printf("%s, you're awesome.\n", user);
+       printf("And attractive.\n");
 }

# looks familiar. we're good.
$ vv commit -m"merge"

July 11, 2011 08:02 PM

July 05, 2011

openmikes.org blog

Anonymous comments may be going away

There's an excellent chance that, very soon, you won't be able to comment anonymously on openmikes.org listings.

"Report a Problem" will still work, as a way to tell me, privately, that something needs to be corrected. But public comments will require you to login; probably via Facebook, to make most people's live easier.

"Comment wars" on a few listings (almost always anonymous), filled with personal attacks, are a prime example of what happens when people don't have to take responsibility for their words. That, and one particular commenter who uses an endless succession of false names (I delete most of that before you folks need to bother with it), are motivating me to eliminate that option.

If you want to speak up against this change, now's the time.

by Paul Roub at July 05, 2011 08:32 PM

July 01, 2011

Paul's Work Blog

Distributed Bug Tracking Avoids Out-of-Sync Bugs and Code

Chipping away at my Veracity tasks today, I ran across an issue that’s common in DVCS + Centralized Bug Tracking scenarios, but unnecessary and easily-avoided in Veracity.

In a nutshell, it’s this:

Centralized Bug Tracking + DVCS Workflow

  1. I commit some changes, locally, to fix a bug.
  2. I mark the bug fixed, on our one and only bug tracker instance.
  3. I don’t push my code just yet.

Until that code is pushed to the shared server, QA will have my bug in their to-verify list, but won’t have the code to do so.

I might delay the push for a number of reasons - waiting to finish a couple of related bugs and push as a unit; needing to merge and test someone else’s latest code before pushing the results back; etc. Until I’m done, though, we’re out of sync.

You can keep track via special statuses, tags, stamps, etc. (and remember to reset them once you’ve pushed), but why?

When I’m working on Veracity, I’m usually working against a local instance of the bug tracking / web UI. It’s faster, I’m not competing for resources, and I get to do things like associate commits to bugs right from the command line while I work.

It also avoids the problem above, since my workflow looks like this:

Distributed Bug Tracking + DVCS Workflow

This is normal in the Veracity world, and unremarkable except in those instances, like this afternoon, when someone marks a bug closed without pushing up the associated code. Not naming names. We all make mistakes, and I’m sure writing a book can be pretty distracting.

July 01, 2011 08:27 PM

June 26, 2011

Paul's Flickr photos

June 23, 2011

Paul's Work Blog

About

I’m a developer at SourceGear, working on Veracity these days.

Elsewhere in my life, there’s mainly music - you can find out more about that at paulroub.com.

My complaining-about-air-travel needs are handled on Twitter as @paulroub.

June 23, 2011 07:13 PM