Nine Inch Nails and the New Online Business Model

As many people may already know, I am a big fan of the band Nine Inch Nails, aka NIN, which is basically Trent Reznor and whomever he hires to work and perform with him at any given time. Earlier in the week, Trent posted that a new album was available, titled “Ghosts I-IV” (volumes one through four). Not even “coming soon,” but available right now. Being a fan, I was naturally psyched about this and went to find out how I could get a copy right now.

Eventually I succumbed and bought the $300 super ultra deluxe edition that comes with four LP’s, two CD’s, one DVD, one Blu-Ray, an art book, ready-to-frame-and-hang art, and Trent’s signature. Plus it’s a limited edition with only 2500 copies. Hey, I need to use those Paint.NET donations for something, right?

The real story here is not that NIN has a new album, but rather in the way that it is being distributed. The music has been released under the Creative Commons Attribution Non-Commercial Share Alike license. Anyone who gets a copy of it has the freedom to make further copies and derivative works (e.g., remixes), as long as they give proper attribution and don’t make any money off of it. You can even download the album for free. They provide direct download links for 1/4th of the tracks, but with that license there’s nothing wrong with distributing or downloading the rest of the album if you find it elsewhere. Trent himself even uploaded those tracks to PirateBay* with a note saying:

“Undoubtedly you’ll be able to find the complete collection on the same torrent network you found this file, but if you’re interested in the release, we encourage you to check it out at ghosts.nin.com, where the complete Ghosts I-IV is available directly from us in a variety of DRM-free digital formats, including FLAC lossless, for only $5.”

Let’s take a step back though, first. The music industry is in a jam because 1) everyone is pirating music (PirateBay, LimeWire, BearShare, etc.), and 2) everyone hates DRM. Oh, and 3) all those lawsuits are making everybody hate them (the RIAA). The majority of people don’t care about paying for most of their music, but those who are willing to pay for it are getting punched in the face with the restrictions that DRM imposes. And even if you buy the CD, only a small percentage of what you pay actually reaches the artist who created the music in the first place. It’s really a lose-lose situation for everyone except the CEO’s of the record companies.

Recently, Trent announced that he is now free and independent of any record label contract, after fulfilling his obligation for a certain number of albums with the “Year Zero Remixed” disc. So, he can now do whatever the heck he wants to, business-wise. He has decided that he will take advantage of the freshly-crowned, most popular method for distributing music: rampant piracy! Except in this case it isn’t pirating because he’s intending people to distribute it this way. He’s getting new fans for free this way, and those fans will find other ways to send him money: concert tickets, t-shirts, and other “non-pirateable” goods. And without a record label as an intermediary, more of that cash goes into his pocket, which is exactly what we want!

It will be interesting to see how well this business model and experiment works out. The real test, however, will be whether this model will work for any other band, especially one that isn’t so widely known.

Also worth noting is that this is basically the business model that Paint.NET has been using for the last few years 🙂 Except that I do not [yet?] have any cool deluxe or limited editions for sale. Hmm, I wonder how much an autographed CD of Paint.NET would go for …

* “Uploaded these tracks to PirateBay” is actually a strong misnomer with the way BitTorrent technology works. But you get the idea.

Ask and you shall receive … Color Wheel for IndirectUI

As part of the version 3.30 release of Paint.NET, I have finally marked all of the code in PaintDotNet.exe as “internal” (instead of public). This code was supposed to be treated as internal implementation details of Paint.NET, but plugin authors were using the code anyway. So, at some point or another I was going to have to do this, and I chose version 3.30 as the ship vehicle.

(See, in Visual Studio 2003, which was the original development environment for Paint.NET, you couldn’t add an EXE as a reference. Then they added this capability in VS2005, but I didn’t catch on until later. So I had always assumed that plugins couldn’t access this stuff and so I didn’t need to mark it all as internal. Oops!)

Well, as it turns out, one of the most popular controls that was being used by plugins was the color wheel. You know, this thing:

This is causing many plugins to break, and I’ve been unmoving in allowing plugins to continue access it. However, KrisVDM on the forums had a reasonable request:

Rick, I don’t know if you followed the discussion on http://paintdotnet.forumer.com/viewtopic.php?f=16&t=22881 , but basically they’re begging and calling me names because I dropped the color wheel from the Drop Shadow UI.

I know I said so before, but I believe many effects and adjustments could benefit from a color wheel (or even two for my duotones) in the effect UI.

Would you please consider adding IndirectUI support for colors?

I told him I would look into it, and tonight I was able to crank out a control for this in about an hour:

It’s in private testing as we speak, and should have no trouble making it into the next beta update for v3.30. It should be a welcome addition for plugin authors.

Paint.NET learns Italian!

There’s one more feature, so to speak, that’s been able to sneak in to the v3.30 release. From the blog title it should be obvious: Paint.NET will soon be available in Italian!

I get a lot of e-mails asking for this, and now thanks to the hard working folks in Microsoft Developer Division ("DevDiv"), it will now be available. (DevDiv also handles the other 7 non-English translations)

"Just Add More Cowbell"

As an owner of a software project, one trap that’s easy to fall into is that of adding more and more features. Quite often these features do in fact add value, but there’s a certain point where adding features ends up being superfluous and actually has a negative impact. At that point, adding more features is akin to "more cowbell," as made famous by the Saturday Night Live skit with Christopher Walken and Will Ferrel. When it comes to deciding on the feature set for a new release, you should ask yourself: "Is this feature necessary? Or is it just more cowbell?"

With Paint.NET, I believe that I have, for the most part, avoided the trap of "more cowbell." However, it’s becoming more difficult. It is very easy for me to add new effects and adjustments and to then put out a new release which results in a spike of downloads, media attention, popularity, and of course … cash. Never underestimate the power that cash can have on the owner of a software project. If there’s no cash involved at all, then progress is slow and at one’s leisure. Too much cash and it becomes easy to fall into the trap of putting out "cowbell releases" because they’re easy. They make money. Apathy can then set in because, hey, rich people don’t have to care, right?

The work that needs to be done for Paint.NET v4.0 is, honestly, quite enormous and even intimidating. And while I’m working on it I need to have at least a trickle of releases using the v3.xx code base in order to keep public attention alive, and also to keep the money coming in. But, I don’t want to make any major changes in the v3.xx design or architecture because then that adds more stuff I have to rewrite or integrate in to v4.0. So, the natural thing to do is to add more effects or adjustments — because of the way these all use the same underlying hosting and execution system, I can literally add tons of these without adding extra work to v4.0.

However, doing this immediately puts Paint.NET into "cowbell territory". I was just thinking about the feature set I’ve made for v3.30, and I’m realizing that it’s teetering on the edge of this. The ability to save in new bit-depths with PNG is useful, but I’m also adding a big group of new effects that, honestly, I’m realizing mostly serve to make the release appear more feature-laden. In fact, I don’t think Vignette and Posterize are really that important, and so I think I’m going to cut them from this release. If you want them then you can download them in Ed Harvey’s plug-in pack from the forum.

So, as 2008 continues to progress, I’m still trying to figure out how best I can get more time to work on v4.0, while continuing a trickle of v3.xx updates, while also minimizing my engineering investment in it, while also avoiding turning those updates into "cowbell releases." One way that you can help is to point out when or if you think you see "cowbell" in Paint.NET!

Paint.NET v3.30 Preview

It’s time once again to start babbling about the next minor update to Paint.NET, which will be version 3.30. I’m planning to push it out the door in early April. Here’s what’s coming:

  • Integration of Ed Harvey’s Fragment, Vignette, and Posterize effects.
  • An enhanced version of the Polar Inversion effect, also written by Ed Harvey and originally included in his “Polar Inversion +” plugin.
  • PNG will now support saving in 8-bit and 24-bit. There is also an “auto-detect” option where Paint.NET will analyze the image and auto-select the lowest bit-depth that can save the image losslessly.
  • BMP will now support saving in 8-bit. It will also have the “auto-detect” option, but there is still no 32-bit BMP support. GDI+ just refuses to cooperate in allowing me to do that.
  • TGA will also support the “auto-detect” option, for its 24-bit and 32-bit support.
  • For developers, IndirectUI is now available for writing UI for file type codecs. There are also some extra property rules you can use, such as the ability to link values based on a checkbox (useful for linking R,G,B sliders for instance).
  • The usual round of bug fixes, including some memory corruption bugs I found after noticing that some effects were trying to access coordinates that couldn’t possibly exist. “NaN” is not a valid coordinate 🙂

After v3.30, I am planning two small updates after that: v3.32, and v3.34. These should include the usual round of bug fixes (there is always something to fix, even if it’s minor!), but also Ed Harvey’s “Surface Blur” and “Dents” effects. I will probably release v3.32 from 6 to 8 weeks after v3.30, and then v3.34 at 6 to 8 weeks after that. Hopefully this will give me a good chunk of time to devote to working on v4.0!

Another Dumb Way to Start a Business Proposal

They just keep coming in.

Subject: re: advertising proposal

Hi,

I am a media buyer at Medios One LLC (www.mediosone.com).  I am interested in buying inventory on your site.  MediosOne is a global online advertising network.  We have offices in 5 countries and many more support offices around the world.  Our publisher network model gives us access to large amounts of high  quality inventory from all types of sites, which are targeted to users in many geographic locations. Some of the advertisers we work with include ICICI, Make My Trip, Max New York Life,  Zapak.com, Colgate, Hewlett Packard, Tata Sky, AOL, Citibank, and  India Times. We are  currently looking for publishers to add to our network. Currently, we are running a good  amount of campaigns targeted to the US, Asia, South America, UK as well as Western Europe.

Can you help me reach the appropriate person who handles advertising sales for your website?

If you are the correct person please let me know and we can move forward, if not would you please direct me to that person in your company.

I look forward to your response and the possibility of our companies doing business together.

Thank you,
Jobette Escobanas
contact information removed

This e-mail was actually relatively well written, and polite. They get points for that, as well as for targeting the global market and not just being limited to English and the good ol’ U.S.A. To nitpick his e-mail, he states his company’s name different ways: is it MediosOne, or Medios One? Also, why would I want Colgate ads on my website?

Maybe I’m old fashioned, but I think that details really do count on an e-mail like this. It’s obviously a copy-pasted e-mail with no mention of my name, my company’s name, my product’s name, the website address, or anything that tells me that the e-mail was targeted at me and not just blindly multicast to hundreds of other e-mails. To be honest, I’m at the point where any business deal I set up must be five figures per month and that’s not something I’m going to trust with just any drive-by e-mail with random spacing anomalies and other inconsitencies.

Also, Jobette has made an enormous faux paus in my book: He started the subject line with ‘re:’. Why did he do that? Does he think he has to trick me in to reading his e-mail by making me think this is part of an existing conversation thread? I don’t get it. Maybe it was a mistake, who knows. In any event, no thanks Jobette … but best of luck though I suppose.

Lastly, I apologize for not blogging much lately. I’ve been busy with work, social life, and of course Paint.NET work. And Rock Band. I’ve made enhancements to the PNG, BMP, and TGA codecs that have come with some refactoring work, as well as having extended IndirectUI to work with file type codecs/plugins. We were also tracking down a bizarre enumeration related bugs with the .NET runtime … I seriously thought my computer was failing and I”d have to buy new RAM, but then tracked it down to a smashed stack. Interesting stuff.

Paint.NET is going to get 8-bit and 24-bit PNG support

"It’s about time!!!" — Many users who keep pestering me for this

I just finished about 90% of the code for adding 8-bit and 24-bit support to Paint.NET’s PNG codec. Most of the work wasn’t even in the PNG codec itself, but rather in adding IndirectUI support for FileType plugins. Once that was done, the extra PNG code just tripped and fell into place. I just really didn’t want to write another WinForms widget complete with obnoxious layout and data binding.

(dang, I was trying to add a screenshot, but Windows Live Writer refuses to cooperate, oh well — I’ll save it for later I guess?)

To be honest, it’s that laborious and error-prone WinForms code that was preventing me from adding this support over the last 2 years. After you write it once you realize that you just don’t want to write and debug it ever again. With IndirectUI I only have to write the layout and data binding once, and then I can re-use it for every other file type configuration UI I make going forward.

I also plan to redo the configuration UI for the GIF, TGA, and DDS file types so that they use a few simple lines of IndirectUI instead of mountains of WinForms code. Who knows, maybe expanded BMP support will make it into the next release as well. Why not? I wish everything was as easy to implement as with IndirectUI.

Also, while implementing this I found out that the SOAP formatter for .NET serialization has essentially been deprecated. It doesn’t support serialization of types that have generic type parameters, and will not be updated … lame! So I have moved the persistence for file type settings over to the BinaryFormatter. This means that the next Paint.NET update will forget any settings you’ve had for file types. For instance, if you had JPEG set to a quality of 75 or something (default is 90), that will be reset in the next update.

Heterogeneous Catch Clauses for CPS Exception Handling

Well, that title is certainly a brain-full and won’t win me any search engine rankings for popular query terms.

Anyway, Nidonocu had an important question he posted on my previous post about the "Do" class:

This looks like this could be quite a useful class but I was wondering how this might work when it comes to wanting to catch specific exceptions rather than just the base Exception type?

I know from using FxCop that using ‘catch (Exception)’ is something Paint.net rather a lot and while I’m sure you sleep at night doing that, its something I’m trying to avoid in my own app. 😉 Are there any simple ways this code could be tweaked to not use Exception?

The issue is that the various TryCatch() helper methods only take a single delegate for the catch clause, and they always take the base Exception type. In essence, the burden of exception type filtering has been placed on that single delegate, forcing you to do something like:

Do.TryCatch(
    () => DoSomething(),
    (ex) =>
    {
        if (ex is InvalidOperationException) { … }
        else if (ex is SystemException) { … }
        else if (ex is FileNotFoundException) { … }
        etc.

    });

Even then, you can’t use "throw" to propagate the exception correctly. This may also encourage lazy exception handling that only covers the generic "oh no something happened" situation. We’re trying to simplify the code, darnit! You see, I knew about this problem, but I didn’t have a solution for it yet. The type of syntax that I wanted was this:

Do.TryCatch(
    () => DoSomething(),
    (InvalidOperationException ex) => { … }
    (SystemException ex) => { … }
    (FileNotFoundException ex) => { … });

This would be very nice and intuitive, and fairly succinct. You would expect the function signature for Do.TryCatch() to look like the following at this point:

void TryCatch(
    Procedure tryFn,
    params Procedure<Exception>[] catchFns);

But you run into a huge problem here. The C# compiler will try to convert each of the lambda expressions into Procedure<Exception> but will be unable to do so — it will convert the first one to Procedure<InvalidOperationException>, etc. and then spit out errors because it can’t convert it. (Actually, it will simply see that the lambda cannot be paired up with Procedure<Exception>, so that last sentence is a weird, technically incorrect simplification.) This is unintuitive at first, but makes perfect sense after thinking about it for a few minutes.

Even if two types, T1 and T2, have an inheritance relationship of T2:T1 (that is, T2 derives from T1), this does not create a relationship between Procedure<T1> and Procedure<T2>. For us, this means that even though InvalidOperationException derives from Exception and is thus substitutable for a parameter that is declared as taking an Exception, it is not the case that Procedure<InvalidOperationException> is substitutable for Procedure<Exception>. They are two distinct types in the .NET runtime. We are doing exception filtering, which is a different problem than just covariance or contravariance (I can never keep those two terms straight, I’m not sure which one applies here).

I was, however, able to set things up to my liking … almost. Here’s the syntax I was finally able to achieve:

Do.TryCatch(
    () => DoSomething(),
    CatchClause.From((InvalidOperationException ex) => CatchResult.Throw),
    CatchClause.From((SystemException ex) => CatchResult.Handled),
    CatchClause.From((FileNotFoundException ex) => { MessageBox.Show("Couldn’t find file!"); return CatchResult.Handled; }));

We are no longer passing a list of delegates to TryCatch(). Instead, we have a CatchClause class (aka functor) that implements a CanHandle() function to allow for filtering, and then a Handle() method that returns CatchResult.Handled to finish the catch clause, or CatchResult.Throw to re-throw the exception.

So, in order to effectively force a type relationship between the delegates (which cannot have "inheritance relationships"), we have to wrap them inside instances of class objects which do have that type relationship we want. In our case, we provide this relationship with a base class called CatchClause, which then has a derived CatchClause<TEx> class, where TEx has a constraint forcing it to derive from Exception. Then, we use CatchClause<InvalidOperationException>, CatchClause<SystemException>, etc. All of these are substitutable for the base CatchClause class, which lets our magic work. Finally, a static helper method in the base CatchClause class makes our TryCatch() usage easier to read and write. Unfortunately we cannot use an implicit type-conversion operator because those cannot take generic type parameters, and the type inference system isn’t quite psychic enough to enable it to work anyway.

Here’s the code, which I hereby release into the public domain:

public enum CatchResult
{
    Handled,
    Throw
}

public abstract class CatchClause
{
    public abstract bool CanHandle(Exception ex);
    public abstract CatchResult Handle(Exception ex);

    public static CatchClause From<TEx>(Function<CatchResult, TEx> catchFunction)
        where TEx : Exception
    {
        return new DelegateToCatchClause<TEx>(catchFunction);
    }
}

public abstract class CatchClause<TEx>
    : CatchClause
      where TEx : Exception
{
    public override bool CanHandle(Exception ex)
    {
        return typeof(TEx).IsAssignableFrom(ex.GetType());
    }

    public abstract CatchResult HandleT(TEx ex);

    public override sealed CatchResult Handle(Exception ex)
    {
        return HandleT((TEx)ex);
    }
}

public class DelegateToCatchClause<TEx>
    : CatchCla
use<TEx>
      where TEx: Exception
{
    private Function<CatchResult, TEx> catchFunction;

    public override CatchResult HandleT(TEx ex)
    {
        return this.catchFunction(ex);
    }

    public DelegateToCatchClause(Function<CatchResult, TEx> catchFunction)
    {
        this.catchFunction = catchFunction;
    }
}

public static void TryCatch(
    Procedure actionProcedure,
    params CatchClause[] catchClauses)
{
    TryCatch(actionProcedure, (IEnumerable<CatchClause>)catchClauses);
}

public static void TryCatch(
    Procedure actionProcedure,
    IEnumerable<CatchClause> catchClauses)
{
    try
    {
        actionProcedure();
    }

    catch (Exception ex)
    {
        foreach (CatchClause catchClause in catchClauses)
        {
            if (catchClause.CanHandle(ex))
            {
                CatchResult catchResult = catchClause.Handle(ex);

                if (catchResult == CatchResult.Handled)
                    break;
                else if (catchResult == CatchResult.Throw)
                    throw;
                else
                    throw new InvalidEnumArgumentException("catchResult", (int)catchResult, typeof(CatchResult));
            }
       }

       throw; // no one handled it, so rethrow
    }
}

"Use Paint.NET to Photoshop it"

I guess "Photoshop" really is turning into a generic verb, something that Adobe is undoubtedly unhappy about. I found this on a Q&A website, paraphrased for readability:

Question: "My friend has pictures of her eyes, a different color that really stick out. It’s grey and her eyes are bright blue or neon green. Please tell me how to do that." (Note: I believe they are asking how to take a picture of someone’s face and apply a grayscale effect to only the eyes.)

Answer 1: "Oh yeah, I’ve seen that but I don’t know how to do that either … let’s read what everyone else has to say, I want to know too…"

Answer 2: "use paint.net to photoshop it"

I won’t link to it so as to preserve their anonymity, but it’s easy enough to find by doing a search for the title of this blog post (including the quotation marks).

Anyway, I just thought that was curious enough to share … 🙂