Home

Posts tagged with code

How to interview well at Google

Posted on August 29, 2011 at 10:11 PM

Categories: tech, code, infographics, jobs

Interview_flow_chart

Some friends of mine have been interviewing at Google and I've been helping them prepare. After some practice interviews, I drew up this flowchart for them to take with them (mentally) to the interviews.

Google uses "oral exam" type interviews:

For another strategy, pull out your copy of CLR(S) (you do have a copy, right?) and re-learn everything. It's all fair game in a google interview.

After you start reviewing, you must do practice interviews. Invite a friend over to ask you questions. Here is what they have to do:

  1. Pick a challenging question and read it to you.
  2. Not give you any help at all.
  3. Ask for a solution in pseudo-code. When you provide it, ask for the order of magnitude runtime analysis.
  4. If you make a mistake, after a while, they should say "are you sure that's correct?"
  5. If you don't give the optimal solution, they should let you develop it, and when you're done, say "do you think there's a better way to do it?"

Believe it or not, interviewing someone isn't a fun as you think, so provide them with beer and/or pizza. Meanwhile you must do your work on a whiteboard. If you don't have one, use a flip-chart or as a last resort paper.

Trust me, answering questions in real time on a white board isn't like doing them in your head. You must practice this or you're going to mess up the interview. Practice with a friend!

Finally, use the interview flowchart to answer the questions:

  • The first, simplest solution just has to work. Don't worry about runtime at this point.
  • Start with pseudocode. Only real code if they ask for it.
  • Do a bunch of examples. Make up some sample data and run through it by hand. This will help you understand the problem better, even if you think you already do.
  • Once you complete a simple (slow) solution, prove it works and then move on to making it faster.

If you do well, the interviewer will tell you you're done before you run out of time. Good luck!

How to embed a 480p YouTube video

Posted on April 19, 2011 at 10:17 PM

Categories: code, internet

Google doesn't provide any "official" way to embed a YouTube video in 480p. It always drops you down to 360p by default, and that just looks crap. You can embed in HD so why not 480p? No one knows. But don't despair, there is a way!

Here's some code for you:

<object width="853" height="505">
  <param value="http://www.youtube.com/v/MOVIE_ID&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;rel=0" name="movie">
  <param value="true" name="allowFullScreen">
  <param value="always" name="allowscriptaccess">
  <embed width="853" height="505" allowfullscreen="true"
    allowscriptaccess="always"
    type="application/x-shockwave-flash"
    src="http://www.youtube.com/v/MOVIE_ID&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;rel=0"&gt;
</object>

That will give you an "HD width" 480p video. Just change "MOVIE_ID" to the ID of your video (e.g. "J-lHxxToCfo") in both places. The width of the embed will be 853px, which is 16:9 for HD video.

What if your video is 4:3, i.e. 640x480? I can't find any clean way to embed at exactly that size, if you use the above code you'll get black bars on either side. However you can use a negative margin to get a box of the right shape. Just wrap your object like this:

<div style="width: 640px; overflow: hidden;">
  <div style="margin-left: -107px;">
    <object etc ... ></object>
  </div>
</div>

The controls will go off the screen but at least the user will still be able to click the centre of the video to start and stop it. Here's an example:

My column width is less than 640px but hopefully you get the idea.

Another job opening :-) iPhone developer — learn on the job

Posted on May 04, 2010 at 04:32 PM

Categories: code, business, iphone, jobs

My iPhone custom software development business is expanding yet again and we need more part-time programmers. The last round I hired two people, now we need more. Our recent apps include Unitron's uHear to test your hearing, OurKids, the Kik chat app, and others.

You must:

  • know C, C++, pointers, object and object-relational patterns already
  • be ready to learn the iPhone SDK fast (we'll help)

I've personally been programming on the Cocoa SDK since 1998 back when it was called OpenStep, so if you can pick things up, we can get you up to speed in a few weeks.

Demonstrate your qualifications by answering 2 out of these 3 tricky questions:

[Question 1] (C Pointers) Here is some slightly odd C code, but it will produce an (int) result, provided that you make some small changes in order to make it compile. What is the result going to be, and why?

int * a = 1990;
int result = &5[a];

[Question 2] (Database design) Create an entity-relationship diagram for a small subset of the Facebook database. In particular, include in your diagram:

  • User
  • Photo (including who is tagged in the photo)
  • Wall Post

Focus on the relationships/associations between these three objects, and only include one or two of the most important static fields (like a person's name). Make sure to indicate the cardinality of a relationship e.g. one-to-one/one-to-many/etc.

To get an idea of what I'm looking for see: http://en.wikipedia.org/wiki/Entity-relationship_model

Here's a tool you can use to draw it online: Gliffy. Then just send me a screenshot. Or feel free to use ASCII art or draw on a piece of paper and photograph/scan, as long as it's very clear.

[Question 3] (C++ Objects) The C++ program below has just 2 compile time errors, 1 runtime error, and there is 1 single line missing. Send us a fixed version that compiles and runs correctly. The errors will test your knowledge of object use and management in C++, and the missing line will test you on abstract/virtual inheritance.

SEND TO: simon@semacode.com. Include your answer(s) and some source code that you have written, whether it's open source, for assignments, for fun, or whatever.

REMUNERATION: Competitive.

MORE INFO: http://simonwoodside.com/pages/consulting

(PS Please keep the answers to yourself)

//// File: futurama.cpp ////
#include <iostream>

class Drinker {
public: Drinker(); void drink( int potency ); int _numberOfDrinksSoFar;
private: virtual int cantDrinkAnyMoreThan() = 0;
}; Drinker::Drinker() { _numberOfDrinksSoFar = 0; }
class Robot : public Drinker { int cantDrinkAnyMoreThan() { return INT_MAX; } };
class Human : public Drinker {
};
void Drinker::drink( int potency ) {
  _numberOfDrinksSoFar += potency;
  if( _numberOfDrinksSoFar > cantDrinkAnyMoreThan() ) { std::cout << "I'm all done." << endl; }
}

int main (int argc, char * const argv[]) {
  int beer = 5, coffee = 3;
  Human fry;
  Robot * bender;
  for( int i=0; i<6283; i++ ) { bender.drink(beer); }
  for( int i=0; i<100; i++ ) { fry.drink(coffee); }
  std::cout << "Bender: " << bender->_numberOfDrinksSoFar << "  Fry: " << fry._numberOfDrinksSoFar << std::endl;
  fry.drink(1);
  return 0;
}

Bug Points

Posted on March 27, 2010 at 03:34 AM

Categories: code

An incomplete list.

Per:

  • line of code: 1 point
  • line of generated code: 5 points
  • repeated line of code: 50 points
  • repeated comment: 10 points
  • TODO note: -10 points
  • comment explaining hack: -10 points
  • hack: 50 points
  • clever hack: -50 points
  • memory leak: 10 points
  • ignored warning: 100-1000 points
  • public but should be private: 100 points
  • unreadable line of code: 50 points
  • whitespace at the end of a line of code: 15 points
  • a tab: 25 points
  • incorrect indentation: 5 points

Compare: technical debt.

Job Opening: iPhone part-time / contract coder wanted -- we'll teach you

Posted on February 11, 2010 at 03:07 AM

Categories: code, business, iphone, jobs

My iPhone custom software development business is expanding and we need more part-time programmers. Our recent apps include Unitron's uHear to test your hearing, OurKids, an upcoming app for Kik, and others.

You must:

  • know C, C++, pointers, object and object-relational patterns already
  • be ready to learn the iPhone SDK fast (we'll help)

I've personally been programming on the Cocoa SDK since 1998 back when it was called OpenStep, so if you can pick things up, we can get you up to speed in a few weeks.

Demonstrate your qualifications by answering 2 out of these 3 tricky questions:

[Question 1] (C Pointers) Here is some slightly odd C code, but it will produce an (int) result, provided that you make some small changes in order to make it compile. What is the result going to be, and why?

int * a = 1990;
int result = &5[a];

[Question 2] (ORM) Draw an relational/DB model that would work for the Twitter database or the Facebook database. You don't have to cover all of the features, just the basics. You can use ascii art if you like.

[Question 3] (C++ Objects) The C++ program below has just 2 compile time errors, 1 runtime error, and there is 1 single line missing. Send us a fixed version that compiles and runs correctly. The errors will test your knowledge of object use and management in C++, and the missing line will test you on abstract/virtual inheritance.

SEND TO: simon@semacode.com. Include your answer(s) and some source code that you have written, whether it's open source, for assignments, for fun, or whatever.

REMUNERATION: Competitive.

MORE INFO: http://simonwoodside.com/pages/consulting

(PS Please keep the answers to yourself)

//// File: futurama.cpp ////
#include <iostream>

class Drinker {
public: Drinker(); void drink( int potency ); int _numberOfDrinksSoFar;
private: virtual int cantDrinkAnyMoreThan() = 0;
}; Drinker::Drinker() { _numberOfDrinksSoFar = 0; }
class Robot : public Drinker { int cantDrinkAnyMoreThan() { return INT_MAX; } };
class Human : public Drinker {
};
void Drinker::drink( int potency ) {
  _numberOfDrinksSoFar += potency;
  if( _numberOfDrinksSoFar > cantDrinkAnyMoreThan() ) { std::cout << "I'm all done." << endl; }
}

int main (int argc, char * const argv[]) {
  int beer = 5, coffee = 3;
  Human fry;
  Robot * bender;
  for( int i=0; i<6283; i++ ) { bender.drink(beer); }
  for( int i=0; i<100; i++ ) { fry.drink(coffee); }
  std::cout << "Bender: " << bender->_numberOfDrinksSoFar << "  Fry: " << fry._numberOfDrinksSoFar << std::endl;
  fry.drink(1);
  return 0;
}

(Update Feb 14: updated code to make my intentions clearer)

How to prepare a build for distribution in the App Store using the Program Portal, XCode, and iTunes Connect

Posted on September 28, 2009 at 04:59 PM

Categories: code, iphone

Apple does a pretty good job of explaining how to prepare the meta-data for an app submission in iTunes Connect, but it's not completely obvious how to prepare your actual build in XCode.

Assuming that you've already got Ad Hoc distribution working, it's not too hard. I was looking for advice and didn't find it, but I did find a question on StackOverflow that people had actually downrated and not really answered. So I figured out how to do it and added a proper answer. So without further adieu, rate me up on StackOverflow to give me wonderful wonderful karma, and view,

How to prepare a build for distribution in the App Store using the Program Portal, XCode, and iTunes Connect on StackOverflow

What happens when you don't understand open source licenses?

Posted on September 17, 2009 at 12:20 AM

Categories: tech, code, opensource

I was just checking out a TextMate-like editor for Windows called E Text Editor. It looks pretty good, but I was a bit surprised when I read about his "Open Company License".

To be clear, this is something he came up with himself, and it's not a bad idea. To be double clear, it's NOT open source. And he says that up front. He added "just one" clause to the standard BSD license:

Any redistribution, in whole or in part, must retain full licensing functionality, without any attempt to change, obscure or in other ways circumvent its intent.

Not bad. Users gain because they can modify the software and use the modified version all they want for in house purposes, and they don't have to share those changes with anyone. But they still have to pay him, and that's why it's not open source.

Unfortunately for him, he made a little mistake, because the clause only stipulates on redistribution.

So if you want E Text Editor for free, just download the source, modify it to remove the licensing code, build and use it. As long as you use it only yourself, you're perfectly legit and don't have to pay.

In addition, he left open a rather major hole. Anyone can now make a completely separate small program which downloads the source code, automatically applies a patch which removes the licensing code, builds it and installs on the local computer. This is the way in which many applications include GPL software into non-free, just in reverse. To be clear, my hypothetical program does this:

  1. You download my program, FreeE and run it on your computer.
  2. FreeE goes online and grabs the source code for E Text Editor.
  3. FreeE applies a patch to remove the code that makes you pay.
  4. FreeE builds—on your local machine—a new copy of E Text Editor without the pay code.
  5. FreeE quits and you delete it.

As long as you never distribute your copy of E Text Editor that you get this way, you're totally clear and legally able to use it without paying.

Alexander Stigsen, the author of E, might want to consider changing his license. But even if he does so, the versions he released under the current license will always have this hole. So go ahead, get some free as-in-beer software :-)

Regarding growing up your acts_as_taggable and lack of primary_key

Posted on August 12, 2009 at 07:53 PM

Categories: code, rails

This is a comment on "growing up your acts_as_taggable" post on Evan Weaver's blog snax.... because comments there are closed.

If you are upgrading from an older acts_as_taggable installation and moving to has_many_polymorphs, as I did, your old table will have create_table :id => false. That will be unhappy. You should add this to your migration:

add_column :taggings, :id, :primary_key

And that's all.

Closures with return values in Java

Posted on July 07, 2009 at 12:29 AM

Categories: code, java

Here's how to get everything you need from closures today in Java, without waiting for the big foreheads to argue over how to make it nice and perfect.

You've almost certainly used something sort of closure-like when you've used the Runnable interface. You can for example create an anonymous subclass of Runnable and .run() it:

  Runnable closure = new Runnable() {
 void run() { System.out.println("Hello"); }};
closure.run(); // prints Hello

In particular in Java Thread class implements Runnable. You can do more interesting things, for example:

  StringBuffer _myString = new StringBuffer("Hello");
// Java will only close around final variables because it's dumb
final StringBuffer foo = _myString;
Runnable closure = new Runnable() {
public void run() { System.out.println(foo); }
};
closure.run(); // prints Hello

This is why it's called a closure—the anonymous subclass Closes Around the variables in the scope in which it's defined. So, it has access here to myString. If you change _myString in the original context the closure will use the new value.

You can pass closures around, for example pass it to another method in another class, and it will still remain closed around the Original context. Like this:

  public void anotherContext( Runnable closure ) {
StringBuffer foo = new StringBuffer("Goodbye");
closure.run(); // still prints Hello from its own context
}

This is all available out of the box in Java, a little boring. It would be interesting if the closure could work on variables BOTH from its original context and that you pass into it at the same time. This can be done, but Runnable doesn't allow it, so we'll make our own Runnable:

// A general-purpose closure class that can receive and
// return values when you call it.
// This is an abstract class... override these functions for
// whatever kind of closure you need.
// If you call a non-overriden function, it will throw you.
public class SemaRunnable {
public void run() { throw new RuntimeException("Must override SemaRunnable.run()"); }
public Object run( Object param ) { throw new RuntimeException("Must override SemaRunnable.run()"); }
}

Now I can do a simple example (from the Wikipedia article):

SemaRunnable bestSellingBooks = new SemaRunnable() {
public Object run( Object thresholdObject ) {
int threshold = ((Integer)thresholdObject).intvalue();
// assume bookList is in the local context:
myBookList = bookList.booksWithSalesGreaterThan(threshold);
return myBookList;
}
};
// call books = bestSellingBooks.run( Integer(5000) );

Here's a more complete example. In some code I'm working on, I need to pass an image—not just an image, but also the ability to get just a subImage of that image. I don't want them to have to know how to do image manipulation. Here is how I do it using closures:

    SemaRunnable getSubImage = new SemaRunnable() {
      public Object run( Object param ) {
        int x = Array.getInt(param,0); // these four variables
 int y = Array.getInt(param,1); // are coming in
        int width = Array.getInt(param,2); // from the
 int height = Array.getInt(param,3); // caller
// Now I will close on a method in my local context:
        short[] subImg = dataForSubImage( x, y, width, height );
return subImg;
      }
    };
someObject.setClosureToBe(getSubImage);

...

// This method is being closed upon in the local context:
public short[] dataForSubImage( int x, int y, int width, int height ) {
...

someObject in some completely different part of my code, gets the closure and calls it like this:

  // completely different class, which received closure object
int [] subImageData = (int[])closure.run( new int [] {new_x, new_y, new_w, new_h} );

You don't have to call it closure. And you can pass as many params either way as you like, storing them in arrays, since array is an Object in java.

But... but... but..., people will say, why not create a class which does this, and import the class, and construct the class, and make calls on the class, it would do the same thing. They just answered their own question: it requires lots of LOCs.

And there's other good reasons. For example, let's say you have two versions of your function for different situations, you can simply swap them out of they are closures. The beauty of it is, the java compiler doesn't know or care what's happening, because everything is just SemaRunnable and Object. So it's not going to complain that a function or class name has changed. That means metaprogramming goodness. Sweet.

So, practical closures in Java. It may look a little unfamiliar at first, but once you know how to do it it's easy and can be really useful.

EXTRA SPECIAL BONUS: An implementation of the full monty, closure that takes a closure, makes a new closure from it, and returns that. I promised myself I'd go to bed early, but instead I stayed up and wrote you this code which is guaranteed to actually work, because I tried it. Try running it.


// By: Simon Woodside sbwoodside (a)(t) gmail (d)o(t) com
// See: http://simonwoodside.com/weblog/2009/7/7/a_little_bit_more_serious/

// To try this out:
// % javac Test.java && java Test

// Demonstration of how to do closures in Java
// In this case, |derivative| is a closure which approximates derivatives, and
// |sineDerivativeApproximator| approximates the derivative of ... you guessed it ... sine.

// It's hard to believe, given how much code there is, but in javascript this would be:
// function derivative(f, dx) {
// return function(x) {
// return (f(x + dx) - f(x)) / dx;
// };
// }
// (See http://en.wikipedia.org/wiki/Closure_(computer_science) )

import java.util.*;
import java.lang.reflect.*;
import java.lang.*;

public class Test {
public static void main (String args[]) {
System.out.println("Closures coming up!");
Test test = new Test();
test.go();
}

// SemaRunnable is a general-purpose closure class that can receive and
// return values when you call it.
// This is an abstract class... override these functions for
// whatever kind of closure you need.
// If you call a non-overriden function, it will throw you.
public class SemaRunnable {
public void run() { throw new RuntimeException("Must override SemaRunnable.run()"); }
public Object run( Object param ) { throw new RuntimeException("Must override SemaRunnable.run()"); }
}

void go() {
// Let's start with a really simple example.
// See my blog post for more details:
StringBuffer _myString = new StringBuffer("Hello");
final StringBuffer foo = _myString;
Runnable closure = new Runnable() {
public void run() { System.out.println(foo); }
};
closure.run(); // prints Hello

// Now let's do something more fun.
// A closure that receives a closure and returns a new closure.
// This is going to be wordy because Java Arrays and Number objects are TERRIBLE

// Return a function that approximates the derivative of f
// using an interval of dx, which should be appropriately small.
SemaRunnable derivative = new SemaRunnable() {
public Object run( Object params ) {
// params must be { SemaRunnable f, Float dx }
final SemaRunnable f = (SemaRunnable)Array.get(params,0); // get f
final float dx = ((Float)((Object[])params)[1]).floatValue(); // get dx
SemaRunnable approximator = new SemaRunnable() {
public Object run( Object xFloat ) {
float x = ((Float)xFloat).floatValue();
float fOfXPlusDx = ((Float)f.run( new Float(x + dx) )).floatValue();
float fOfX = ((Float)f.run( new Float(x) )).floatValue();
float answer = (fOfXPlusDx - fOfX) / dx;
return new Float(answer);
}
};
return approximator;
}
};
// Now create a closure that will simply return the sine(x):
SemaRunnable sineClosure = new SemaRunnable() {
public Object run( Object xFloat ) {
double sine = Math.sin( ((Float)xFloat).floatValue() );
return new Float(sine);
}
};
// And finally put it all together:
SemaRunnable sineDerivativeApproximator =
(SemaRunnable)derivative.run( new Object [] { sineClosure, new Float(0.001) } );
for( double x = 0.0; x<3.1416; x+=0.1 ) {
Float result = (Float)sineDerivativeApproximator.run(new Float(x));
System.out.println( "Sine(" + x + ") = " + result );
}
}
}

I ran out of time to demonstrate this, but you can also modify variables in the context from inside the closure, even though they are final, by creating a final array containing the variable, and then modifying the object contained in the array. It's not pretty but it works.

How many programming languages do you know?

Posted on June 16, 2009 at 10:31 PM

Categories: tech, meta, code

List of programming languages that I know* that appear on the Official Wikipedia List of Programming Languages**.

  • * Or once knew... but I could pick it up again, I swear. It's like riding a bicycle. I don't include languages that I tried to learn but failed... like Scheme and Prolog.
  • ** Commonly recognized as the standard in Lists of Things. Let it be known that I only include those languages that are turing complete, so CSS and HTML don't count.

Begin listing:

  1. AppleScript
  2. BASIC (Apple ][+)
  3. Bourne Shell
  4. C
  5. C++
  6. DLX Assembler (not listed, but it's a language...)
  7. HyperTalk (my first, favourite language!)
  8. Java
  9. JavaScript
  10. Lingo
  11. MATLAB
  12. Modula-3 (and don't I wish I didn't?)
  13. Objective-C
  14. Pascal
  15. Perl (and don't I wish I didn't?)
  16. PHP
  17. Python (and don't I wish I didn't? :-)
  18. Ruby (my third, favourite language!)
  19. μC++ (is it really a separate language? Well, it requires a separate compiler...)
  20. Visual Basic (sufficiently different from basic BASIC)
  21. XSLT (yes it's turing complete) (my second, favourite language)

So. Thoughts. FIrst, I can say that I know more than 20 languages. Second, my # of languages isn't going up as slowly these days, but the depth is. Third, my big hole is functional languages. Only XSLT is really functional-ish (people get mad when I say that).

I'd like to learn oCaml.

All of this work courtesy of procrastion and needing to quote a number of languages on my updated Custom Software Development page.

Rails "core team" fucks up big time

Posted on June 07, 2009 at 11:03 PM

Categories: tech, code, rails

Hey, if you have a rails app that uses the recently introduced authenticate_or_request_with_http_digest Rails 2.3 / http_authentication.rb, you've got a big fucking security hole. Anyone can log in if they provide a wrong username and no password, or a nil username & password.

Kind of terrible, right?

So Nate posts it on his blog after a week of trying to get the attention of the Rails security people, and they blame him in their security alert:

Due to communication difficulties and a mis-understanding between the reporter and the security team. This vulnerability has been publicly disclosed on several websites, users are advised to update their applications immediately. Steps are being taken to ensure that the security email is more reliable in the future. We regret the nature of this disclosure and will endeavor to ensure it doesn’t happen again in the future.

And they give him no credit. Most of the RCT idiosyncracies I can write off but don't fuck with security.

uHear -- test your hearing with an iPhone

Posted on June 04, 2009 at 11:39 PM

Categories: code, mobile, iphone

Here's a little movie I made of an iPhone app called uHear I developed for Unitron. This is also a bit of an experiment because I've uploaded the movie to Amazon S3 and you're watching it from AWS.

Anyway, the video is short, and shows you four parts of the app:

  1. The standard hearing sensitivity test, which finds out how quiet you can hear at various pitches in each ear,
  2. the speech & noise test, which tests if you might have trouble hearing over noise like in a restaurant,
  3. lots of hearing-related info, and finally,
  4. a live audiologist lookup based on your current location, powered by google maps API.

You'll want to turn your speakers up or the first bit might seem a bit pointless.

Making this app was pretty cool, my client was excellent, I worked closely with their audiologist in charge of this project and really pushed the boundaries of playing back audio on the iPhone in a very precise way. We also implemented some really cool UE/graphics designed by Tom Auger of Zeitguys in Toronto.

Incidentally, I'm available to do more iPhone consulting on a part-time basis :-) Bring in Simon & Woodside when you need crack software development (but not software development for crack).

How to do rails tests when running with restful_authentication

Posted on May 26, 2009 at 01:18 AM

Categories: code, rails, ruby

The Restful Authentication plugin seems to be the standard right now, although I'm staring to wish I'd tried something else, maybe AuthLogic... because restful_authentication is kind of poorly documented. One serious error of ommission is how the hell do you update your tests so that you can run them on controllers that require a logged in user? Well, I have had the pain, and so you can have the quick answer, here it is.

Assuming you are using ActionController::TestCase ... first edit test_helper.rb:

  # Add this helper function to test_helper.rb
# It will allow you to run any block under the aegis of
# a controller of your choosing. This is not something
# that is possibly by default
def run_with_controller( controller_class )
old_controller = @controller
@controller = controller_class.new
yield
@controller = old_controller
end

Now you can use that helper method in your test cases, in the setup function do this:

  def setup
run_with_controller(SessionsController) do
post :create, { :login => "george", :password => "monkey" }
end
end

What you're doing here is simply making a POST to the Restful Authentication SessionsController to "create" a new session, pass in a login/password that exists in your fixtures. And that's it.

By the way, if you chose to install with RSpec because of the dire warnings that old fashioned tests will be out of date, but aren't currently using RSpec for you other tests, you should copy the rspec fixture data into test/ so that you get the right password hashes. Tricky...

sudo apachectl stop && sudo apt-get remove apache2 && sudo apt-get install nginx

Posted on April 30, 2009 at 12:56 AM

Categories: tech, code, rails, internet

Nginx-logo

I binned apache finally on semacode.com. It was easy. A little bit of "this is really the last straw" frustration with mod_rewrite and I ditched it.

I've been threatening to leave you, apache, for years. Ever since I first cursed your horrid rewriterules, I knew that it would never be the same between us. You were good, once. You weren't just "a patchy" web server, but a scrappy one... once. But 2.0 you just didn't live up. You didn't fix your big warts. You got flabby. Even the decision by your developer team to finally remove the default MIME type didn't redeem you in my eyes.

No, it was just one poke in my eye too many, when you insisted on unencoding my percent encoded URLs before passing them to the rails/mongrel proxy, and there was just no way to make you stop doing it, no matter how many googles I searched. And so I said: enough is enough. Everyone on Rails uses nginx now, and I will too. I'm tired of learning how to sacrifice chickens to the apache configuration gods. Bring me something new, clean, shiny, fast, and easy to configure!

Learning how to configure nginx took an hour on the outside—it's very easy and keeps all the good parts of apache's syntax and throws away the complete crap. It even allows me to compress stupid blocks into one-liners! :

  if (-f $document_root/system/maintenance.html) { rewrite  ^(.*)$  /system/maintenance.html last; break; }

Isn't that gorgeous! I agree. And so the "engine x" russians get my love now. It's all over. Sayanora. End communication.

How to really URL encode an NSString in Objective-C, iPhone, etc.

Posted on April 22, 2009 at 02:52 AM

Categories: code, mac, iphone, objectivec

Trying to encode URL parameters on Mac or iPhone? Frustrated because NSString stringByAddingPercentEscapesUsingEncoding encodes non-URL characters but leaves the reserved characters (like slash / and ampersand &) alone? "Apparently" this is a "bug" apple is aware of, but they haven't done anything about it yet, and so, here is a solution that actually works.

Try this:

  NSString * encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
 NULL,
 (CFStringRef)unencodedString,
 NULL,
 (CFStringRef)@"!*'();:@&=+$,/?%#[]",
 kCFStringEncodingUTF8 );

As an example, @"'Decoded data!'/foo.bar:baz" will become "%27Decoded%20data%21%27%2Ffoo.bar%3Abaz".

Obviously you would use this, not on the full URL, but just on the parameters.

The better way to code error-handling routines

Posted on April 17, 2009 at 12:50 PM

Categories: code, rails, ruby

There's an excellent guide to Rails 2 that I'm reading through right now, but I don't like this bit:

    if @comment.save
redirect_to post_comment_url(@post, @comment)
else
render :action => "new"
end

It's much better like this:

    render :action => "new" and return unless @comment.save
redirect_to post_comment_url(@post, @comment)

They do exactly the same thing, but mine is 2 lines instead of 5, and mine clearly eliminates the exceptional/error case first, and then leaves you to see the normal case. In fact, I virtually always code this way when I can, deal with the error cases first, and return, and then the rest of the function is an un-nested normal case handler.

iPhone programming: how to switch to a landscape view at the moment of your choosing

Posted on February 27, 2009 at 05:12 PM

Categories: code, mobile, iphone

Maybe someday, Apple will make it easy to rotate manually into a landscape view. But right now it's been causing me enormous headache with hideous frames issues. Running an app in landscape the whole time is easy, but doing just some views in landscape is insane, especially if you're trying to switch while in the middle of a navigation controller.

However I've found an easy solution which is to use a new window. Just reset the whole view problem. You can then fake out the navigation bar using the method of your preference. Here's the bare bones. For me, I'm going from a tableView, click on an item and get a "results view".

// In ResultsListController, a UITableView delegate:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  ResultsViewController * resultsViewController = [[[ResultsViewController alloc] initWithNibName:@"ResultsViewController" bundle:nil] autorelease];
  resultsViewController._recordIndex = indexPath.row;
  UIWindow * window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // this is a leak!
  window.backgroundColor = [UIColor redColor]; // just for debugging
  [window addSubview:resultsViewController.view];
  [window makeKeyAndVisible];
}

Now ResultsViewController has its own NIB, and the view is set to be sideways in IB.

// In ResultsViewController
- (void)viewWillAppear:(BOOL)animated; {
// First rotate the screen:
  [UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationLandscapeRight;
// Then rotate the view and re-align it:
  CGAffineTransform landscapeTransform = CGAffineTransformMakeRotation( degreesToRadian(90) );
  landscapeTransform = CGAffineTransformTranslate( landscapeTransform, +90.0, +90.0 );
  [self.view setTransform:landscapeTransform];
}

// Connect your "back" button in the results view to this:
- (IBAction)back:sender; {
// return screen rotation to normal:
[UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationPortrait;
// Get rid of the window, and the "normal" window will re-appear from underneath
self.view.window.hidden = YES;
[self.view.window resignKeyWindow];
}

Easy as cake!

UPDATE: There's follow-up Q&A on the iphonedevSDK forums.

Wondeful joy! Mix Ruby and Objective-C with MacRuby

Posted on February 10, 2009 at 02:51 AM

Categories: code, mac, ruby

Macruby

How great is this. You can use any language you want in your MacRuby projects. Want to add in some code you already wrote in Objective-C++? No problemo!

Check out the cool screenshot below which shows everything in action! (You might have to click on the full post view to get the picture).

Also, you might be wondering how to get full bi-directional bridge going on between Ruby and Objective-C/Cocoa. In otherwords, how do you call/access/include/import/require your own Objective-C classes from Ruby and your Ruby objects from Objective-C? It's actually done sort of automagically. If you have a Ruby class Foo and a ObjC class Bar...

(You seem to have to use NSClassFromString(@"FooController") to avoid getting a linker error. Apparently the bridge is not yet running at compile/link time. Also, you (seem to) have to type your bridged objects to id in ObjC, although maybe there's a way around both those limitations that I don't know about yet.)

# Foo.rb
class Foo
def foo
puts 'FOO'
bar = Bar.new
puts bar.bar
end
def baz
return "BAZ"
end
end

// Bar.h
#import <Cocoa/Cocoa.h>
@interface Bar : NSObject {
}
- (NSString*)bar;
@end

// Bar.m
#import "Bar.h"
@implementation Bar
- (NSString*)bar; {
id foo = [[NSClassFromString(@"FooController") alloc] init];
NSLog(@"%@", [foo baz]);
return @"BAR";
}
@end

And you will get this output when you call Foo.foo:

FOO
2009-02-10 02:46:28.017 Untitled[37257:10b] BAZ
BAR

Boing boing boing! Enjoy!!!!

How to make WYM Editor support embed objects (such as flash videos, youtube, etc.)

Posted on February 08, 2009 at 02:27 AM

Categories: code, internet

Hello! I've got a big update for this post, so skip to the end for the goodness!

I use WYM Editor for editing my posts, it's awesome, there's only just one small thing that I don't like about it, which is out of the box it doesn't allow you to copy/paste embed tags like you would use to embed a flash video, youtube video, etc. into your posts. It actually strips out embed tags if you try to put them in.

Why they would not support this, is out of my mind, I can't understand it. There doesn't seem to be any sense in it. Oh well, I know javascript and XML so I can fix it right? Sure, why not.

So, here is a patch that enables basic support. You can switch to "HTML mode" (i.e., the mode where you can see the sourc code, 2nd button from right in the standard view) and paste in some embed code, the stuff you get from YouTube that looks like this:

<object width="480" height="295">
<param name="movie" value="http://www.youtube.com/v/jzHBszZn6uo&amp;hl=en&amp;fs=1"&gt;&lt;/param&gt;
<param name="allowFullScreen" value="true"></param>
<param name="allowscriptaccess" value="always"></param>
<embed src="http://www.youtube.com/v/jzHBszZn6uo&amp;hl=en&amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="295"></embed>
</object>

The embedded item might or might not actually appear in the preview mode at that point. Don't worry about it. Save it, view the final result, it should be there.

It would be nice if the developers would take this and build it in so that you can actually copy/paste them in the "normal" way.

Here is the patch, apply it by hand, or copy/paste it into a patch file and apply using the patch command.

Index: wymeditor/jquery.wymeditor.mozilla.js
===================================================================
—- wymeditor/jquery.wymeditor.mozilla.js	(revision 119)
+++ wymeditor/jquery.wymeditor.mozilla.js	(working copy)
@@ -80,10 +80,11 @@
     
     //replace em by i and strong by bold
     //(designMode issue)
-    html = html.replace(/<em([^>]*)>/gi, "<i$1>")
-      .replace(/<\/em>/gi, "</i>")
-      .replace(/<strong([^>]*)>/gi, "<b$1>")
-      .replace(/<\/strong>/gi, "</b>");
+    // this messes up embed tags—changes them to ibed
+    //html = html.replace(/<em([^>]*)>/gi, "<i$1>")
+    //  .replace(/<\/em>/gi, "</i>")
+    //  .replace(/<strong([^>]*)>/gi, "<b$1>")
+    //  .replace(/<\/strong>/gi, "</b>");
     
     //update the html body
     jQuery(this._doc.body).html(html);
Index: wymeditor/jquery.wymeditor.js
===================================================================
—- wymeditor/jquery.wymeditor.js	(revision 119)
+++ wymeditor/jquery.wymeditor.js	(working copy)
@@ -2068,6 +2068,17 @@
     "13":"dl",
     "14":"dt",
     "15":"em",
+    "embed":
+    {
+      "attributes":[
+      "allowscriptaccess",
+      "allowfullscreen",
+      "height",
+      "src",
+      "type",
+      "width"
+      ]
+    },
     "fieldset":
     {
       "inside":"form"
@@ -2243,10 +2254,11 @@
     {
       "attributes":
       {
-        "0":"type",
+        "0":"name",
+        "1":"type",
         "valuetype":/^(data|ref|object)$/,
-        "1":"valuetype",
-        "2":"value"
+        "2":"valuetype",
+        "3":"value"
       },
       "required":[
       "name"
@@ -3449,7 +3461,7 @@
     this.block_tags = ["a", "abbr", "acronym", "address", "area", "b",
     "base", "bdo", "big", "blockquote", "body", "button",
     "caption", "cite", "code", "col", "colgroup", "dd", "del", "div",
-    "dfn", "dl", "dt", "em", "fieldset", "form", "head", "h1", "h2",
+    "dfn", "dl", "dt", "em", "embed", "fieldset", "form", "head", "h1", "h2",
     "h3", "h4", "h5", "h6", "html", "i", "ins",
     "kbd", "label", "legend", "li", "map", "noscript",
     "object", "ol", "optgroup", "option", "p", "param", "pre", "q",

The Big Update

Thanks to Maxwell Scott-Slade for commenting and pointing to his even more improved version on his blog. I've taken his & my work, added the ability to support flashvars attribute (required for flickr embeds among others) and forked the wymeditor svn repository into GitHub. Get WYMEditor that supports flash on GitHub.

If you want to use it, just:

% git clone git://github.com/sbwoodside/wymeditor.git
% cd wymeditor/trunk
% make

The result will be in build/build/wymeditor.tar.gz.

How to make an iPhone button highlight (hold state)

Posted on February 05, 2009 at 07:26 PM

Categories: code, iphone

Here's how to use iPhone SDK to make a button hold it's on/highlighted state when you click on it:

- (IBAction)badButton:sender; {
  badButton.highlighted = YES;
  if( _hasChosen == NO ) {
    _hasChosen = YES;
    [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(badButton:) userInfo:nil repeats:NO];
  }
}

On simulator it looks perfect, but on device there's a brief moment when it goes white before it goes blue/highlighted again.

iphone objective-c pain ... give me ruby, bastards!

Posted on January 11, 2009 at 02:37 AM

Categories: code, mobile, ruby

I'm writing an iPhone app in Cocoa Objective-C and really wishing that I could be writing it in Ruby instead (cocoa-ruby on iphone anyone?).

Take this one line:

    if( ! [foo isEqualToString:bar] ) {

Oh yeah, I can really tell what that does by glancing at it... not! But here's the equivalent ruby:

    unless foo == bar

Shorter, more obvious, easier to write, easier to read and maintain. Why does Cocoa need to be so wordy? Even [foo equals:bar] would be better. But no, that would be too ... ambiguous. I don't know. isEqual: is defined in NSObject but who knows what highly dangerous or unexpected result it would have between two strings. Maybe it would only be true if they were the same pointers, or copy: results. No one in ObjC land seems to be thinking about making syntax easier for the programmers, do they? And why don't we have overloading???

For example, if we had method overloading, you could easily have different versions of equals: (or isEqual: if you must) that handle NSString*, NSWhatever*... of course this would require the compiler to be smarter, and the runtime to be smarter, and who uses Objective-C other than Apple ... no one, that's who. Hey, here's an idea—why not ditch ObjC wholesale for Ruby? It's not like Ruby is going to be, you know, slower. Well, of course it will be slower in the C sections.

At least now with "Fast Enumeration" in Objective-C 2.0 we can do something like this:

    for( NSString * bird in [NSArray arrayWithObjects:@"owl", @"parrot", @"partridge", @"pigeon"] ) {

Although again, it's really annoying that there's no convenience syntax for creating an array. How hard would it be? Not very hard, that's how hard. In Ruby it would be simply:

    for bird in ["owl", "parrot", "partridge", "pigeon"]

At least we have convenience syntax for NSString * animal = @"Bandicoot" right? I suppose we should pray at the altar for that one and hope they never take it away...

Finally, I have to kiss good-bye to any kind of interesting use of first-order functions and closures. Technically Objective-C CAN actually do dynamic function calls at least, but it's so bloody wordy that I rarely use it unless forced to. I can't use the lovely map function in Objective-C which adds considerably to my line count.

But wait, Apple is adding closures?  ... why don't they spend the effort on making Ruby Cocoa better instead? Or maybe give me garbage collection on the bloody iPhone.

Ruby on Rails Feed/RSS Aggregator (35 lines)

Posted on December 07, 2008 at 03:17 AM

Categories: code, rails, ruby

I wrote myself a feed aggregator for my front page. And... voila! I'm finally satisfied with it to post it.

Update: I've now published this as a complete standalone rails app on github/sbwoodside/portal. The important bits are app/controllers/portal_controller.rb and config/config.yml.

For me I run this as a standalone rails app, separately from my weblog. You could do that (and redirect requests to / or /index.html with Apache or nginx/etc. Or you could integrate it into your own app. Up to you.

Features:

  • Will aggregate ANY feed, no matter how badly mangled by the creators, using FeedTools (I also tried feed_normalizer and simple rss but they're not as good)
  • Deals with slowness of downloading feeds, RSS, etc., and REXML by caching
  • Deals with need to recache using elegant http/cron periodic system
  • Display the feeds in a facebook-like news feed format, sorted by dated.
  • You can easily re-label the feeds, add and renew feeds (in the code)
  • Only 35 lines of controller code!

The heart of it is the controller, obviously. The best thing? It's only one page of code! Ruby rocks!

require 'feed_tools'

class PortalController < ApplicationController
layout 'site'
# Instructions: 1. Change @@secret. 2. Add a cron job to regularly call /?recache=yes&secret=XXXXXXX
# This is a feed aggregator that uses FeedTools because it handles practically any feed.
# But FeedTools is super slow in every way so this aggregator stops using it as soon as possible.
# TODO add XML feed output

@@secret = "change_this" # change this to protect your site from DoS attack
# The array of feeds you want to aggregate. If you change this then manually delete the whole cache.
@@uris = ['http://simonwoodside.com:8080/posts/rss', 'http://simonwoodside.com/comments/rss',
'http://semacode.com/posts/rss',
'http://api.flickr.com/services/feeds/photos_public.gne?id=20938094@N00&amp;lang=en-us&amp;format=rss_200',
'http://api.flickr.com/services/feeds/activity.gne?user_id=20938094@N00']
# A map between the "official" feed titles in the XML, and the titles you want to show when rendered.
@@title_map = { "Simon Says" => "Simon Says:", "Simon Says: Comments" => "Simon Says comment:",
"Uploads from sbwoodside" => "Flickr picture:", "Semacode" => "Semacode blog post:",
'Comments on your photostream and/or sets' => 'Flickr comment:' }

def index
if params[:recache] and @@secret == params[:secret]
cache_feeds
expire_fragment(:controller => 'portal', :action => 'index') # next load of index will re-fragment cache
render :text => "Done recaching feeds"
else
@aggregate = read_cache unless read_fragment({})
end
end

private
# This will replace cached feeds in the DB that have the same URI. Be careful not to tie up the DB connection.
def cache_feeds
puts "Caching feeds... (can be slow)"
feeds = @@uris.map do |uri|
feed = FeedTools::Feed.open( uri )
{ :uri => uri, :title => feed.title,
:items => feed.items.map { |item| {:title => item.title, :published => item.published, :link => item.link} } }
end
feeds.each { |feed|
new = CachedFeed.find_or_initialize_by_uri( feed[:uri] )
new.parsed_feed = feed
new.save!
}
end
# Make an array of hashes, each hash is { :title, :feed_item }
def read_cache
@@uris.map { |uri|
feed = CachedFeed.find_by_uri( uri ).parsed_feed
feed[:items].map { |item| {:feed_title => @@title_map[feed[:title]] || feed[:title], :feed_item => item} }
} .flatten .sort_by { |item| item[:feed_item][:published] } .reverse
end
end

It's actually pretty simple but it took me a while to get the balance just right. What you need to do is set up a cron job or other repetitive task that does an HTTP load on http://mywebsite.com/?recache=yes&amp;secret=XXXXXXXX ... every once in a while. You can use wget or curl, or whatever. You might want to recache every minute, five minutes, hour, whatever. Since it's done as a part of the controller there's no nonsense about running backgroundRB, RubyCron and all the other nonsense at HowToRunBackgroundJobsInRails. Yay!

Here's the view:


<div id="feed-stream">
<% cache do %>
<%
lastday = -1
@aggregate.each do |item| %>
<div class="item">
<%
mydate = item[:feed_item][:published].getlocal
if mydate.yday != lastday
%><div class="item_details"><p style="text-align:right"><%= mydate.strftime('%A, %B %e') %></p></div><%
lastday = mydate.yday
end
%>
<div class="item_content">
<%= item[:feed_title] %>
<a href="<%= item[:feed_item][:link] %>"><%= item[:feed_item][:title] %></a>
</div>
</div>
<% end %>
<% end %>
</div>

My cache is all Hashes. I don't cache the FeedTools object because I discovered that even after FeedTools has parsed your feed, accessing the supposedly "final" data is incredibly slow (like maybe 10x or 100x slower than a hash).

Here's the model:


require 'feed_tools'
class CachedFeed < ActiveRecord::Base
validates_presence_of :uri, :parsed_feed
validates_uniqueness_of :uri
serialize :parsed_feed, Hash # note that if this exceeds a certain KB size, it will likely fail (thinking it's a String)
end

And the migration:


class CreateCachedFeeds < ActiveRecord::Migration
def self.up
create_table :cached_feeds do |t|
t.column :uri, :string, :limit => 2048
t.column :parsed_feed, :text, :limit => 128.kilobytes # use for serialized object
t.timestamps
end
end

def self.down
drop_table :cached_feeds
end
end

Well, that's all you need. When I started out to make this I thought I'd find a simple example out there but there wasn't anything. It turns out that there's a number of interesting challenges — picking a parser to deal with difficult feeds, XML, and malformatted XML... to deal with caching ... to deal with background processing. Took me a while to get it all just right.

It powers my own front page ... consider to be under standard ruby open source license. As the vending machine says: Share And Enjoy!

New version of FractalTrees X (FTX) 2 beta 1

Posted on December 03, 2008 at 02:28 AM

Categories: code, mac

So after something on the order of 4 years I've finally upgraded my FTX program that draws fractal trees in 2 dimensions. I'll update the program's home page later, but in the mean time, here's the download link, with source code included.

Fractal Trees X 2 beta 1 (FTX2b1)

This has the advantage over the "alpha" in that it actually works the way it's supposed to.

Why am I returning to this after so long? Well, suddenly coding for Macs is cool again, and also I was going to try out MacRuby. So... first get it working in ObjC again I guess, and then we'll see — maybe I'll port it to iPhone and sell it for $0.99 a pop :-) :-)

(NB This version probably only works on Intel / 10.5.)

Vuze (Azureus) search template for The Pirate Bay (TPB)

Posted on October 31, 2008 at 05:55 PM

Categories: code, bittorrent

Vuze provides a built-in search function to make it easier to find bittorrent files that you want to download. And, it's extensible, so you can add new search "templates" for torrent sites beyond the ones that they support by default.

There's a Pirate Bay template floating around but it doesn't work any more, so I made up my own. And here it is:

Download The Pirate Bay (TPB) search template for Vuze.

To install this sucker, you can just double click the file. If that doesn't work, try this:

  1. Download it (duh)
  2. Do a search in Vuze
  3. On the right, it says "Show results from..." "All" and then some options, and then "Add/Edit". Click Add/Edit.
  4. Below the list, click "Import a new template"
  5. Browse to tpb.vuze and open it.

UPDATE: some people are having trouble. Please post your Vuze version # and operating system if it works, or doesn't.. maybe there's a pattern.

UPDATE #2: It seems that if you are running in a language other than English, this might not work. If you can confirm that I would appreciate it. Thanks.

UPDATE #3 2009-12-10: The Pirate Bay changed their format a bit, so I updated the template. Click the download link to get the new one.

Apple are idiots

Posted on October 17, 2008 at 07:22 PM

Categories: code

I just tried to open my old XCode project for FractalTrees X in XCode. No dice—XCode doesn't even recognize the "pbproj" extension any more, and that's only from 2002... Then I try to open my NIB at least? And it's totally toast. Nothing. Won't open. Won't upgrade in ibtool. Nothing.

Hacking the java compiler: using anonymous subclasses as closures

Posted on July 10, 2008 at 11:17 PM

Categories: tech, code, java

UPDATE: new more comprehensive post on this subject: Closures with return values in Java.

In Java, closures/first-order functions are not a language feature. However, as everyone knows, you can effectively get a first-order function by using an anonymous subclass instead. Something like this:


class MyClosure {
void run() {} // override this
}
void doSomethingClosureLike() {
MyClosure closure = new MyClosure() { void run() { System.out.println("We're inside a closure!"); }};
runTheClosure(closure);
}
void runTheClosure(MyClosure closure) {
closure.run();
}
// will print We're inside a closure!

Anyway, it's simple enough, you pass the class instead of the function and there's a little extra verbage but it works!

Also you get closure-like functionality, because inside run() you can access variables from outwhere where you created it. E.g.:


void doSomethingCooler() {
final String myString = "Foo!";
MyClosure closure = new MyClosure() { void run() { System.out.println("The string is: " + myString); }};
runTheClosure(closure);
}
// will print The string is: Foo!

You can also access global variables that change over time, and the closure will use whatever is the current value WHEN THE CLOSURE RUNS.

There's just one small annoying thing, which is this particularly annoying compiler message:

local variable (WHATEVER) is accessed from within inner class; needs to be declared final

If you were do change myString to not be final, you'd get that error. Bummer. You could make myString a global variable and that would work, but that's stupid. There is a better way. Try this: UPDATE: This doesn't work, see new version at the bottom, thanks commenter the.d-stro.

void doSomethingCooler() {
String myString = "Foo!";
final String myStringFinal = myString;
myString.concat(" Bar!");
  MyClosure closure = new MyClosure() { void run() { System.out.println("The string is:" + myStringFinal); }};
 runTheClosure(closure);
}
// will print Foo! Bar!

Now you can even change myString after you assign myStringFinal, because Java, although they say it doesn't use pointers, really does use pointers. I.e. it passes by reference. So, myStringFinal is actually just a reference to myString, and keeps pointing to it even when you change the contents of myString.

You can CHANGE it (like using concat()) but you CAN'T reassign it. That will break the pointers. It makes sense if you think about it—myString will have a new memory address, and myStringFinal will still be pointing to the old memory address (and the old string value). So, this won't work:

myString = "won't work"; // breaks myStringFinal

You can use this technique with any object (but not primitives like int).

UPDATE

The last source block is wrong because java Strings are immutable. Here's an example that will work as advertised:


void doSomethingCoolest() {
StringBuffer myString = new StringBuffer("Foo!");
final StringBuffer myStringFinal = myString;
myString.append(" Bar!");
MyClosure closure = new MyClosure() { void run() { System.out.println("The string is: " + myStringFinal); }};
runTheClosure(closure);
}
// will print The string is: Foo! Bar!

Restoring the old posts

Posted on July 07, 2008 at 12:35 AM

Categories: tech, code

OK, here's a test of how WYMeditor works, because I'm going to try to copy/paste some code in here. I just had a little foray into my past with XSLT. I had 344 old blog posts (starting year 2000!) to convert from XML to SQL. Nothing better than XSL for the job! Here it is.

NB: I haven't restored images as of this writing.


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="no" omit-xml-declaration="yes" encoding="ASCII"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="ucletters">ABCDEFGHIJKLMNOPQRSTUVWXYZ- </xsl:variable>
<xsl:variable name="lcletters">abcdefghijklmnopqrstuvwxyz-_</xsl:variable>
<xsl:variable name="allowed_letters">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_ </xsl:variable>
<xsl:template match="/">
<xsl:text> USE `sw-blog-dev`;
</xsl:text>
<xsl:apply-templates select="weblog/entry"/>
</xsl:template>
<xsl:template match="entry">
<xsl:text>INSERT INTO `sw-blog-dev`.`posts` (`author_id`,`created_at`,`modified_at`,`permalink`,`title`,`synd_title`,`summary`,`body_raw`,`extended_raw`,`body`,`extended`,`is_active`,`custom_field_1`,`custom_field_2`,`custom_field_3`,`body_searchable`,`extended_searchable`,`text_filter`,`comment_status`) VALUES
</xsl:text>
<xsl:text> (2,</xsl:text> <!— author_id —>
<xsl:text>'</xsl:text><xsl:apply-templates select="date"/><xsl:text> 12:00:00',</xsl:text> <!— created_at —>
<xsl:text>'</xsl:text><xsl:apply-templates select="date"/><xsl:text> 12:00:00',</xsl:text> <!— modified_at —>
<xsl:text>'</xsl:text><xsl:apply-templates mode="PERMALINK" select="title"/><xsl:text>',</xsl:text><!— permalink —>
<xsl:text>'</xsl:text><xsl:apply-templates mode="XHTML" select="title/text()"/><xsl:text>',</xsl:text><!— title —>
<xsl:text>'</xsl:text><xsl:apply-templates mode="SYND_TITLE" select="content"/><xsl:text>',</xsl:text><!— synd_title —>
<xsl:text>'',</xsl:text><!— summary —>
<xsl:text>'</xsl:text><xsl:apply-templates mode="XHTML" select="content"/><xsl:text>',</xsl:text><!— body_raw —>
<xsl:text>'',</xsl:text><!— extended_raw —>
<xsl:text>'</xsl:text><xsl:apply-templates mode="XHTML" select="content"/><xsl:text>',</xsl:text><!— body —>
<xsl:text>'',</xsl:text><!— extended —>
<xsl:text>1,</xsl:text><!— is_active —>
<xsl:text>'',</xsl:text> <!— custom_field_1 —>
<xsl:text>'',</xsl:text> <!— custom_field_2 —>
<xsl:text>'',</xsl:text> <!— custom_field_3 —>
<xsl:text>'</xsl:text><xsl:apply-templates mode="TEXT_ONLY" select="content"/><xsl:text>',</xsl:text><!— body_searchable —>
<xsl:text>'',</xsl:text><!— extended_searchable —>
<xsl:text>'markdown',</xsl:text><!— text_filter —>
<xsl:text>1);
</xsl:text><!— comment_status —>
</xsl:template>
<!— must remember to backslash all single quotes —>
<xsl:template match="date">
<xsl:value-of select="translate(.,'/','-')" />
</xsl:template>
<xsl:template mode="PERMALINK" match="title">
<xsl:value-of select="substring(
translate(
translate(., translate(., $allowed_letters, ''), ''),
$ucletters,
$lcletters
),
0,42)"/>
</xsl:template>
<xsl:template mode="SYND_TITLE" match="content">
<xsl:call-template name="escapesinglequotes">
<xsl:with-param name="arg1"><xsl:value-of select="normalize-space( substring(.,0,42) )"/></xsl:with-param>
</xsl:call-template>
<xsl:text>...</xsl:text>
</xsl:template>
<xsl:template mode="TEXT_ONLY" match="content">
<xsl:call-template name="escapesinglequotes">
<xsl:with-param name="arg1"><xsl:value-of select="normalize-space(.)"/></xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template mode="XHTML" match="content">
<xsl:apply-templates mode="XHTML"/>
</xsl:template>
<xsl:template mode="XHTML" match="node()|@*">
<xsl:copy>
<xsl:apply-templates mode="XHTML" select="@*"/>
<xsl:apply-templates mode="XHTML"/>
</xsl:copy>
</xsl:template>
<xsl:template mode="XHTML" match="text()">
<xsl:call-template name="escapesinglequotes">
<xsl:with-param name="arg1"><xsl:value-of select="normalize-space(.)"/></xsl:with-param>
</xsl:call-template>
<xsl:text> </xsl:text>
</xsl:template>
<xsl:template mode="XHTML" match="@*">
<xsl:attribute name="{name()}">
<xsl:call-template name="escapesinglequotes">
<xsl:with-param name="arg1"><xsl:value-of select="normalize-space(.)"/></xsl:with-param>
</xsl:call-template>
</xsl:attribute>
</xsl:template>
<xsl:template name="escapesinglequotes">
<xsl:param name="arg1"/>
<xsl:variable name="apostrophe">'</xsl:variable>
<xsl:choose>
<!— this string has at least on single quote —>
<xsl:when test="contains($arg1, $apostrophe)">
<xsl:if test="string-length(normalize-space(substring-before($arg1, $apostrophe))) > 0"><xsl:value-of select="substring-before($arg1, $apostrophe)" disable-output-escaping="yes"/>\'</xsl:if>
<xsl:call-template name="escapesinglequotes">
<xsl:with-param name="arg1"><xsl:value-of select="substring-after($arg1, $apostrophe)" disable-output-escaping="yes"/></xsl:with-param>
</xsl:call-template>
</xsl:when>
<!— no quotes found in string, just print it —>
<xsl:when test="string-length(normalize-space($arg1)) > 0"><xsl:value-of select="normalize-space($arg1)"/></xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

Niiiiiiice.

The Quick and Easy Guide to moving your project from CVS to Subversion

Posted on March 05, 2007 at 12:00 PM

Categories: unix, code

So you want to use SVN? Fine, it's easy to move a project from one to the other.

Get cvs2svn

Go to a checked out copy of your cvs project and run cvs admin -kb filename on any binary files.

Commit to CVS.

Assuming that you've got a simple CVS project with no branches that you want to keep, do this:

./cvs2svn-1.5.1/cvs2svn —trunk-only -s project-name /path/to/cvsrepository/project-name mv project-name /path/to/svnrepository/ 

Camino ships 1.0

Posted on February 19, 2006 at 12:00 PM

Categories: links, code

I'm on an enforced work holiday which gives me lots of time to blog. So aside from a lot of work on the tagging system here at Simon Says , I've been going through old bookmarks and recent news as well. Here's a good one.

Camino (the best browser for OS X) reaches 1.0 :

The Camino Project is proud to announce the Camino 1.0 web browser, the culmination of four years of work by dedicated volunteers.

Designed exclusively for Mac OS X, Camino 1.0 is built on Mozilla’s Gecko rendering engine and offers one of the fastest browsing experiences available. The only browser available that combines the rendering power of Gecko with the Aqua user interface, Camino 1.0 offers superior integration with the Mac platform and a focused feature set. Among Camino’s signature features are elegant tabbed browsing, an enhanced bookmarks manager, and built-in ad-blocking.

I helped to write that announcement. Snappy eh? Anyway, my last major involvement was back in, er, let me consult my new tag browser ... 2004 when my history patch landed . I wrote a major improvement to the history panel, which was crap before that. It's still not perfect, but just after that I got awfully busy with Semacode.

However I was with the project during a rocky time in 2003/2004 when Apple launched Safari and it looked like the game might be up for Camino. But it's definitely not up. Camino is way better than Safari. It's faster, more attractive, renders better ... it's even more "mac-like" (however you want to say it). And the crowd now involved are clearly doing a good job. All around great news.

PS. The new website looks great . Also. I still administer the mailing list .

Bottlenose

Posted on September 15, 2005 at 12:00 PM

Categories: tech, code, mac

What do you get when you mix HTML, CSS, Javascript, Asynchronous Javascript, a web server, a web browser, interprocess communication, and native application views?

I was on "vacation" during August. I only got to have 5 days of "real" vacation because some stuff cropped up for work but I did do some sort of recreational programming. And I had this idea that seemed like a good idea, and my programmer buddies didn't immediately shoot it down as being completely stupid, so, I did up a demonstration in Objective-C and it's called Bottlenose.

Bottlenose is a way to enable graphic designers, and HTML/CSS/Javascript designers, to directly create the interface for a native application. Where a "native application" is something that runs right on the computer, like a work processor (not a web app, ASP, or applet).

I might have used pure java but (a) there's no good web browser API available for free and (b) Apple's WebKit is sooo easy to use and well documented. But still - Bottlenose could easily be ported to other platforms. In fact, I want to see it especially on Linux. Because I think that on Linux it could make a big improvement in the UIs if the graphics people could write it themselves. That is, after all, the Linux philosophy.

Anyway, I have this idea of running a contest to develop UIs for the demo that are better than the one I made. I'll probably even throw in a valuable prize of some sort (some books?) for the winner, and post all of the good entries.

If you have any comments at all, or think it's a good/bad idea, feel free to contact me .

The good CVS book

Posted on June 17, 2005 at 12:00 PM

Categories: links, code

There is one good online CVS guide and manual, and it's this one: Open Source Development With CVS . It's also a real book, and although the version I'm pointing you to may well be not the latest edition, it's still really, really good.

TELL THE WORLD! I was Mr. Marklar

Posted on June 06, 2005 at 12:00 PM

Categories: tech, meta, code, mac

OK, I've been waiting for four long, long years to tell you this. My "Secret Project" at Apple was Marklar aka OS X on x86, finally announced today! I'm not going to say today whether I think it's a good idea or a bad idea, or what, but I will say this. In 2001, my job at Apple was Program Manager for the Marklar project. When I started, Marklar was relatively moribund, being nursed by a handful of Core OS engineers. Lots and lots of new code had been introduced in OS X from the old Mac side, and new code written, since the last release of Rhapsody worked on Intel.

My job was to get the system working on x86 again and that's what I did. I traced dependencies like there was no tomorrow. I worked with engineers in a dozen different divisions, each time making first contact with the division manager, then finding just the right person for the job. Each time the same drill: "I'm going to tell you about a project that is Need To Know only. You can't tell anyone about this, even inside Apple. I'm not even going to tell you everything, just the minimum that you need to know in order for us to continue. If you're wondering who the hell I am and why you should listen to me, ask you manager who will just tell you to do it."

I went on leave in fall 2001 after the WTC thing, but by the time I left the Marklar team gave a demo to something like the top 100 managers of the company with a working Marklar system complete with Finder running and a whole range of apps. I kicked ass!

Obviously such an important part of my professional history, but until TODAY I haven't been allowed to breathe a word. A very SENSITIVE project, of all sensitive projects! But now, tell everyone, tell your friends!

Why Your Code Sucks

Posted on May 17, 2005 at 12:00 PM

Categories: code

It's so true .......

The best looking code I ever worked on was the BSD code from Mac OS X. Now that's what I call clean crisp code. OK, so the variable names were a bit cryptic, but they could be decoded once you got the hang of it (they were all very short..). The BSD people I've found out since are known wonks for good clean code.

These guys at Artima are pretty sharp. They're serious code geeks. I think they've talked a lot about refactoring, and if there's one new thing you've learned about coding in the 00's it's what is and how to refactor.

How to decompile and obfuscate in MIDP on OS X

Posted on April 21, 2005 at 12:00 PM

Categories: code, mac

OK, just some notes. To decompile any java jar, use something like this:

javap -c -classpath ./semacoderead.jar org.semacode.imagerec.Ecc200Decoder 

I'm using mpowerplayer on OS X to do my J2ME compiling, which makes things pretty easy, except that I want to use the ProGuard obfuscator. Obviously! You NEED to obfuscate if you've got code like mine (for semacode) that needs to be protected from reverse engineering which is SUPER easy with java. It's available from fink.

HOWTO develop Symbian apps using Mac OS X

Posted on April 03, 2005 at 12:00 PM

Categories: code, symbian

I just posted a HOWTO for building Symbian C++ apps on OS X. It's based on the previous HOWTO for OS X and Linux but heavily modified. My goal has always been to do everything on OS X and now I've achieved that goal. So, check out the link to see the howto and get going with Symbian dev on OS X already.

Unpack Nokia SDK 2.1 on Unix

Posted on January 21, 2005 at 12:00 PM

Categories: code, symbian

Ever wanted to install the Nokia Symbian Series 60 SDK on your Linux or Mac OS X box? Now... you can. Follow the link for details.

LINK

Installing UIQ on Linux / sdk2unix

Posted on January 17, 2005 at 12:00 PM

Categories: code, symbian

I've had these notes lying around for a while with the intention of fixing them up and making a proper how to. I never have. Maybe because my whole experience with UIQ was altogether less pleasant than S60 (basically, I just don't like it). Anyway, here are the notes in the form that I made them, some time in the fall of 2004.

- installed UIQ21 on windows 
- zipped it up
- transferred to linux
- got gcc539src.zip from symbian.com
- downloaded sdk2unix-1.2.tar.gz
- [target-directory] should be something like foo/bar/symbian/uiq
21 or foo/bar/symbian/6.1 for series 60 toolkit
- I ran sdk2unix installer and got this error: ### Configure, compile & install mkdir obj cd obj; sh ../src/configure —prefix=../uiq21 —target=arm-epoc-pe >/dev/null 2>&1 Unexcpected error: aborting.
- I ran that command without the redirect and found that a directory name was different from what the installer expected, the directory expected was "Documentation/Packages/UIQ
70" the actual name was "Documentation/Packages/UIQ2.1".
- the name change is probably the result of a patch I applied from Sony-Ericsson on the windows side
- solution: renamed the directory from UIQ
2.1 to UIQ70 - problem: rcomp says: "Failed to write UIDs"
- solution - rcomp.exe needs to find uidcrc.exe and can't. I can't figure out how to set WINEPATH to point to paths outside the fake windows directory. So I did - cp uidcrc.exe ~/.wine/fake
windows/Windows/
- in fact, I copied this from symbian/6.1/Tools because it's not even included in the uiq_21 distro!!
- see: http://www.freelists.org/archives/p900/02-2004/msg00009.html for a different solution
- genaif complains unless the .aifspec file is at least 2 lines apparently ......

my thresholding is getting pretty good

Posted on December 12, 2004 at 12:00 PM

Categories: graphics, code

My thresholding algorithm for semacode is getting pretty good I think. Check out these results on the classic "Barbara" computer graphics test image.

barbara

Next up we have my threshold of the image (adaptive, with an algorithm based on Chow and Kaneko, but the bimodal detector isn't as good as theirs)

barbara

Finally, by comparison, a threshold of the image by the person at this page . Mine is better in some places (like the fabric grain and the hand) but not as good in others (like the face).

barbara

(If you go there you can also see what you get with global threshold, which isn't as good.)

more symbian errata

Posted on July 18, 2004 at 12:00 PM

Categories: code, symbian

I'm now porting my Semacode DLL SDK over to windows so that I can build a WINS (emulator) library and DLL file. Needless to say there are some small hiccups. Here's one. I'm using Visual C++ .NET, which while it apparently works, is not like the standard. They still consider VC6 to be standard I think. So when I get this error:

LNK2019: unresolved external symbol __ftol2 

I'm in a bit of trouble. Fortunately I think I found the solution, which is ugly, but works. Go into the file C:Symbian6.1SharedEPOC32Toolscl_win.pm and search for the line that contains "/W4" and change it to this:

"CLFLAGS = /nologo /Zp4 /W4 /QIfist" 

(so basically add /QIfist to the options). So what's the problem. I guess that symbian's tools suck?

While I'm here, remember that cls will clear the scrollback buffer when you are in the fugly DOS shell.

XSLT code to create XML output from XML in an <xsl:variable>

Posted on July 04, 2004 at 12:00 PM

Categories: code, xml

Here's some code I just wrote in order to parse out XML from a string in XSLT. In XSLT, URL parameters are received in the string type. You can't just copy them into the output because they will be fully entity encoded. So, let's say you wanted to have a form field where someone could enter XHTML, and then you'd store that into an XML file. Of course you don't want to store <p>whatever...</p> into the file. So you have to actually process the incoming string and then create output XML elements as you go. In order to get you started here's some XSLT code that does an OK job of this:

It's pretty easy to call into, just do something like this:

<xsl:call-template name="parseXMLParam">
 <xsl:with-param name="input" select="$url_content"/>
</xsl:call-template>

... and that's about it. I think it should generally work for XHTML, but I think that it may fail if there are nested elements with the same name (e.g. a para inside a para) or nested loops of names. However as I said since that doesn't happen much in XHTML it should be useful for that at least.

more dll

Posted on June 04, 2004 at 12:00 PM

Categories: code

One of the programmers on #mobitopia was kind enough to build the simple, DLL-based guiengine example from the Nokia SDK for me on windows. I'm using it to test against my linux build. I copied all of the files (the .app, .rsc, and .dll) over to the phone and it works. Then I copied over my own .app file, built against the windows .lib, and that ALSO works. Yay! Now I see that my linux build isn't making the necessary .rsc file. Why not? Oops, that's my fault, when I took out the AIF file from the makefile I also removed the RSC. I just need to remember to copy the .rss file into the src directory next time. OK, I can make a .sis file for the application side of guiengine now on linux and it works OK.

Now I have built my own DLL from the same source but on linux. If I run strings on the .lib files I see some differences. I'm not sure yet what the differences actually are. In any case, I can build the .app against the linux .lib, install it on the phone with the windows .dll still in place, and it will run. However it crashes when I attempt to draw a shape (with KERN-EXEC 3).

Finally I have renamed C:/System/Libs/shapemanager.dll to Wshapemanager.dll and copied my own linux-built DLL into that directory. And I launch the app and it runs AND works. OK finally I have built I think a DLL that runs.

Here is the makefile for the DLL. Note that U1 and U2 must ALWAYS be those values for a DLL file. U3 and USIS3 should be the same.

EPOC=/home/simon/sandbox/sdk2unix/gcc-target PATH=$(EPOC)/bin:/usr/local/er6/bin:/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin include $(EPOC)/lib/makerules/dll TARGET=shapelistmanager U1 = 10000079 U2 = 1000008d U3 = 10005b7e USIS3 = 10005b7e OBJECTS=myshapelistmanager.o shape.o rectangle.o circle.o LIBS = $(EPOCTRGREL)/euser.lib  $(EPOCTRGREL)/estor.lib MTOP=\System\Libs CFLAGS+= -DHAVECONFIGH -I. -I../inc -I$(EPOC)/include/libc -DNOGLOBALS -O2 -DEPOC32 -DZLIB -Wall all:$(TARGET).sis -@mkdir -p s60 mv $(TARGET).sis $(TARGET).dll $(TARGET).Lib s60 $(TARGET).sis:$(TARGET).dll $(TARGET).pkg $(TARGET).dll:$(OBJECTS) $(TARGET).o $(TARGET).o: @echo > $(TARGET).o clean: rm -f $(GENERATED) $(TARGET).pkg: @echo "Making $(TARGET).pkg..." @echo '&EN' > $*.pkg @echo '#{"$(TARGET)"},(0x$(USIS3)),1,01,1,NC,TYPE=SISAPP' >> $*.pkg @echo '(0x101F6F88), 0, 0, 0, {"Series60ProductID"}'>> $*.pkg @echo "$(TARGET).dll"-"!:$(MTOP)\$(TARGET).dll" >> $*.pkg 

Here's my makefile for the app. These UID3 values, by the way, are from the example code.

EPOC=/home/simon/sandbox/sdk2unix/gcc-target PATH=$(EPOC)/bin:/usr/local/er6/bin:/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin include $(EPOC)/lib/makerules/eikon NAME=guiengine U1 = 1000007a U2 = 100039CE U3 = 10005b7d OBJECTS = guiengine.o guiengineappui.o guienginedocument.o  guiengineapplication.o guiengineappview.o LIBS=$(EPOCTRGREL)/apparc.lib  $(EPOCTRGREL)/avkon.lib  $(EPOCTRGREL)/cone.lib  $(EPOCTRGREL)/eikcore.lib  $(EPOCTRGREL)/estor.lib  $(EPOCTRGREL)/euser.lib  $(EPOCTRGREL)/ws32.lib  ../engine/s60/shapelistmanager.Lib #../../../fromwin/guiengine/shapelistmanager.lib TARGET=$(NAME).app PKGVERS=1,1 PKGFILES=$(NAME).app $(NAME).rsc # $(NAME).aif CFLAGS = -O -DNDEBUG -I. -I../inc -DUID3=0x$(U3) -DQUARTZ -DEPOC3261 -I$(EPOC)/include/libc CPPFLAGS += -DQUARTZ -DEPOC32_61 -I../inc all:$(PKGFILES) $(NAME).sis $(NAME).sis:$(NAME).app $(NAME).rsc $(NAME).pkg $(TARGET):$(OBJECTS) $(NAME).aifspec: echo "mbmfile=icon.mbm" >> $(NAME).aifspec echo "ELangEnglish=$(NAME)" >> $(NAME).aifspec semacode.o: $(NAME).rsc clean: rm -f $(GENERATED) $(NAME).aifspec 

dll madness

Posted on May 31, 2004 at 12:00 PM

Categories: code

I'm still trying to figure out how to build a DLL for symbian on Linux. sdk2unix didn't do it "out of the box" so I'm learning, learning, learning about how DLLs work, how symbian builds DLLs, etc. Here's one: if you include a DLL's lib stub file in your makefile, it still won't link to the .app unless you actually use something from the DLL in your source code.

all I need to know I learned from symbian.com

Posted on May 29, 2004 at 12:00 PM

Categories: code

such as what the heck all those different UIDs are for . Here's a quicko primer:

  • The first UID indicates the structure of the file
  • The second UID indicates the outermost "interface" provided by the file
  • The third UID indicates a particular instance of the object identified by the other two UIDs

So it sounds to me like: uid1=filetype, uid2=resourcetype, uid3=myuid. Or something like that.

Anyway, for a DLL, I think according to this and other docs I need to have: uid1=KDynamicLibraryUid=0x10000079, then uid2=KSharedLibraryUid=0x1000008d, then uid3=myownUID.

HOWTO develop Symbian apps using Linux and OS X

Posted on May 09, 2004 at 12:00 PM

Categories: unix, code, mac

I finished writing up my HOWTO on using Linux to develop for Symbian. Specifically, it covers Series 60 but the tools can be used for other variantions of Symbian as well.

daypop top 40 for semacode

Posted on May 06, 2004 at 12:00 PM

Categories: meta, links, code

semacode made it to the Daypop Top 40 Links today. We're number 18 right now. With an up arrow. And some green bars below. I have no idea what that means. But other people have blue and red bars and some gray ones. I think green is probably good.

Update: Made it as high as 15. daypop

The blue bars are your existing score. Red bars are a decrease since the last update. Green bars are a gain since the last update. I also caught "semacode" as a wordburst, in position 17. wordburst

semacode coverage

Posted on May 05, 2004 at 12:00 PM

Categories: links, code

I released semacode a few days ago. And it's been pretty well received so far. Here's a round up of the coverage.

Reiter's Camera Phone Report was first out of the block. I like Alan and his weblog so I put him in the first wave of announcement emails. He emailed me back with some questions which he added to the report. And my name is in the headline :-) Next up was Smart Mobs . I emailed Howard Rheingold but he must be busy because it was posted by someone else. Howard's been a fan from early on of the whole idea. Rafe at All About Symbian gave me a write up and posted a semacode for their site too.

The second wave had Boing Boing with a short write up. Probably most of today's hits came from there. It's a pretty popular site. Although I haven't actually checked yet. Also the story was picked up by TheFeature's Eric Lin which is cool because I like thefeature. And I didn't directly contact them myself so that's a good sign too. They also provided some highly accurate background info which was missing from other coverage so far. I was also contacted today by heise.de so we'll see if something comes from them. Since my site is still operational I'm assuming there's no /. link yet. So far AxKit is holding up just fine which is great.

A little bit more. Some linkage and commentary from MobileWhack : "Semacode is about as cool an app as I've come across ... You can be sure I'll be sporting the semacode equivalent of http://www.mobilewhack.com/ on the back of my scooter helmet—talk about mobile whackery." engadget has a story also.

grr

Posted on April 21, 2004 at 12:00 PM

Categories: code

I just spent like an hour debugging this stupid problem with a resource file for symbian. Turns out when you get this error:

<empty>(0) : Link name not found 

you have avkon.rsg included BEFORE avkon.rh. You need to include them in the OTHER order. At least now it will be in google.

symbian learning curve

Posted on April 05, 2004 at 12:00 PM

Categories: code

I feel like I may be slowly getting on top of the symbian programming API. One thing you have to do is enable the full error codes for leaves and exceptions. There's a SIS file you can download to turn it on (sorry I don't have the link on hand). Then you can look up the errors from untrapped leaves and the system panic codes . Oddly, the term "panic" is used for user level application crashes. These would usually I think be more accurately called exception codes.

Another useful thing I've discovered is the way to grab the current free memory (in bytes). You can do something like this:

TInt memoryfree; HAL::Get(HALData::EMemoryRAMFree, memoryfree); TBuf<99> msg; msg.Format( _L("Free memory is %d"), memoryfree ); RFileLogger::Write(LOG_DIR, LOG_NAME, LOG_MODE, msg); 

Useful eh? You'll need to include hal.h and hal_data.h and link hal.lib. Note that this is NOT well documented! There is a better documented call that does something similar but it's deprecated.

I wish the Symbian API had string support that was more ANSI C++ strings, or just char * strings. I haven't really figured out "descriptors" yet (even though I'm using them...).

programming for symbian (tips)

Posted on March 26, 2004 at 12:00 PM

Categories: code

Programming for symbian isn't very sexy. J2ME? That's sexy. But Symbian C++ is NOT sexy. First, at least in theory, you have to use Windows, and windows is NOT sexy. Two, it's C++, and frankly, although C++ may have had some sex-appeal in the mid-90s, it's all gone now. Three, it's poorly documented. What documentation exists is terse and seems to have been generated from header files. It rarely explains how to use the API. So for any kind of help understanding how to do it, you have to go to the examples, which are fairly limited. Next you can try NewLC: they have articles and forums . Next you might want to try searching the Forum Nokia discussion area . And finally, be sure not to miss the newsgroups. No, they're not archived anywhere on the web, which is a real pain. But you can access them through your favorite newsreader at publicnews.symbiandevnet.com . Only the NewLC postings are archived in google, which is a major hassle. There's also a small number of web pages and even some source code floating around on the web with some useful symbian C++ info. So there is some information out there, but you really need to dig to find it.

sdk2unix makefiles

Posted on March 22, 2004 at 12:00 PM

Categories: code

I think I'm travelling relatively untrodden turf with sdk2unix . So here's another thing I got hung up on and figured out. Probably someone with more makefile experience than I have would have got this instantly, but under OBJECTS you have to have applicationname.o FIRST or else it might not work. That's because the way it's set up, that particular rule will fire off the creation of the .rsg file which is some kind of generated resource file your source code needs or it won't build.

tracking down uninitialised data in sdk2unix

Posted on March 18, 2004 at 12:00 PM

Categories: code

If you're writing symbian C++ code you might get an error like this from petran:

ERROR: Dll 'MENUITEMS[10008AD0].APP'has uninitialised data. 

this page has a somewhat-adequate description of the problem, but you really should google for "bss segment" to find out what they're talking about. Since you can't build for symbian with this stuff in your code, you need to find and fix it. But the problem is, the error doesn't actually tell you what the offending code is. There's some stuff about .map files but they admit it won't show everything. Well I'll tell you what to do.

First off, you're looking either for an non-const global variable with no initialization e.g., int foo; or for a static local variable in a function. Now using sdk2unix add the following to your CFLAGS in the makefile: -save-temps This is the gcc flag that will save all of the intermediate files as it builds. Included is the .s files which I think are assembly language. grep these files for "bss"

grep -i "bss" *.s 

If you see one, less or more the file and have a look at what comes after the .bss directive. A few lines down should be the name of the offending variable.

If you're getting "has initialised data" the solution is probably similar but you need to look for the data segment.

fun with porting

Posted on March 14, 2004 at 12:00 PM

Categories: code

Today I ported the decoding porting of my semacode application from java to C++. As a part of the process I first went to ANSI C++, using C++ strings and couts to output to the console. Then, I make my own simple character buffer class and eliminated the C++ strings which aren't supported in Symbian. Symbian has it's own system of "descriptors" which are O-O and to my noviciate mind seem horrifyingly complex. So my software spits out its result as a simple char* C string.

Next I compiled and built the simple "helloworld" example from the nokia series 60 examples pack. It comes with the SDK. At the point where the code inserts the "Hello" literal I replaced it with a call to my decoder (which contains at this stage a test pattern). Then I turn the C-string result into a descriptor. As far as I can tell, there doesn't seem to be any API in symbian that will do this conversion for you (!!) although this page seems as though maybe it offers some hints. I can't tell. Anyway, a search in google found me this post on NewLC with some code that did the trick. I added my ported code to the helloworld code, installed the result and ran it and got a nice URL output on the screen.

sdk2unix for symbian on linux

Posted on March 07, 2004 at 12:00 PM

Categories: unix, code

After a week of messing around with windoze and linux toolkits, I finally did a successful build and run of an example app on my nokia 3650 using Symbian C++. Was it any of the toolkits I've already mentioned that I used? No, it was sdk2unix , a seemingly wonderful (hey it works!) distro by Rudolf Koenig and distributed at the Knowledge-Intelligence AG site (some kind of german company). They've got howto's for a bunch of symbian platforms, but note in particular the Series60 (SymbianOS 6.1) SDK on Linux/Unix HOWTO which is what I followed.

In addition to what they say there I would add the following notes:

  • It worked for me with the 1.2 nokia SDK (it's not clear that when the howto was written 0.9 was the latest)
  • when you run bin/install_gcc539 you must give absolute paths
  • target-directory is the same directory for both bin/install_gcc539 and bin/install_series60_sdk
  • you will have some minor troubles with case-sensitive names ... I just renamed directories that were expecting something different.

I had to do some hacking a little bit to make it all work .... I can't remember everything I did right now. I used Chris Davies'unpack-s60cppsdk to unpack the nokia SDK under linux. I found that when I went to 'make'in the series60ex/form example I had to fix the case of the include files in a bunch of .cpp files. (i.e., make them lowercase).

Overall I am VERY happy right now because this makefile system actually makes some sense. The bldmake and makmake and abld crap from symbian is just crap. So, hopefully this success with the example will be followed by me successfully writing my own little hello world program soon! :-)

gnupoc

Posted on March 06, 2004 at 12:00 PM

Categories: code

The project named GnuPoc a Symbian SDK for GNU/Linux. What is this? It purports to allow you to develop all your Symbian C++ code on linux. I installed it this week on a fresh debian system. Installation, I have to say, was not exactly trivial. There didn't seem to be any particular HOWTO that covered the Nokia 1.2 SDK very closely. I installed, configured, and built the series60ex/helloworld project finally, got the thing to generate a .sis file, installed it on my 3650 and... nothing. "System Error". That's all. So what gives? I have no idea.

Now I'm starting to wonder if anyone has ever used gnupoc for a 3650 as the target. Seriously. Because all of the recent examples on google are for Sony-Ericsson phones like the p800 and p900. Dunno why that is. But apparently at least one person has used it for 7650, which is basically the same phone as the 3650, so maybe there's some hope.

My camino history patch has landed

Posted on January 13, 2004 at 12:00 PM

Categories: code, mac

Mike Pinkerton, lead for Camino, just landed my history patch. This is my first major patch to go into Camino, it's about 1000 lines of code changes or so. It fixes the history view so that you get to see a flat, time-ordered listing with daily folders.

FTXSaver alpha 4

Posted on January 12, 2004 at 12:00 PM

Categories: code, mac

I just posted another alpha of the screen saver. This one fixes the anti-aliasing problem and adds a requested feature to speed up colour animation. Get it here.

I also posted some new gallery images. It really doesn't compare to seeing the thing in operation, but maybe you can get a taste for what it looks like. See more.

By the way the nifty gallery widget is AxKit::App::Gallery by Nik Clayton. It caches the thumbnails at smaller sizes to give the downloads a break, and it generates them automatically as well, so less work for me.

screen saver with openGL

Posted on December 27, 2003 at 12:00 PM

Categories: code, mac

Do you have Mac OS X? Download my screen saver . It's powered by OpenGL. It draws about 60 000 primitives per second now on my machine. I suppose to make it any faster now I'd have to look at the math logic and method passing. Also in this version is the option to draw points instead of lines. It's on by default because I think it looks better.

My first screensaver

Posted on December 18, 2003 at 12:00 PM

Categories: code, mac

I just released my first ever screensaver. Get it here .

new FractalTreesX

Posted on December 17, 2003 at 12:00 PM

Categories: code, mac

I just released a new version of FractalTreesX . It's a total alpha, complete with loads of bugs and some very odd behaviour when the size of the tree changes, but it's a LOT faster. I think it's probably about 3-4 orders of magnitude faster now. And the code is completely rewritten and I am MUCH happier about that. I would even say go and read it, because it's pretty good looking. I removed the total spaghetti that someone (initials are MYI...) told me was a good way to do it and replaced it with a nice simple multithreaded engine.

credit me

Posted on October 23, 2003 at 12:00 PM

Categories: code, mac

My Camino bookmarks patch .

Check out the link. You'll see "thanks to ... simon woodside". I did ton of work on this bookmarks patch. I won't go into the gory details, maybe in a few years. One problem with being a "program manager" (ala Apple and Microsoft) is that you can't take much credit for what you do. Mostly it's "glue" work and we all know how much credit glue gets. I do like to get credit for what I do. So, in that sense, the program manager type role is kind of unfulfilling.

I don't know really what to do about that. The individuals who I work with / have worked with I think fully appreciate what I do/did as a program manager. And I say "did" because this most recent experience kind of nudged me away from taking on that kind of job again. On the other hand, it's cool to see Camino moving again. I think I played a fairly central role in that.

Alexandra thoughts

Posted on October 01, 2003 at 12:00 PM

Categories: code, xml

After the first release of Alexandra, I discussed with several people a major flaw, which was that it did not preserve the RNG order as given in the schema when it added or changed elements. I was concerned I would need to use some sort of database update-type scheme. I wasn't keen on this as the only xml update project that seemed to be anywhere near a state of completion was XUpdate and it wasn't very complete, and also seemed like a hassle. I realized later that I could generate XSLT to do the update. More recently I was working on how to pass through the positioning information for both elements that are already instantiated and ones that aren't. I seem to have that completed now. So, at this point I believe it is possible to generate only RNG-valid instances using alexandra.

AxBlog 0.2

Posted on August 31, 2003 at 12:00 PM

Categories: meta, code

An update of AxBlog to what I use currently here and on openICT and semacode.org

Camino

Posted on August 03, 2003 at 12:00 PM

Categories: code, mac

I'm involved in the Camino project for Mozilla. It's a pretty face for the Gecko engine basically. Recently the whole Mozilla project was transferred to a new foundation. Mike Pinkerton was moved to a different job at AOL but he's got the nightly builds going again and I've been testing out David Haas' rewrite of the bookmarks manager. Looks good so far. It includes some novel features that I think might be cool, like a top-ten list, and Address Book integration. Could you manage all your bookmarks in the Address Book?

New computer and Camino

Posted on July 21, 2003 at 12:00 PM

Categories: code, mac

Got myself a new computer now. The old one was getting pretty old (2 years old almost exactly) and sloooooowwww and not enough disk space. I was actually at the point where I had to build mozilla on the other computer because I didn't have enough space. Now I've got 60 GB of space, and a nice new faster 1 GHz processor and some other nifty unexpected benefits like more pixels on the screen (although the size didn't change) and some other stuff. I think the battery lasts longer.

Anyway in the last day I've been dealing with the usual environment having to get my environment installed properly again. Camino needs glib which I didn't have installed from fink and it wasn't on the list, so I wasted a day building camino and then trying to get it to recognize that I had actually installed glib. I wound up deleting the configure output files by hand because the new camino.mk doesn't seem to clean them automatically.

And stuff.

FTX on 10.1.5

Posted on October 07, 2002 at 12:00 PM

Categories: code, mac

Circumstantial evidence (in the form of emails from users...) indicates that FTX 1.5 didn't work very well on Mac OS X 10.1.5. Well, that's what I get for upgrading all of my computers to 10.2. However with me making fixes and sending off test copies to the helpful users, it seems I've squished the bugs for now. Hence the updated FractalTrees 1.5.1 release. Oh yeah, and it's open source software now too ;-)

FTX 1.5

Posted on October 01, 2002 at 12:00 PM

Categories: code, mac

Check out the Fractal Trees section of the site for a new version of FractalTrees X . The new version 1.5 is lots more fun to play with. Written in the only practical GUI application environment, Cocoa.