/dev/trouble
Eric Roller's Development Blog

Trying to update Xcode 4.0.1 from within the Mac AppStore application, I was greeted with this error message:

You have updates available for other accounts Sign in to (null) to update applications for that account.

There exist numerous forum entries on Apple's discussion board on that subject and the recommended solution is to trash the "Install Xcode" application and then to re-launch the AppStore, selecting to re-install Xcode.

I trashed "Install Xcode" but AppStore produced the same message. Relaunched one additional time and it allowed me to update (note: not install). However, when it was finished, there was no new "Install Xcode" in the Applications folder!

It turns out, the AppStore had located and updated a different copy of the software on a separate drive where I had made a backup, even though I had renamed it to "Install Xcode-4.0.1". Its info window revealed that it had been modified and that its version number now was 4.0.2.

Installation from that modified backup worked correctly.

The old backup could be restored from the version that I had put into the trash.

Compiling an application for the MacOX10.4u SDK (with Xcode 3.2.4, GCC 4.2.1) results in this linker warning:

ld: warning: object file compiled with -mlong-branch which is no longer needed. To remove this warning, recompile without -mlong-branch: /Developer/SDKs/MacOSX10.4u.sdk/usr/lib/crt1.o

This is not a critical issue and can be ignored. However, it can also be fixed as shown by an answer from Bernhard Baehr on lists.apple.com:

What needs to be done is to recompile the Csu package which can be found on Apple's opensource archive, e.g. the one for 10.4.11 x86 where the -mlong_branch flag has already been removed: http://www.opensource.apple.com/release/mac-os-x-10411x86 http://www.opensource.apple.com/tarballs/Csu/Csu-71.tar.gz

Then it's just a question of recompiling it:

cd ~/Downloads
tar zxvf Csu-71.tar.gz
cd Csu-71
make RC_ARCHS="ppc ppc64 i386 x86_64"

Then we can replace the (stripped) object file in the SDK:

cd /Developer/SDKs/MacOSX10.4u.sdk/usr/lib/
sudo mv crt1.o{,.org}
sudo strip -S ~/Downloads/Csu-71/crt1.o -o crt1.o
sudo chmod 644 crt1.o

Google Search Tips

- Posted in General by

Added this blog post to get that piece of scrap paper off my desk and also to remember these tips by means of typing them in.

apples oranges Search for pages with both apples and oranges.

apples OR oranges -worms Either or, not others.

"candied apples" Exact phrase.

+fruit filetype:ppt Only the exact word, in PowerPoint presentations.

~fruit site:meals.com Include synonyms, but only on that site.

define:egoism Search after definitions.

BMW 318...328 Search for ranges, e.g. not the bad 316 model.

link:macworld.com Search after sites linking to macworld.com.

info:www.apple.com/se Show information about apple.se.

related:cdon.com Search for similar sites.

**mac*** All words beginning with mac, e.g. macworld, macintosh.

ARN BSL Search for routes between airports.

Harry Potter For books with harry potter, select the book icon.

stocks:AAPL Stock information.

weather Stockholm Search for weather information.

time Cupertino Get the current time for other places.

sunrise Kuusamo Get the sunrise times, try also "sunset".

5*9+(sqrt 10)^3= Evaluate calculations.

10.5 cm in inches Unit conversions.

66 GBP in EUR Currency conversions.

**Shakespeare wrote *** Let Google fill in the blanks.

P.S. Of course, Google has its own help page on this topic.

We can use iTunes to play music while we do circuit training, i.e. 40 seconds music while we work out, and 15 seconds pause while we rest or go to the next station:

  • save the following AppleScript in ~/Library/iTunes/Scripts; you will probably have to create the Scripts directory;
  • open iTunes with a suitable playlist; we recommend a good song and a Genius playlist;
  • select the first song;
  • launch the script from Scripts menu.

NB. This is an updated version of a previous script.

(* AppleScript for circuit training with iTunes.
The default circuits are 40 seconds each, with pauses of 15 seconds.
At the beginning, the script allows you to set different times.
After every second set, iTunes is asked to go to the middle section
of the next song.

version 2.1, ©2010, Eric Roller
*)

property wCount : 40
property tWork : 40
property tRest : 20
property tFudge : 1.0 -- use this to adjust the rest times

on run
    -- begin by asking for the workout and delay times
    set wCount to askUser("Number of Workouts", wCount)
    set tWork to askUser("Workout Time in Seconds", tWork)
    set tRest to askUser("Rest Time in Seconds", tRest)
   
    -- whether to skip to the next song, but only every other time
    set skip to false
    set remaining to wCount
   
    try
        with timeout of 6000 seconds
            -- enter the workout loop
            repeat while (remaining > 0)
                announceCount(remaining, wCount)
                -- wait, play the music, wait and then stop it again
                sleepFor(tRest, "Rest")
                tell application "iTunes" to play
                sleepFor(tWork, "Workout")
                tell application "iTunes" to pause

                if skip is true then
                    -- every other time, change the track
                    tell application "iTunes" to next track

                    -- skip to the middle section of the next track
                    set tForward to trackSeconds() / 2 - tWork
                    tell application "iTunes" to ¬
                        set the player position to tForward
                end if
                set skip to not skip
                set remaining to remaining - 1
            end repeat
        end timeout
    on error errText number errNum
        if errNum is not -128 then ¬
            display dialog "Error: " & errNum & return & errText
    end try
   
    -- finish by pausing iTunes
    tell application "iTunes" to stop

    -- work out how many iterations we did
    set remaining to wCount - remaining
    if remaining is greater than 0 then ¬
        say "Well done! You completed " & (remaining as text) ¬
        & " workouts."
end run

-- small helper to ask the user for an integer
on askUser(aText, aDefault)
    set anInt to the text returned of ¬
        (display dialog "Set the " & aText default answer aDefault)
    return (anInt as integer)
end askUser

-- helper to announce how many more workouts there are
on announceCount(aCount, maxCount)
    if aCount = maxCount then
        set message to "Starting " & (aCount as text) & " workouts."
    else if aCount = 1 then
        set message to "Last one."
    else if ((2 * aCount) as integer = maxCount) then
        set message to "Half time."
    else if (random number from -1.0 to 1.0) > 0.0 then
        set message to (aCount as text) & " more"
    else
        set message to (aCount as text) & " to go"
    end if
    delay (tFudge / 2)
    say message without waiting until completion
end announceCount

-- helper to wait for a given amount of seconds
on sleepFor(tDelay, workType)
    set tOut to tDelay
    -- apply a fudge factor for the rest times
    if workType is "Rest" then set tOut to tDelay - tFudge
    -- we use a dialog message with a delay
    set answer to display dialog (tDelay as text) & " Seconds " ¬
        & workType buttons "Stop" with title "Circuits Loop"  ¬
        giving up after tOut
    -- trigger an error if we want to stop
    if the button returned of the answer is "Stop" then ¬
        error "User canceled." number -128
end sleepFor

-- helper to determing the length of the current track in seconds
on trackSeconds()
    -- ask iTunes for the track length (MM:SS)
    tell application "iTunes" to get the time of the current track
    set the tLength to the result

    -- split the length into minutes and seconds
    set saveDeli to AppleScript's text item delimiters
    set AppleScript's text item delimiters to {":"}
    set tMinutes to the first text item of the tLength
    set tSeconds to the last text item of the tLength
    set AppleScript's text item delimiters to saveDeli

    -- add up the total length in seconds
    return (tSeconds + 60 * tMinutes)
end trackSeconds

Symptoms: When 'mounting' the external disk, shared over the AirPort Extreme WiFi network, it is not added to the Finder's sidebar; instead, you get an error like this:

The alias can't be opened because the original item can't be found.

Also, dragging the disk icon from the SHARED section in Finder's sidebar to the DEVICES section is not possibe; the Finder just displays a "can't drop it here" icon.

Searching online, I found a discussion on Apple's forums which contained the solution.

Fixing permissions with Disk Utility was not an option since a network-shared disk is not accessible within the app.

Apparently, the disk acquired an "alias" attribute by mistake. This can be checked in the Terminal, where the alias attribute is the capital 'A':

% /usr/bin/GetFileInfo /Volumes/AirDisk
directory: "/Volumes/AirDisk"
attributes: Avbstclinmedz

You can use the following command to turn the alias attribute off (then check again with the above GetFileInfo command and look for a lowercase 'a'):

% /usr/bin/SetFile -a a /Volumes/AirDisk

After that, the mounting problem disappeared.

One sign to check whether the monthly scripts have been executed is to look at the log file in /var/log/monthly.out. If that file were missing of if it did not show results from regular monthly runs, then here's why:

The default setup is to execute the scripts on the first of every month at 5.30 a.m. To change that on Mac OS X, you will want to modify this file: /System/Library/LaunchDaemons/com.apple.periodic-monthly.plist

[Update: If the plist uses Interval and GracePeriod then don't change it; it is already solved].

This blocking effort appears to have started in the Windows world but it is applicable to all UNIX-based systems where a hosts file is used.

Basically, copy the contents of this example hosts file to the end of your /etc/hosts file (requires root access).

[more]

In /etc/hosts, make sure not to remove the pre-defined settings, but you may comment out the duplicate "127.0.0.1 localhost" line. It should look similar to this:

##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1       localhost
255.255.255.255 broadcasthost
::1             localhost
fe80::1%lo0     localhost

# Custom entries (not shown)


# This MVPS HOSTS file is a free download from:            #
# http://www.mvps.org/winhelp2002/                         #
#                                                          #
# Notes: the browser does not read this "#" symbol         #
# You can create your own notes, after the # symbol        #
# This *must* be the first line: 127.0.0.1     localhost   #
# *********************************************************#
# ---------------- Updated: Sept-02-2009 ------------------#
# *********************************************************#
#                                                          #
# Entries with comments are all searchable via Google.     #
#                                                          #
# Disclaimer: this file is free to use for personal use    #
# only. Furthermore it is NOT permitted to copy any of the #
# contents or host on any other site without permission or #
# meeting the full criteria of the below license terms.    #
#                                                          #
# This work is licensed under the Creative Commons         #
# Attribution-NonCommercial-ShareAlike License.            #
# http://creativecommons.org/licenses/by-nc-sa/3.0/        #

##DUPLICATE:
##127.0.0.1  localhost

#start of lines added by WinHelp2002
# [Misc A - Z]
127.0.0.1  fr.a2dfp.net
127.0.0.1  m.fr.a2dfp.net
127.0.0.1  ad.a8.net
[...]

Finally, remember to check the example hosts file for updates; it is updated quite frequently.

To automate this process, I have created this script. You would need to execute it with "sudo" (or it could be placed into /etc/periodic/monthly ?).

#!/bin/sh
# File: 900.host_db_update

echo "Started /etc/hosts update"

# Download the current version without progress info:
curl -so /tmp/hosts.zip https://winhelp2002.mvps.org/hosts.zip

if [[ -s /tmp/hosts.zip ]]; then
    # Unzip quietly and convert CRLF -> LF
    unzip -aoqq -d /tmp /tmp/hosts.zip HOSTS
    rm /tmp/hosts.zip
fi

if [[ ! -fs /tmp/HOSTS ]]; then
    echo "Error: Download of hosts file failed."
    rm -f /tmp/HOSTS
    exit 1
fi

tmpdate=$(grep -m 1 Updated: /tmp/HOSTS|awk '{print $4}')
etcdate=$(grep -m 1 Updated: /etc/hosts|awk '{print $4}')

if [[ "$tmpdate" == "$etcdate" ]]; then
    echo "Info: Hosts file is already up-to-date ($etcdate)"
    rm -f /tmp/HOSTS
    exit 0
fi

# Remove the previous MVPS additions from /etc/hosts
sed '/^# This MVPS HOSTS/,$ d' /etc/hosts > /tmp/hosts.new

# Append the new settings
sed '/^[^#].* localhost$/ s/^/##/' /tmp/HOSTS >> /tmp/hosts.new
rm /tmp/HOSTS

# Make a backup and move the new file:
cp /etc/hosts{,~}
mv /tmp/hosts.new /etc/hosts

# Print a message:
echo "Updated /etc/hosts with settings from $tmpdate"
exit 0

Essential Mac Applications

- Posted in General by

When installing Snow Leopard, it occurred to me that there are a number of applications that I like and that I (almost) always use. They are, in alphabetical order:

Calico ($59 keskus.com)

An easy to use tool to stitch together multiple photos into panoramas.

Camino (open source, caminobrowser.org)

While I use Safari almost throughout, my bank is the only one that is deliberately refusing to support it. Firefox is good a good browser, but for my purposes it is too big. Camino, being specifically for the Mac, is just what I need for my bank.

Chicken of the VNC (open source, sourceforge.net)

A simple VNC client.

Cyberduck (donateware, cyberduck.ch)

An FTP client will all the bells and whistles to keep you happy (for those cases where "Conntect To Server" in the Finder is not sufficient to your needs).

DrawBerry (donateware, raphaelbost.free.fr)

A simple graphics app.

Fission ($32 rogueamoeba.com)

An easy to use audio editor with a nice waveform viewer (where Garageband is just overkill).

GraphicConverter ($35, lemkesoft.com)

I still use version 5.9.2 since it works fine for my needs.

HexEdit (open source, sourceforge.net)

For those rare cases where you like to dig in and see the guts of a file. Unless you are Japanese, you should stay away from the Japanese "J" version (look under Files for the one without the "J").

iLife ($79 or free with every new Mac, apple.com)

I mainly use iPhoto and iWeb. Most recently, I opted out of installing iMovie and GarageBand since I simply never use them.

iVolume ($30, mani.de)

Analyses and adjusts the loudness of your songs in iTunes.

iWork ($79, apple.com)

I mostly use Pages, but have also discovered that Keynote can be used as a vector-based drawing tool. The only problem is that every new major version cost again $79, which is why I feel inclined to skip one or two versions before upgrading.

Pixelmator ($59, pixelmator.com)

A photo editor. Not quite yet on the same level as Photoshop, but much more affordable and it keeps getting better and better.

TextWrangler (freeware, barebones.com)

Not quite willing to pay for the infamous BBEdit, I find that TextWrangler is an excellent alternative. I particularly like the graphical "diff" tool and that you can launch it from the Terminal (via custom edit and twdiff commands)

Tunnelblick (open source, code.google.com/p/tunnelblick/)

An OpenVPN client for the Mac. Only useful if you use OpenVPN.

An old trap that I keep to be falling into is this one:

> find . -name "Frameworks" -prune -or -name "Info.plist"
./Frameworks
./Info.plist

Notice how the Frameworks folder is also returned (since -prune defaults to true), but the intention was to exclude it! The solution is to add -print:

> find . -name "Frameworks" -prune -or -name "Info.plist" -print
./Info.plist

On Mac OS X 10.5 (Leopard) it appears to work fine, but when I quit my app, on a machine running 10.4 (Tiger), these messages appear in the Console:

2009-03-03 21:49:10.680 MyApp[6793] *** Illegal NSTableView data source
    (). Must implement numberOfRowsInTableView: and
    tableView:objectValueForTableColumn:row:
2009-03-03 21:49:23.139 MyApp[6793] *** -[NSCFString count]:
    selector not recognized [self = 0x1bc7f00]
2009-03-03 21:49:23.140 MyApp[6793] Exception raised during posting
    of notification.  Ignored.  exception: *** -[NSCFString count]:
    selector not recognized [self = 0x1bc7f00]

The interesting fact is that the MyApp class is the delegate of the NSTableView since it implements support for drag & drop. However, it is not designed to be the data source for the NSTableView. Instead, I use an NSArrayController through a binding in the NSTableView instance. This works fine until one quits.

What I suspect is happening (on Tiger) is that the NSArrayController is purged before the NSApp, which suddely remains as the only data source of the NSTableView, but without the access methods implemented.

The solution would be to implement dummy methods in the MyApp class for numberOfRowsInTableView: and tableView:objectValueForTableColumn:row: where one returns 0 and nil, respectively.