A splat of all my blathering.

Thursday, April 22, 2004

Base64 and URL Encodings 

Here's a useful site for testing encodings http://ostermiller.org/calc/encode.html

Posted at 4/22/2004 03:58:00 PM | (0) comments

Monday, April 19, 2004

Instant Runoff Voting 


Why don't we use this form of voting? Makes me wonder...

Posted at 4/19/2004 06:28:00 PM | (0) comments

Mounting the projector  

There are many different ways to mount a projector. I decided to mount mine to the ceiling so that it would be out of the way. I looked into the projector mount kits that are sold at projector retail sites. There are many, many to choose from. The first thing to check out is the plate that screws to your projector. They make some that are static (made specially to fit a project model) and some that are flexible (they have spider arms that adjust to any angle and reach) to fit almost any projector. The next thing you need to decide is how far the projector will extend from the base. In my case I needed the projector to drop down about 10" from the ceiling because the image would otherwise be blocked by the basement ducting. These extensions are also available but are really quite pricey considering what they are. In fact, the pipe they use is the same that you can buy at Home Depot for plumbing. It's just 1 1/2" NPT (National Pipe Thread, the kind we use in America) metal pipe. I bought my 6" piece at Home Depot for about $3. I also found a floor flange that I could bolt to the ceiling and screw the pipe into. That just left me with the plate that attaches to the projector. The plate comes with an attachment that has a female connector to connect to the pipe hanging from the ceiling. I bought this part online at Mounts and More for $149.50. I wanted to buy this part instead of making it myself so that I was sure that it would fit my projector and because it comes with a very nice ball-in-socket design for precision adjustments. You'd be surprised how much the image moves on a wall 16' away when you move the project 1" on axis. (In fact, the answer is that it moves 32".) It also comes with an easy way to detach the projector so that I can remove it for cleaning or using it elsewhere.

I bought a can of black paint and painted both the flange and the threaded pipe that I bought from Home Depot. Then I mounted the flange to the ceiling using 2 1/2" machine bolts. I pre-drilled the holes in a ceiling joist for two of the bolts and used expansion anchors on the other two since they were in drywall only. I weight about 150lbs and was able to hang from it. I then screwed the threaded piece from the project mount part to the pipe. I attached the projector mount to the projector using the supplied screws and then finally attached the projector to the ceiling mount. Using an Allen wrench supplied with the mount plate I tightened down the screws that lock the project in place and was ready to go.

The next thing was to wire the video cables and electrical outlet right next to the mount so that I wouldn't have to run exposed cables. I'll talk about making your own component video cables in an upcoming blog.

Posted at 4/19/2004 04:39:00 PM | (0) comments

Choosing a home theater projector screen: Part 3 Size 

Now lastly but perhaps most importantly I needed to decide how large of a screen I wanted. This is important because people who have no idea about all this work that goes into building a home theater really only comment about one thing... the size factor. "Wow, look at the size of that screen! That's awesome."

I talked with several people about this topic at my local stores and as usual, I got several differing opinions. Some said that quality was more important than size (and that is the tradeoff) and some said that bigger was the only way to go.

In my case I had some limitations because my room is quite small. I also had to figure in what my projector would be capable of doing in quality. I wanted around a 100" diagonal on my viewing area so that meant that I needed a screen that was 6 x 8 (recall that I went with the 4:3 format). I checked DaLite's site for a price on the Model C in this configuration and found that it was about $265. That was indeed very pleasing to me but I wasn't ready to give in just yet. I'm frugal (if you haven't already noticed) and I wanted to check around for better pricing. As it turns out DaLite's price was very good and the only reason that I didn't buy it directly from their website was that I found a local store that would price match. This turns out to have been a great idea because the screen was delivered damaged. I think that this is very rare and the local store was very apologetic (they could see the tears streaming down my face) and helpful. I got the replacement screen 5 business days later and installed it the following weekend.

Since my room is still being finished I just have bare studs on the wall where the screen is going. I had some 3" x 1/4" lag bolts laying around so I put them into the wall and used washers to secure the screen frame. I just couldn't wait to see what my projector and screen would look like together.

I hadn't mounted the projector yet because I still wanted some flexibility after seeing what it looked like with the screen. I sat the projector on top of a really heavy shelf and leveled it with a blanket. It turns out that I was within about 6" of my ideal size. With the 1.2x zoom capabilities of the X1 I could easily scale the image to the 100" diagonal. I was very pleased at how everything was turning out. My next task was to mount the projector on the ceiling.

Posted at 4/19/2004 03:20:00 PM | (0) comments

Step-up voltage transformers 

Last week I wanted to buy a device that would take my 110V outlet and allow me to plug in a 220V appliance. I wanted the device to be installed permanently in the wall so that I could use it frequently.

What I found is that I can't do this. First of all I couldn't find such a device anywhere. I also found out that putting such a device directly in the wall doesn't meet code. Apparently, the electric company doesn't like such things attached directly to the grid. The solution that I found was to buy a step-up voltage transformer.

While I was researching I found a couple interesting sites.

Posted at 4/19/2004 10:50:00 AM | (0) comments

Wednesday, April 14, 2004

RCWs and reference counting 

Over the last couple of days I have been working with a couple of my team members to identify a problem with our DCOM server interacting with a managed class implementing a CCW. In the method call to the CCW the DCOM server passes a COM interface which the managed class uses via an RCW. We were seeing the DCOM server crashing at pretty regular intervals and they always coincided with a .NET garbage collection. It turns out that the problem was in the DCOM server code but during our testing I found some important things that I didn't know before about RCWs.

When an interface is passed to a managed object an RCW is used. As I understand it, in this simple case (no cross-AppDomain marshalling), the RCW will hold a single reference to this interface which effectively bumps the reference count by 1. When the RCW is no longer referenced it will be garbage collected and during this process Release will be called which will decrement the count by 1. Note, that this *could* result in the COM object being deleted. While inside the method call the interface is still being referenced so will not be garbage collected right away. This is true even if you call GC.Collect();GC.WaitForPendingFinalizers();. However, the very next time the GC is run this object could be collected.

Please note that this behavior is not a bug. It is a known feature of the .NET runtime and well documented. I'm just pointing out that it may not be immediately obvious.

Consider this example (error checking removed for brevity):

// in the DCOM server code
void CServer::ExecutePlugin()
  CComPtr<IPlugin> pPlugin = 0;
  HRESULT hr = pPlugin.CoCreateInstance(L"MyPlugin.MyPlugin", 0, CLSCTX_SERVER);
  CComPtr<ISession> pSession = 0;
  hr = pSession.CoCreateInstance(L"Server.Session.1", 0, CLSCTX_SERVER);
  hr = pPlugin->Execute(pSession);

// in the plug-in code
class Plugin : IPlugin
  public void Execute(MySession session)

After the call to pPlugin->Execute(pSession) has returned the reference count on the pSession object will be (at least) 2. One for the initialize CCI and one for the RCW created for the managed plug-in. After the local CComPtr is deleted the reference count will be 1. This means that the object will not be deleted within the scope (or thread) of the CServer::Execute method. In fact, with some trivial tracing added you can see that the destructor of the pSession object is called from a different thread altogether. This thread must be the GC thread that is cleaning up the RCW for the ISession object.

The reason why this is important to keep in mind is that if the DCOM server was not correctly following the rules of COM interface reference counting of the ISession object, then the resulting bug would not manifest itself so easily if the plug-in were written in unmanaged code as it would in the managed case.

Most, implementors of the IPlugin interface would realize that the ISession interface handed to their Execute method does not require an AddRef and Release since it is not being copied and so the reference count would remain at 1 for the entire lifetime of the CServer::Execute call and the object would be destroyed when the CComPtr left scope. In this case the object would be destroyed on the same thread as it was created and not some other .NET GC thread.

In the managed case the RCW will most likely be the last reference to the pSession object and therefore release it only when GC'd. If the COM object was deleted prematurely because of not following the rules of COM, this might manifest itself as some kind of null derefence exception or crash.

Posted at 4/14/2004 02:20:00 PM | (1) comments

Tuesday, April 13, 2004

Detecting which .NET Framework version is installed? 

How do I detect what .NET Framework version is installed on a machine?

Posted at 4/13/2004 02:29:00 PM | (0) comments

Using CAPICOM and OpenSSL 

I was recently challenged with a project that required sending a secure message from a Windows network to a *nix network. The client insisted that we use CAPICOM on the Windows side and the partner on the *nix side was adamant about using OpenSSL. I figured since both libraries were capable of support PKI they must be compatible but I was unsure of how. I was also skepticle because CAPICOM is notorious for its proprietary implementation. After many unsuccessful attempts, talking with folks at Microsoft, and reading gads of web pages on the subject I was becoming quite unsure that it could be done. However, MS suggested that it was possible and that the PKI implementation of CAPICOM did support the standards. The trick was to figure out how.

After quite a bit of reading and playing with OpenSSL for Win32, I was able to come up with a way to use CAPICOM 2.0 and OpenSSL together to send a secure message. The key was with the S/MIME capabilities of OpenSSL.

In my situation I needed to sign and envelope a message using CAPICOM (on Windows of course) and send the message to a *nix machine using OpenSSL to decrypt and verify it.

For this example I will use VB 6.0 (sorry) to drive the CAPICOM calls. I am following the best practices of PKI solutions such as PGP as closely as I could (I think). In particular, I am embedding the plain-text content within the signature for use in the verification process later. The signature is then encrypted within the envelope so that only a single file needs to be sent. This results in a slightly larger envelope but simplifies the process by not requiring separate messages to be sent.

One thing to note is that CAPICOM is a scriptable COM interface and therefore uses BSTR as the string format of choice. This means that all content will be represented in UNICODE and will require translation on the server so that *nix tools like OpenSSL can interpret them.

The following VB code shows 4 sub-routines that read, write, sign, and encrypt a clear-text text file as well as an event sub-routine for a simple form with a single button for kicking the process off.

I am simplifying the example by removing the error handling and making some assumptions about the storage of the certificates being used. I am assuming that the certificates are stored in the local user store called “My” and that the certificate location is known. Almost certainly, neither of these would be the case in the real world.

' I do not claim any responsibility for the correctness or security of this code

' and any or all portions should be used at your own risk.

Option Explicit
Const ForReading = 1, ForWriting = 2, TristateFalse = 0
Const TemporaryFolder = 2

Private Sub Command1_Click()
  SignFile "c:\temp\in.txt", "c:\temp\signed.txt"
  EnvelopeFile "c:\temp\signed.txt", "c:\temp\smime.txt"
End Sub

Sub SignFile(ByVal sInFile As String, ByVal sOutFile As String)
  ' Open the MY store and retrieve the first certificate from the
  ' store. The signing operation will only work if this certificate is
  ' valid and has access to the signer's private key.
  Dim oCertStore As New Store
  Dim oSigner As New signer
  ' The signer's certificate is at index 1
  oSigner.Certificate = oCertStore.Certificates.Item(1)
  Set oCertStore = Nothing
  ' Set the content to be signed.
  Dim oSignedData As New SignedData
  oSignedData.Content = ReadFile(sInFile)
  ' Save the time the data was signed as a signer attribute
  ' NOTE: the name 'Attribute' is not a unique name
  ' and must be preceded by 'CAPICOM.'
  Dim oSigningTimeAttr As New CAPICOM.Attribute
  oSigningTimeAttr.Value = Now
  oSigner.AuthenticatedAttributes.Add oSigningTimeAttr
  ' Sign the content using the signer's private key.
  ' A value of 'True' in the second parameter indicates that the
  ' content signed is not included in the signature string.
  ' A value of 'False' indicates that it is
  Dim s As String
  s = oSignedData.Sign(oSigner, False, CAPICOM_ENCODE_BASE64)

  ' Strip off the last blank line
  s = Mid(s, 1, Len(s) - 2)
  ' Add the PKCS #7 header and footer so that the signature conforms to what
  ' OpenSSL expects.
  s = "-----BEGIN PKCS7-----" + vbCrLf + s + vbCrLf + "-----END PKCS7-----"
  WriteFile sOutFile, s
  Set oSignedData = Nothing
  Set oSigner = Nothing
  Set oSigningTimeAttr = Nothing
End Sub

Sub EnvelopeFile(ByVal sInFile As String, ByVal sOutFile As String)
  ' Open the MY store and retrieve the first certificate from the
  ' store. The signing operation will only work if this certificate is
  ' valid and has access to the signer's private key.
  Dim oCertStore As New Store
  ' Declare and initialize an EnvelopedData object
  Dim oEnvelopedData As New EnvelopedData
  oEnvelopedData.Content = ReadFile(sInFile)
  ' The signer's certificate is at index 1
  ' NOTE that you can add as many recipient certs as you like.
  oEnvelopedData.Recipients.Add oCertStore.Certificates.Item(1)
  Set oCertStore = Nothing
  ' Set the encryption algorithm and key length. Comment out
  ' or remove the following lines to use the default algorithm
  ' and key length. The triple DES algorithm and 128 bit key
  ' length may not be supported.
  oEnvelopedData.Algorithm.KeyLength = CAPICOM_ENCRYPTION_KEY_LENGTH_128_BITS

  'Declare the string that will hold the enveloped message.
  Dim sEnvelopedMessage As String

  'Encrypt the message into sEnvelopedMessage. The enveloped message
  'string contains everything that an intended recipient will need to
  'decrypt the message, including information on the encryption algorithm 'key length.
  sEnvelopedMessage = oEnvelopedData.Encrypt

  ' Release the EncryptedData object and the Store object.
  Set oEnvelopedData = Nothing

  ' Add the MIME headers to the content
  Dim sMimeHeader As String
  sMimeHeader = "MIME-Version: 1.0" + vbCrLf
  sMimeHeader = sMimeHeader + "Content-Disposition: attachment; filename=""smime.p7m""" + vbCrLf
  sMimeHeader = sMimeHeader + "Content-Type: application/x-pkcs7-mime; name=""smime.p7m""" + vbCrLf
  ' these last two line feeds are important
  sMimeHeader = sMimeHeader + "Content -Transfer - Encoding: base64" + vbCrLf + vbCrLf

  sEnvelopedMessage = sMimeHeader + sEnvelopedMessage

  WriteFile sOutFile, sEnvelopedMessage
End Sub

Sub WriteFile(ByVal sFileName As String, ByVal sText As String)
  Dim oFS, oTF As Object
  Set oFS = CreateObject("Scripting.FileSystemObject")
  Set oTF = oFS.OpenTextFile(sFileName, ForWriting, True, TristateFalse)
  oTF.Write (sText)
  Set oTF = Nothing
  Set oFS = Nothing
End Sub

Function ReadFile(ByVal sFileName As String) As String
  Dim oFS, oTF As Object
  Set oFS = CreateObject("Scripting.FileSystemObject")
  Set oTF = oFS.OpenTextFile(sFileName, ForReading, False, TristateFalse)
  ReadFile = oTF.ReadAll
  Set oTF = Nothing
  Set oFS = Nothing
End Function

Then to decrypt and verify the message you can use the OpenSSL command-line tools with the smime command.

This first command will take the envelope and decrypt it to find the signature (containing the plain-text content).

openssl smime -decrypt -in smime.txt -recip ..\cert.pem -inkey ..\privkey.pem -out signature.unicode.txt

Recall that the output from CAPICOM is always UNICODE so we need to translate the files back to ANSI before proceeding. I use a simple tool that I wrote to do this.

Unicode2AnsiConvert.exe signature.unicode.txt signature.txt

This second command will take the signature and verify it. If the signature is verified the tool will write “Verification successful” to the console. Please note that verification requires correct certificate resolution to be configured for the machine but this is necessary for security.

openssl smime -verify -in signature.txt -inform PEM -out message.unicode.txt

Finally, translate the message to ANSI.

Unicode2AnsiConvert.exe message.unicode.txt message.txt

The resulting message.txt file will contain the original message input into CAPICOM.

Posted at 4/13/2004 01:20:00 PM | (4) comments

The Man In The Arena 

Why can't we get a president that can speak like this again?


Posted at 4/13/2004 08:35:00 AM | (0) comments

DateTime formatting and best practices 


Posted at 4/13/2004 08:32:00 AM | (0) comments

Monday, April 12, 2004

Do I use Load, LoadFile, or LoadFrom? 

From Suzzanne Cook's blog:

Posted at 4/12/2004 05:38:00 PM |

Any given Monday? 

I was recently tasked with finding out the calendar date of of the first day of any week. I came up with the following code:

DateTime GetFirstDayOfWeekDate(DateTime reference, DateTimeFormatInfo dtfi)
   Calendar cal = dtfi.Calendar;
   DayOfWeek dow = cal.GetDayOfWeek(reference);
   DateTime firstDayOfWeek = dtReference.AddDays((((int)dtfi.FirstDayOfWeek - (int)dow) - 7) % 7);
   return firstDayOfWeek;

I have run it through a test that uses all 7 days as the first day of the week and calculates the date for 10,000 days. Upon spot checks of the results it seems to work. I have only tested it with the EN-us culture. I don't know how it works with other cultures.

Does anyone know of a different\better way or see any problems with this?

Posted at 4/12/2004 05:36:00 PM | (0) comments

Using SQL bigint in your applications 

You can use SQL bigint in your applications but be careful that you use the appropriate integer size in your code. For a quick reference see the following list:

SQL bigint = 9223372036854775808
XSD unsignedLong = 18446744073709551615
.NET ulong = 18446744073709551615

Posted at 4/12/2004 05:28:00 PM | (0) comments


Chris Brumme to the rescue again...


Posted at 4/12/2004 05:23:00 PM | (0) comments

Side-by-side execution in .NET 

Good overview of side-by-side execution.


Posted at 4/12/2004 05:22:00 PM | (0) comments

The XmlSerializer Generates Code At Runtime 

The XmlSerializer inspects your serialized type and generates code on the fly using the Code Document Object Model (CodeDom) to serialize and deserialize instances of it. Normally this code is deleted as soon as it is compiled into an assembly. To see the code generated by the compiler, you must add a switch to the machine.config (or web.config) file to keep compiler-generated files around. To do this, follow these steps:
Open the machine.config file in a text editor, such as Notepad.
Add an XmlSerialization.Compilation switch to the system.diagnostics section of the code, as follows:

   <add name="XmlSerialization.Compilation" value="4"/>

Run the client application that does XML Serialization.

Look in the %temp% directory for a recently created .cs file. There will be several others as well. Note: if this is a web app (i.e. web service) then look under %windir%\temp. The .cs file is the generated source. The .out file should have any compiler errors.

You should also be aware of the permissions needed to do this: http://support.microsoft.com/default.aspx?scid=kb;EN-US;823196

Posted at 4/12/2004 05:13:00 PM | (0) comments

.NET Garbage Collection of Unmanaged Objects 

Some very interesting articles on problems with the GC and unmanaged objects. They gave me some insight into proper handling of non-memory unmanaged resources (like handles) in .NET.

Lifetime, GC.KeepAlive, handle recycling
TSS.NET Article: Garbage Collection and Interoperability in .NET
GC.KeepAlive Method
Garbage Collection: Automatic Memory Management in the Microsoft .NET Framework
Garbage Collection—Part 2: Automatic Memory Management in the Microsoft .NET Framework

I found some interesting replies to one of the articles above. It so happens that some readers looked into some of the claims in this article further and found them left wanting. An "almost" heated discussion ensued over the conclusions that the author drew. In particular, one reader took issue with the claim that the object was not referenced and therefore needed the GC.KeepAlive call.

"The problem you experienced must be related to something else. I really don't understand how adding GC.KeepAlive(h) solved the problem..."

One of the follow-up postings contained a few more links to even more interesting articles on this topic. These are particularly relevent to those of us designing managed classes and even more so if those classes are wrapping unmanaged "things". One link includes a quiz and a reference to a tool called CLR SPY that can be used to help debug related problems.

// This code has a bug!
public static void Main ()
// Open the key for read-only access
RegistryKey key = Registry.LocalMachine.OpenSubKey(
Console.WriteLine("Install root: " +

I found the answers to the quiz very revealing.

"When the current instance gets collected as the PInvoke call to RegQueryValueEx is initiated, RegCloseKey ends up being called before the unmanaged implementation of RegQueryValueEx executes. By the time the RegQueryValueEx API processes the handle, the handle is invalid! This problem is easy to introduce in any managed classes that wrap unmanaged handles. Yet the time window for failure can be so small that it would usually take a really long time for you to discover the bug."

In particular, I found it interesting that part of the solution includes the correct use of the IDisposable pattern.

Posted at 4/12/2004 02:50:00 PM | (0) comments

Thursday, April 08, 2004

Choosing a home theater projector screen: Part 2 Aspect ratio 

The next big question I needed to ask myself is which format to choose from? 4:3 or 16:9? Again, I had many choices and in this case I found out that my choice was really dependent mostly on my personal preference. Projector Central has a great article to read about screen and projector formats and I can't say anything that they didn't. It was pretty much the only article that I read about this subject before making my decision and I highly recommend it.

Since I wanted to view mostly DVDs and am way too cheap for HDTV at this point, I chose the 4:3 format and I have been very happy with this choice. I can still view 16:9 or widescreen if I choose but I really prefer the look of 4:3 when I'm at home.

Posted at 4/08/2004 05:52:00 PM | (0) comments

Choosing a home theater projector screen: Part 1 Configuration and Material  

If you have been following my posts then you know that I am completely new to the world of home theater and therefore have and had a lot of learning to do. I sat down at my computer to figure out which screen I wanted to buy for my home theater. I had no idea....

Manual or electric, permantent tension or rolled, the list goes on. I spent two nights online doing research and then decided to go to some local stores to ask for help. As I found out with the projector earlier no one seems to know much about this stuff. Or maybe I just didn't ask the right people. At any rate I was determined to learn.

Once again, my choices were limited by my fictitious budget. That and the fact that no way am I so lazy that I cannot get off my *ss and pull the screen down myself. ;)

I also decided that I didn't want the screen to be permanently visable. My room is quite small already and having an entire wall with a huge white canvas covering it was probably not a good idea. Besides, permanently tensioned screens are considerably more money.

As usual, I started with a google search but quickly found myself at DaLite.com. At this site I found a wealth of knowledge on screens. I think they deserve a lot of credit for making it easier for people like me to get up-to-speed and understanding the technology. Good job, DaLite.

The one thing that was quickly becoming apparent to me though was that there are a lot of screens out there. However, DaLite offers a page that guides you through the process of finding a screen that's right for you. Well, to be more exact they guide you through finding a screen material. However, this turns out to be one of the most important criteria and probably the one that most people like me wouldn't have a clue about. It all has to do with something called the "gain" factor of the screen. Some materials can make the picture look brighter than others. To accomplish this they need to use certain materials like glass beads or polymers. These materials come at a price though and this mostly manifests itself in the viewing angle. For instance, if you have a high-gain screen you may not be able to place your audience at wide angles to the screen.

Why would you need a high-gain screen? Well, that depends upon a few of factors:

1. What is your projector's output in lumens?
2. How many square feet will your projected image be?
3. How much control do you have over ambient light conditions in your home theater?

Determining your foot-lumens is pretty simple. The lumens output should be obvious from your projector's documentation. For the X1, it's about 1100 max or about 700 after tuning for watching DVDs. The ambient light question should also be obvious after taking a quick review of your room. DaLite.com's helpful pages will guide you through this process nicely.

It turns out that since my theater is in my former garage and I have completely walled off the room from any windows I have complete control over the ambient light situation. It also turns out that my X1 setup was about 27 foot-lumens. This meant that I could go for a 1.0 gain screen. That's great because that meant I could buy the relatively inexpensive Matte White material for my screen.

So now that I've decided on Matte White and a manual pull-down screen I could narrow my choices of screens considerably. DaLite offers the Model C screen for a very reasonable price. They also offer most of their screens with something called Control Screen Return (CSR). I thought about getting this option for awhile but in the end I felt that I could trust myself to return the screen carefully and save my money for more important things.

Posted at 4/08/2004 02:20:00 PM | (0) comments

Choosing the right projector for your home theater  

I knew that one of the most expensive pieces was going to be the projector so that's where I started my research. As with almost every aspect that I'm going to cover on this topic my search always begins with google. How did we ever live without this tool folks? :)

I figured that there must be droves of information on creating your own home theater. I even thought that I would find the perfect website explaining everything I ever wanted to know and more. I was horribly wrong. In fact, it's one reason that I decided to sit down and create this blog to share my experience.

I started doing a lot of research on projectors to find out what the state of the technology was. I kind of knew what I wanted but also was afraid to find out what that was going to cost me. I looked at many projectors from Panasonic, InFocus, Sony, Dell, IBX, and Gateway. I probably looked at others as well but can't recall all of them now. To my surprise it really didn't take me that long to decide on the InFocus X1. It was receiving great reviews and made the top 10 list in it's price range.

Since I was looking for a projector primarily for playing DVDs, the X1 had exactly what I needed and for about 1/2 the price of the competitors. The following reviews will give you the skinny on the X1.

InFocus X1 Reviews:

I found the X1 online for $915 at www.onlinemicro.com. Last I looked it was even cheaper. :L

I got the projector about a week later and hooked it up immediately to my DVD player. I watched The Matrix: Reloaded on my dining room wall complete with shadows from the chandelier and a vase on the table. It was pure ecstasy.

Posted at 4/08/2004 11:40:00 AM | (1) comments

Creating a home theater on a budget  

About two years ago I bought a house in SE Portland. I started doing some home improvement shortly thereafter. I had a nice 3-car (stacked) garage under the house and the layout was perfect for turning the one space into an entertainment room. I started by partitioning the space with a wall (and door) and things were moving along nicely. Then I hit the home improvement equivalent of writers block. That and the fact that I was un-motivated at the time. To make the story short and to keep things interesting I'll fast-forward to about 6-months ago.

I made a decision to start working on it again and made some choices about what I wanted to do. For better or worse. :)

I decided to create a home theater. I knew that this would be expensive but I figured that since I would be doing most of the work I could offset some of my costs for the equipment and still come in under my "flexible", okay let's say non-existent budget.

To get the project re-started I drafted up blue-prints of the room (including wiring diagrams) and hired an electrician to re-configure my main electrical box and run heavy-guage wire to a sub-panel in the new room. I am handy with most things required for this project but this part made me a little nervous. Needless to say I was extremely happy with his work and it gave me the exact kick in the pants that I needed to get inspired.

In subsequent posts on this topic I will talk about what I learned while doing this project and try to share some of my experience in the hope that it helps somebody.

Posted at 4/08/2004 10:34:00 AM | (0) comments

This page is powered by Blogger. Isn't yours?