<<
 
>>
 
 
justin = {main feed , music , code , askjf , pubkey };
 
mac porting...
December 9, 2006

In August I began cleaning up REAPER's source code, and began separating the platform-specific code (mostly UI) from the mostly-portable code. Ten days ago, after 3 months of doing that while also adding new features and releasing new Windows versions every few days, I began spending a great deal of time actually writing a bunch of Cocoa code so that we could have it run on OS X.

It has gone very well, expect some preview version around Christmas.

I love it when this stuff goes faster than I had expected. I'm going to detail some of my experiences here.

There's a lot to like about programming on OS X, but there's also plenty of idiocy.

CAUTION-Boring programming discussion follows. These are mostly things that I have sort of, but not completely correctly, working.

For example, if you wish to draw text, there are countless ways to do it, and at least for what I wanted to do (emulate DrawText for our GDI emulation layer), I still haven't found a way that works as I want. The first way I tried was using CGContextShowText, which worked, except the only way I could find to measure the text before, or after drawing it didn't seem to work (using CGContextSetTextDrawingMode with kCGTextClip to modify the clip path, then get the bounding rectangle of that). So without any way to measure the rendered text, I had to find another way. I could use NSAttributedString to draw, but the first problem is that I wanted to supprot drawing to an arbitrary CGContext, which may or may not be the "active" context. Then, suggested to me, was to use Carbon's HIThemeDrawTextBox etc, which isn't really documented at all (other than in the header file and some examples). HIThemeDrawTextBox works, except the font I selected using CGContextSelectFont isn't used. It appears I could use some other API to set the font, but I havent spent that much time on that. Why can't there just a be a simple, working way?! At least win32's DrawText just works (though I hear the internals are a nightmare).

OK I won't go too much more into those sort of things. The good things are some things are just easier. Anytime you want to modify the behavior of something, it's WAY easier, since you can do a simple objective C subclass, rather than having to do the tricky hacks we do in Windows. Porting the customizable keyboard code to OS X took an hour or so. Getting it to work originally on Windows took many times that.

Rendering with Quartz just looks nice, too. The plain Windows GDI calls just look harsh and cruddy in comparison.

Here's an interesting challenge: on Windows, REAPER renders its play cursor (the line that moves constantly with playback) by using XOR drawing. It renders it by flipping all of the bits in the line, then when it needs to erase the cursor (in order to draw it in the new position), it can just XOR again. Win32 makes this available by using DrawFocusRect(). Anyway, on OS X this isn't possible, to my knowledge, because the system handles so much of the drawing process. I didn't want to be responsible for updating any of our track view at 30fps+, so I had to come up with another solution. After some experimentation, I found that you could create a new NSWindow, make it a child of the main window, and move it around as the play cursor. And it works, the system handles redrawing the track view, from its cached rendered version, so it's FAST, probably hardware accelerated, and you can do neat things with the alpha channel of the cursor. The verdict: while you can't do oldschool things like XOR drawing, you can do things sexier.

So to aid porting, I've created a new part of WDL (our general reusable code library, pronounced "whittle"), called SWELL (Small Windows Emulation Layer Library or something). So far it emulates (at an API level), portions of the Windows GDI, menu API, MessageBox, ini file (GetPrivateProfileString etc), and a bit more. Eventually we'll probably BSD license SWELL, too.

One interesting thing in SWELL is a set of macros and small functions that let us paste in menu definitions from a .rc into a C++ source file and have it generate a HMENU for it. Fun use of the C preprocessor, if you ask me.

Anyway, this is all challenging, and as a result, mostly fun.

programming style and process
December 9, 2006

I previously said I was planning on writing an article on coding style etc, and while I haven't gotten around to finishing it, I'll go ahead and discuss some of it.

1) If you program, and you're working on something that you expect to be working on for more than a couple hours, use version control. The benefits are countless. Safety, yes, but also, it gives you the ability to easily see everything you've done (if you're religious about checking your code in often), and even more importantly (to me), it lets you diff and review your changes before checking in. I do this all of the time, to make sure everything I did was everything I wanted, and that I didnt fuck anything up.

2) Don't be afraid to let things get messy. A very common (and valid) sentiment in programming is to avoid "premature optimization", where the programmer spends too much time too early on some part which may or may not even need it, introducing complexity for the sake of possible speed improvements etc. I don't hear people say this much, but I think you should take the same stance on organization. If you're programming software, and you need to add some new function for some task, don't be afraid to just toss it in near where you need it, and see what happens. Don't go creating tons of new files every time you need them. Moving code around for organization later is easy, and if you don't do it too soon, you'll a) stay focused, and b) save time in the event that the code you added wasn't used. Which brings us to the next point:

3) Don't be afraid to toss out code that you've written. Sometimes you have some problem and code a solution for it, and at the end of it, you just don't like it. If you don't like it, and think you could do it better the second time, do it the second time.

4) Going back to point #2, don't obsess from the beginning about reusability. Write code that you need, and once you're using it and see how you actually need to reuse it, then go make it reusable.

5) Finally, evolve your code. Getting something to the point of limping is the hardest part, so you should try to get to it as fast as possible. Once you're there, progress is much faster. It's like waiting for a minute to pass. If you look at a clock with a seconds hand, it goes quick, but if you just stare into space, it takes forever. Get to the point where you can see progress, then enjoy it (and test your work often).

More later, perhaps...

oh, and
December 9, 2006
I added a super simple thing to prevent spam on these comments, and it has worked perfectly. We'll see how long that lasts...


12 Comments:

Posted by Danno on Sun 10 Dec 2006 at 07:12 from 128.113.148.x

Hi Justin, I don't program Apple GUIs, but maybe this helps?

lists.apple.com/archives/Quartz-de...

Might I suggest another style and process tip? Learn and use a build tool on any project where executing the program with your new changes takes more effort than typing the name of the file.

Posted by Mauro on Sun 10 Dec 2006 at 11:34 from 203.28.159.x

Justin, which version control software do you use ?

Posted by hi on Sun 10 Dec 2006 at 14:23 from 24.31.9.x

yup

Posted by Cassidy on Sun 10 Dec 2006 at 15:54 from 209.66.18.x

Wonderful coding advice. The few projects I've created that I've actually been proud of were the result of this style of programming, although I didn't realize it at the time.

Posted by Jed on Mon 11 Dec 2006 at 09:44 from 222.153.241.x

You know a lot of that is great advice for any endevour - I thoroughly enjoyed the read even though I'm not a coder

Cheers
Jed

Posted by Jersey Jay on Mon 11 Dec 2006 at 10:37 from 137.237.193.x

Thanks for the programming insights. Also, that's a spiffy spam trap!

Posted by Jay on Tue 12 Dec 2006 at 22:16 from 220.130.149.x

Need to know UML and use it??

Posted by magicchord on Thu 04 Jan 2007 at 13:11 from 204.128.192.x

Oddly enough, your programming tips, with some words changed, would work as tips for songwriting as well.

Posted by VCS on Wed 17 Jan 2007 at 08:38 from 131.161.241.x

there is only one version control worth using. =) subversion.

Posted by ron on Fri 26 Jan 2007 at 05:44 from 139.149.1.x

I wholly subscribe to your programming tips...

Posted by Mike on Thu 08 Feb 2007 at 13:26 from 64.119.103.x

Why not avoid using windows api's and use a portable library. There are number of libraries to choose from. Also consider writing gui stuff in Java. Java 1.6 is less than 25% slower than C++, in some cases the same speed.

Posted by Jamsmith on Wed 12 Dec 2007 at 21:46 from 69.15.208.x

Java just sucks. And no I won't qualify it. Its like trying to talk to a Jesus freak. I will takle anything - C++, C#, anything BUT java. I will work with VB6 and the Win32 API before I will use Java. Yecch!

Add comment:

Name:
Human?: (no or yes, patented anti crap stuff here)
Comment:
search : rss : recent comments : Copyright © 2024 Justin Frankel