Monday, June 15, 2009

Replacing a 1st Gen iPod Nano headphone jack

A few years back, I was lucky enough to win an iPod Nano from the Clock Tower Law Group (because I returned a data sheet at the right time). It was pretty cutting-edge at the time and I really enjoyed listening to podcasts on a variety of subjects during morning runs. For about three months. At that point, it was "borrowed" by kit and kin and I've barely used it since. C'est la vie.

My wife, who is studying voice, relied upon the iPod heavily. She listened to music she was studying, new songs, recordings of her voice lessons, and warm-up routines. She would use the iPod to get her voice work in where ever possible; no small challenge while raising five children. So, when the iPod stopped working reliably, she was at a loss.

The symptoms were that the sound was not coming reliably through both headphone ear buds. I tried swapping headphones, listening to different music and as many other diagnostic comparisons as I could manage. I wish I knew how to put the iPod into diagnostic mode then. (Press and hold the center Activate button + the Menu button until the phone reboots. Then move your finger from the Menu button to the Left Arrow button and press and hold the Activate and Left Arrow button until the diagnostic menu appears. Press Activate + Menu to reboot when done).

Nonetheless, I determined that the headphone jack was defective. I despaired at the thought of trying to pry open the iPod and replace the headphone jack, but since the darn thing didn't work anyway, what did I have to loose?

I googled around for a 1st Generation iPod Nano headphone jack and purchased one for $6 from Binh An at bureenz@gmail.com through eBay. He was very helpful even when I initially purchased the wrong generation headphone jack. I also picked up a replacement battery since I knew I would have the unit open. Mr. Binh included an iPod tool for opening the unit at no cost.

I followed the directions at www.ifixit.com to open the unit and remove the motherboard. The headphone jack is held to the motherboard by a screw and there is a small nipple under the motherboard that fits into a hole in the headphone jack unit. I used a pencil tip on my soldering iron and removed the old headphone jack. I then stripped off as much old solder as possible with some solder braid and cleaned up the entire area by scraping away the solder paste that appeared.

Finally, I put the new headphone jack in place and carefully soldered the four leads to the motherboard. Keep your soldering iron hot and touch the tip to the leads one at a time. Wait a moment before moving to the next lead to let the board cool down.

Then I replaced the battery -- very straight forward compared to soldering the leads of the headphone jack. I used a tiny drop of cryanoacrylate to re-attach the grounding strap before closing up the unit. Make sure the ground strap runs from the headphone jack screw to the back plate.

Check that the little tabs on the metal back plate are all in the proper position before closing up the unit. They're easy to bend when opening the unit.

I charged up the battery and ran the unit through the diagnostics. Everything works perfectly and my wife has her iPod back for less than $20 in materials.

Tuesday, June 09, 2009

Supressing Object#id deprecation warnings

I picked up some Ruby on Rails code up which I was working a few months ago to complete the project. While adding and running my rspec tests, I started getting the following warning during test execution:

"Object#id will be deprecated; use Object#object_id"

The warning was coming from the super_inplace_controls plug in that I was using. I really like these controls, and wanted to clean up the warning.

So, I popped open vendor/plugins/super_inplace_controls/lib/super_inplace_controls.rb and checked out line 234, from which one of the warning was eminating.

Sure enough, there was, in the method id_string_for, the line:

"#{object_name}_#{method_name}_#{object.id}"

No problems, I'll just change "object.id" to "object.object_id". I did this here and on line 260 in the form_for_inplace_display method.

Of course, this broke the code and the in-place object no longer received its updates after changing a value. The ID part was necessary to retrieve the updated record and display the correct value after update. So I backed out my changes.

Some more searching and I came across a way to suppress warnings around a small block of code, which is exactly what I wanted. I didn't want to suppress all warnings, but I knew that the object.id had to be there (truth be told, I should have tried using just "object"); I just didn't want to hear about it.

To suppress the warning, I wrapped the offending line in Kernel::silence_warnings() {}. So the id_string_for method become:

def id_string_for(object_name, method_name, object)
     Kernel::silence_warnings {
        "#{object_name}_#{method_name}_#{object.id}"
    {
end

I tried the same thing for the form_for_inplace_display method and ended up putting the whole method into the silence_warnings block due to the scoping problems the block introduced.

The danger to this whole method is that, should this code base advance into a new version of Ruby or Rails where the object.id call causes an error, code that seems to work will suddenly break. On the plus side, this won't be a complex logic bomb to solve, but should come up right away in a standard testing cycle.