Dali Clock

OSX Dali Clock is just about done... try it out and let me know?

All the preferences work, and I think it doesn't leak. I'm not sure how good it is about CPU usage.

The application icon is kinda crappy. Someone make me a nicer one!

I played around with making it use CGContextClipToMask to draw a 1bpp bitmap instead of using NSImage-drawInRect, but I couldn't see how to do that and have transparency still work. I'm also not sure it would make that much of a difference anyway; any informed opinions? (It's in DaliClockView-drawRect).

Tags: , , ,

31 Responses:

  1. badger says:

    All the prefs work that I checked. Using about 24-25% CPU according to top, 800 MHz G4 Powerbook, 512MB RAM, OS X 10.4.3.

  2. how about fullscreen mode and anti-aliased text?

    • jwz says:

      Do you mean something by "full screen" other than "the maximize button"? What would you use that for? A screensaver version would be nice, though.

      Currently the largest font bitmap it operates on is 256 pixels tall; I have larger ones, but they kill performance (it's not just running a slideshow, it has to do some computation on each scanline). Any scaling beyond that is done by the OS. Maybe there's a way to smooth out the bitmap a bit more at the graphics card level, but I don't know it.

  3. rob_from_ca says:

    Running about 20 minutes, played with preferences a bit, memory size seems about constant (@19MB resident). CPU usage ~ 6.7% (Dual 1.8 G5)

  4. bodyfour says:

    Yeah, CPU usage seems a little high. I guess it's constantly redrawing everything just to make the color-shifting effect, huh? Even in hour:minute mode and the cycle speed turned to minimum it seems to munch about 20% of a 2GHz G5 CPU when filling one of my screens.

    Also in "float on top" mode it should probably still stay behind its Preferences and About windows.

    • jwz says:

      I used to have an optimization in there that would make it mostly idle in that case (don't try to animate a digit when the source and target digits are the same) but there's a weird margin case that makes that sometimes not safe; sometimes you'd get left with a digit stuck halfway between "3" and "4" if there was a load spike before it finished (it would bail on the animation, but not realize it). I'll see if I can put that back.

      • bodyfour says:

        Shouldn't be more than adding a per-digit is_in_the_middle_of_animating flag, right?

        • jwz says:

          You'd think so, but I'm finding it a real pain in the ass to make it work...

        • jwz says:

          I got that optimization working, but I shouldn't have bothered; according to Shark, it's spending 75% of its time down in CoreGraphics. I need to get those bits on the screen faster.

          • bodyfour says:

            Well it's got to at least help the case of "no color cycling; hours:minutes only" There it's chewing CPU while displaying a static window for 60 seconds.

  5. felicks says:

    Huh, I'm running 10.3 and it crashes.

    • jwz says:

      That'd be the part where I said "I don't think it will work on 10.3."

      10.3 doesn't have the NSDatePicker widget, and 10.2 doesn't have Bindings (which is how all the preferences work.)

  6. duskwuff says:

    There are some fine leak-checking tools in your /Developer folder. Particularly handy are MallocDebug and ObjectAlloc.

    Shark is also nifty for performance profiling, if that's your thing.

  7. pnendick says:

    My new, magical, floating clock is using 116.82 MB virtual memory, 16.94 MB real mem and 36.30% of my 800MHz G3's attentions. Will modern marvels never cease?

    Homerpalooza Teen1: Oh, here comes that cannonball guy. He's cool.
    Homerpalooza Teen2: Are you being sarcastic, dude?
    Homerpalooza Teen1: I don't even know anymore.

  8. edouardp says:

    As the sign says, "Do not ask for features, as refusal often offends".

    Still, here's my observations and requests.

    1/ The Icon. It *is* kinda crappy, but on the other hand it's a very honest representation of what the user is going to get. I was thinking about trying to photoshop out an actual clock from the Dali painting, and turning that into an Icon, but it struck me that that would be like those Atari 2600 games I got as a kid where the picture on the box was exciting and cool, whereas the game was really a bunch of blocks moving around.

    2/ Startup. Seems to take quite a while to startup, and while it's doing it the user gets a window with some default colours/transparency, and a couple of dots. Just don't display anything until it's all ready to go and/or speed up the startup. Also. I noticed that the first frame on of actual numbers is the wrong width.

    3/ Anti-aliasing. Yes please. Draw offscreen at 1bpp but 2x or 4x the target resolution and then downsample to 32bit for display? How did you originally generate the bitmaps (when was that - I remember DaliClock in the 80s?) - is it possible to get vector data for them? That would probably reduce the memory footprint (and probably startup time to load in the number data).

    4/ Full Transparency. Makes the resize widget very hard to grab. Is there a better way to resize the clock? Perhaps a slider in a floating window - maybe a right click brings up a pop-up slider like the volume control one that you can get in the menubar? Something like http://www.edouard.info/dali.jpg on a right click?

    5/ Titlebar. Kind of ruins the appearance when you've got the background fully transparent. How about an option to turn it off? You don't need the title bar since you can move the clock around by the content, and if you take suggestion 4 above on board, then the resize widget is also redundant. Then you just have a floating clock, and that's cool.

    6/ Menu Items. You can get rid of most of them. But I'm not a Mac OS X programmer (that job starts next week), so perhaps they are "for free" when you create an app?

    That's all for now.

    • jwz says:

      I think a Dali-painting clock for the icon would be great!

      It's already drawing the fonts at 2x size or more and letting the hardware scale the bitmap down. Getting vector fonts wouldn't help, because the algorithm is raster-based, and while performance is ok with a 256-point font, a 512-point or higher font kills the frame rate. So, I think that's as anti-aliased as it can get.

      I'd like to have an option to turn off the title bar, but I don't know how...

      All those menu items came for free. I don't know how to turn them off, or even if that's considered a reasonable thing to do...

      • duskwuff says:

        Making the title bar disappear requires that you generate the NSWindow yourself, and pass it some extra flags. Check out Apple's RoundTransparentWindow code for an example.

        To get rid of extra menu items, edit the MainMenu.nib (within English.lproj - it's a localized file) and kill everything you don't want. Make sure to hold on to at least an Edit menu (for text editing), a stub File menu (close window, especially), and the Windows menu, or people will get angry because important keystrokes (Cmd-C, Cmd-W, Cmd-M) don't work.

      • edouardp says:

        Best I can do is:


        Unfortunately all i could find was a very crappy source image (http://www.postare.it/user/39972/dali.jpg) and there's not a lot you can do with bad input data (as I know from when I worked in pre-press).

        I'd prefer it to have a "Aqua" table edge to hang over - one of those blue glass material things with the specular highlight from the overhead bank light, and the special Apple "inner glow". But it's been far too long since I could do those...

        Also - the PNG looks fine, but when you add the ICNS to the App, the right hand pixels get messed with - which screws up my alpha mask. Do a "Get Info" on both files, and you'll see what I mean. It's not the on-disk pixels, it's something to do with the icon display code. Weird.

        • edouardp says:

          Remember though:

          You wouldn't steal a car.
          You wouldn't steal a handbag.
          You wouldn't steal a television.
          You wouldn't steal a DVD.
          Downloading dead artists paintings is stealing.
          Stealing is against the law.

          Stop internet piracy now.

          • waider says:

            Curse you, now I really REALLY want to rip the music from that "advert" and fling it on the intarweb. Oh the delicious irony.

        • jwz says:

          Thanks for the icon, looks great!

      • rexpop says:

        Turning off the title bar is really easy. What you need to do is:

        1. In Interface Builder create a subclass of NSWindow. Call it DaliClockWindow or something like that.
        2. Get Interface Builder to create the .h and .m files.
        3. On the instances palette of select the Window instance. On the floating inspector select the ''Custom Class" Panel. Change the class of the instance to the one you created in (1).
        4. Open the .m file you created in (2) and add the following block:

        - (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag
        self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
        [self setMovableByWindowBackground:YES];

        return self;

        Basically the styleMask controls how the window will be rendered. NSBorderlessWindowMask displays the window without a titlebar.

        I think you can also do this with a delegate rather than having to subclass, but if you have further initialization code then this makes it look cleaner.

        • jwz says:

          Do you know if there's a way to turn the title bar on/off without recreating the window? I'd like to make it be a checkbox in preferences...

          • rexpop says:

            Nope. According to the NSWindow documentation, once its set you can't change it without recreating the window. In this case its probably easier to close the old window and recreate the window with or without the border.

  9. wootest says:

    Some suggestions for stuff you might want to do in the near future:

    Upgrade to Xcode 2.2 - it's in Apple's Developer Tools section on developer.apple.com. Xcode 2.1+ will let you build binaries that work with the current PowerPC Macs and the new Intel Macs that will come out any minute now. Xcode 2.1+ has a new file format - .xcodeproj - which sadly isn't backwards-compatible, and in fact everyone on Xcode 2.1+ has to upgrade a copy of the project file first thing they do when they open the old project.

    Update the Makefile to actually also build the project when possible (when on OS X). Xcode has a wonderful command-line tool called `xcodebuild` that can be used to automatically build a target - give the man page a read.

    What's the deal with this: char *progname = "Dali Clock"; /* #### where should this go? */
    in DaliClockView.m? If you're trying to change the name of the executable - change all these places:

    * CFBundleExecutable in Info.plist ("Which executable should I launch for this app?")
    * CFBundleName in InfoPlist.strings ("Which name should I show for this app in the file system?")
    * The Build Setting "Product Name" in the DaliClock "target" (double click it in the list) ("Which name should the executable I produce have?" - same as CFBundleExecutable above)

    • wootest says:

      Also, "how to turn off the menu items": Open MainMenu.nib in Interface Builder. Double click the MainMenu menu object in the small document window where you find all your windows and classes. Click the menus to fold them down, and select menu items and hit delete to actually remove them. (To add new menu items, drag them in from the Menu tab of the controls palette.)

      In Cocoa you mostly don't have to wire up the interface in pure code - the nib file itself is made up of freeze-dried objects that are instantiated when the nib is loaded. So if you want to change or get rid of something, just make the change in the nib first, if possible.

    • jwz says:
        What's the deal with this: char *progname = "Dali Clock";

      I'm in the habit of my various modules expecting a global variable 'progname' that they prefix all their fprintfs with, so that I don't have to wonder which program the logs came from (this can especially be a hassle with xscreensaver, which has hundreds of executables that all share code...) I realize this doesn't really fit into the Brave New Mac World at all, but hey, I got a link error, so whatever...

      • wootest says:

        NSLog(), the console debug/log facility, automatically prepends the executable name to the message, but this is probably not what you had in mind for printing your own logs - and especially not with xscreensaver.

        • bodyfour says:

          Or if you don't mind using non-standard stuff you can just do:

          extern char *__progname;

          to get the executable name. Not standard, but I think should work with most *NIX based things. (I'm sure it's good on anything linux or BSD based; too lazy to check SYSV right now) It's what syslog(3) uses. It gets set by crt0.o before main() is called.