Home Theater update

Mon, Dec 22, 2003

I haven't been posting in a while as I've been working on my new Home Theater!

Here is the final setup:

  • Sanyo Z2 LCD projector.  1280x720 widescreen.
  • Paradigm Monitor speakers.  I got Monitor 7s in front with the CC-370 center and the ADP-370 dipole surrounds.  I picked these up in Canada on Chris' recommendation.
  • SVS 20-39PCi subwoofer.  This thing is a beast!  It is over 3 feet high and can really shake the walls.
  • Denon AVR-3803 reciever.  There was a great deal going on these.  Otherwise it would have been way out of my price range.
  • ReplayTV 5504 as a TV tuner.  I got one of these as it was priced wrong at Circuit City.  Normally it is ~$450 with 3 years of service, but they were selling them for $150 with 3 years of service as they had updated the pricing for no included service but the units they still had did have the free service.
  • XBox.  Some games (like Amped 2) do 720p natively.  They look pretty sweet.

I also built my own ceiling mount for the projector and had a friend help me build and paint a screen.  I'll put some pictures up when things get further along.

Changeables desconstructed

Mon, Dec 22, 2003

Frank Hileman (no blog, Frank?) has been pounding us (the Avalon team) with some great questions.  Most of these have been conversations in comments, but I figured that I should bring this to the front page, so to speak.

Of of Frank's concerns, at least as expressed in my comments section, is that we are essentially over engineering with the Changeable pattern.  Specifically, he says this:

The non-intrusive part of Changeable has a const flag on stock brushes, etc. This means the user must clone these and write to a copy. This is simple and easy to understand.

The intrusive part of Changeable is the part which introduces the idea of "used" and changes the simple concept of "object reference" into something complicated. From what you have explained, the intrusive part of Changeable exists only to allow simultaneous multi-threaded writers to the scene graph.

I think that the point around threading is a red-herring here. 

Changeable Requirements

The main problem that changeables are trying to solve is that we want to have, under most circumstances, these changeable API objects (Brush, Pen, etc.) act like value types and other times we want them to act like refernce types.  We essentially want to walk a fine line and get advantages from each.  Frank, forgive me if you've heard a bunch of this before, but I think that this is useful to put together in one place.

With respect to value types, we want the simple user semantic to be: Modify my local copy and have it be disconnected or "severed" when I pass it in to another object.  When rendering this means that I can do this:

SolidColorBrush scb = new SolidColorBrush();
scb.Color = Colors.Blue;
myDrawingContext.DrawGeometry(scb, null /*pen*/, myGeometry1);
scb.Color = Colors.Red;
myDrawingContext.DrawGeometry(scb, null /*pen*/, myGeometry2);

and have my two geometries be drawn with different colors.  Since many times the drawing context is writing in to a metafile like data structure, if we used pure reference semantics both geometries would be drawn as Red. 

Another example is setting properties in to a set of elements:

SolidColor Brush scb = new SolidColorBrush();
scb.Color = Colors.Blue;
myElement1.Background = scb;
myElement2.Background = scb;

// in some other code...
((SolidColorBrush)myElement1.Background).Color = Colors.Red;

I think, in most cases, if some user walks up to an element, such as myElement1 above, and sets the background brush, he doesn't expect that this will have the side effect of changing the background brush of another element.  Side effects like this would make for an unstable system.

Value types don't solve all of our problems though!  We also want the efficiencies and advanatages of making these be reference types.  Specifically, we want to have to have hierarchies, not have to copy the entire thing around and be able to save space by having multiple places reference the same thing.  We imagine a world with lots of elements getting their values via styling.  Because of this, we want the normal case be that a user puts a value in to a style block somewhere and then that object (via reference) gets widely shared, perhaps between hundreds of elements.  We obviously want to make the per-reference cost as small as possible here.  Going with a pure value type system won't work.

The Builder Pattern

The first cut at solving this problem was called the Builder Pattern.  This pattern was a generalization of the StringBuilder pattern.  Specifically, for each type, there was a companion, or Builder type.  The main type was immutable.  In other words, any write operations would raise an exception.  So, for SolidColorBrush, we wrote a SolidColorBrushBuilder.  SolidColorBrush was immutable while SolidColorBrushBuilder was a fully writeable object.  All of the APIs in the system (property types on element, parameters in to DrawingContext methods, etc.) took the non-builder types.  To create one of those non-builder types, the user had to do one of the following:

  • Create the target type directly by using a constructor.
  • Create a builder, configure it, and call the ToXXX method on it to construct the main type.
  • Create a builder by initializing it off of its companion type.  Make a delta and call the ToXXX method to construct the main type.

From one point of view, this is a great system.  It is very explicit (at compile time) what is editable and what isn't.  However, some early users of our system (ad-hoc usability) ended up really disliking this system.  The need to constantly deal with both types was onourous.  It also meant that the user could never just index directly in to a type and change it.  To affect any change, it was always necessary to create the builder, make the change, and set the old value in.

The Changeable Pattern

In response to a hail of internal criticism on the Builder Pattern we went back and came up with the Changeable pattern.  The idea is that we would have one type object with an immutable bit.  Once the immutable bit gets set, all further changes to that object will throw.  This opens the way up to runtime errors (instead of compile time errors) but makes certain "delta" scenarios much easier to deal with.

However, we still wanted to solve the problems listed in the first part of this post.  Specifically, we didn't want to leave it up to the user to manually flip the immutable bit.  In this way we defined certain types of operations that would automatically create a copy and flip the immutable bit for you if necessary.  We then went further and added advanced modes so that those APIs either make a copy but don't flip the immutable bit or the APIs just take a reference.  These last modes (whereby something like an element holds on to a mutable brush) were never possible with the Builder pattern.

We also added a notification mechanism so that someone who does hold on to an object that isn't immutable can learn when that object changes.

So, do you guys (Frank?) like the more explicit builder pattern better?  More questions?

DX interop in Avalon

Mon, Dec 22, 2003

Vince (who I knew in high school as Steve) wrote in my comments:

How can I get to the underlying DX9-esque interface I know you guys gotta be using this stuff. I don't want to deal with EllipseGeometry objects and the like, gimme DrawPrimitive, push buffers, and pain-in-the ass ITexture objects.

Don't worry dude!  The details are still being worked out, but we know that we have to make it possible for people to interop with old code, and with DX.  At the very least, you will be able to host another hwnd window that is written using GDI/User or DX.  The details on when and how DX will get accelerated, and how it will play with the rest of the system are still TBD.  At the very least, when you go full screen with DX you will own the device.

For simple 3D stuff (load up a model and spin it around like a 3D icon) we will have our own 3D API that doesn't pretent to offer all of the flexibility of D3D.

What specific scenarios are you interested in?  My thinking is that you might want to write a tool and have the UI done with Avalon and the "canvas" of the tool done via D3D.  In this scenario, you are in a windowed situation and Avalon is on top.  The 3D stuff is running in a window in an Avalon app.  Another scenario that might be interesting is that you have a D3D app/game and you are using Avalon to drive 2D type UI inside of the game environment.

I can't promise that all of the scenarios will be doable, but let me know what is most important to you.

Holiday parties

Mon, Dec 22, 2003

I went to a great holiday party last night thrown by my neighbors, Bob and Carol.  We moved in quite a while ago but hadn't really had a chance to interact with any of our neighbors yet.  This was a great opportunity for us to not only chat with our hosts, but also others from around the neighborhood.  It turns out that the internet makes the world even smaller.  Bob had run across my blog and already knew more about me (or at least my work!) than I knew about him.

I also chatted with our neighbors on the other side, Gary and Marge.  Gary is a long time photographer that just recently went digital with a Canon 10D and a sweet lens setup.  He sent me a link to some of his images.  These were done with film -- a Pentax 6x7 that he recently sold.  I really need to get off of my butt and put together a gallery of some of my better up on the net.