Year: 2005

  • Google Talk

    (23:13:21) gmail.com: The broken link has been fixed. Thanks for being our first users!

    Let the talk begin! I used these instructions for Gaim to get online last night after Russ popped on and let me know that all the cool kids were using Google Talk.

    Per usual the official client is Windows only, but since they’ve done the smart thing and used XMPP (Jabber), you can point just about any client at it and away you go. The setup (at least in Gaim) is a bit non-standard, but it works.

    I really want to sniff some packets on a windows box to see how they’re integrating the VOIP stuff over XMPP. Hopefully they’ve done the right thing again and are using SIP.

    Update: At this time it looks like Google does not provider any server to server connections and (to my knowledge) no gateways to the outside world. Please stay within the walled garden, and don’t stand on the grass. This seems to contradict a lot of the “user choice” and “open communication” bits scattered throughout the rest of the page.

    Their developer FAQ is interesting though. They’re using custom XMPP signalling to a soon-to-be-documented peer-to-peer chat protocol that just happens to work with iChat. They support a bunch of protocols too and are thinking about speex too.

    It looks like their first connections with the outside world will be federations with Sipphones Gizmo project and EarthLink’s Vling services. There’s no GoogleOut or GoogleIn at this time.

    You can find me at first initial last name (all one word) at gmail dot com.

  • Mono on ARM

    Thanks to ljl for pointing this out in #maemo:

    People may be interested to know that the initial pass at the JIT port to ARM is in svn.
    make test in mono/tests reports 123 pass, 70 fail.
    Most of the regression tests in mini/ work as well.

    Nice! There are still some hurdles to be overcome, but this is great news.

  • Cingular’s 6682 Pricing

    Take a peek at Darla’s blog if you’re curious about Cingular’s pricing of the Nokia 6682 both on and off contract. While I hope that Lets Talk or Amazon can do just a little bit better, but this is definitely a step in the right direction if indeed the picture is legit (which I’ll bet it is).

  • My New Class 1 Bluetooth Dongle

    I’ve had a trusty low power Bluetooth dongle for a couple of years now, but I jumped on the opportunity to pick up a Hawking Tech HBTC1 Class 1 adapter for $10 after rebates at CompUSA. I wasn’t able to determine on the taco if this puppy worked with Linux or not, but I decided that It would be useful even if it didn’t for $10.

    Unfortunately the definitive listing of Bluetooth devices that work under Linux with BlueZ has been taken off the air:

    Whether or not you’re selling them makes no difference. The problem is due to the distribution of them from your Web site. Please note that the use and distribution of non-qualified products is a violation of the Bluetooth License Agreement. As neither of these products have been qualified using Linux it is illegal to make them available for public use.

    Total bummer. For the time being anyway you can find the list thanks to The Internet Archive. My Hawking tech device wasn’t listed, but I can assure you that at least hcitool scan works just fine.

  • Newcomers to the Bookshelf

    Newcomers to my bookshelf

    Several new books have landed on to my bookshelf recently and I thought I’d take a minute to highlight them:

  • Nokia N70 Gets FCC Approval

    I went trawling the FCC website looking for dirt on the latest devices and their FCC approval status this morning when I stumbled across this one: The FCC has approved the N70 from Nokia UK. Take that at face value folks, it just means that the N70 is appoved for sale in the US, not that any carrier has picked it up for mass dispersal. It is a good sign though that progress is being made on the N70, and increases the chances of us seeing the N70 en masse slightly above the magic 8 ball saying “DON’T COUNT ON IT”.

    Still, it’s quite an interesting development!

  • Nokia 6682 Real Soon Now?

    MobileTracker mentioned that there’s a print ad for the 6682 in this month’s Wired (on page 71 of my copy). They’re jumping to the conclusion that the ad along with images of the 6682 stealthily existing on Cingular’s web server are imperical evidence that the 6682 is shipping Real Soon Now.

    I’m pretty skeptical at this point. This ad looks identical to one that was seen in another magazine sometime in July and it’s late August now. While I remain hopeful that the 6682 will ship sooner rather than later, I wouldn’t be suprised if it didn’t see the light of day until September or even October.

    The best unsubstantiated rumours by far are on this Howard Forums thread: Nokia 6682 Coming in July? It’s on something like page 39 now.

  • Hula Visual Upgrade

    Nat shows off the sexy new interface to Hula. The screencast looks quite impressive. Hula has definitely come a long way in a short time, even though it was an awesome little project when it was released as open source.

  • The Scourge of the iPod

    This weekend I went in search of an FM modulator to finish hooking up a Delphi Roady2 to the parental minivan (yes my parents have XM. Can anyone say tipping point?). A few years back you used to be able to walk in to a Best Buy or Radio Shack and pick up a crappy little FM modulator for $15-20 or so. I mean, it’s not rocket science. Audio in and a small FM transmitter. After The iPid Revolution however, every freaking FM modulator on the shelf costs like $50 and the vast majority of them are iPod white.

    Don’t get me wrong, I’m glad that the iPod in all its variations and those other mp3 players are so dang popular. The inner gadget geek in me loves that. But the iPod economy is killing me with the acccessory inflation.

    I really am amazed that people get away with charging so much for a hunk of plastic, an audio cord, a case, or the million other overpriced widgets that you can attach to your mp3 player of choice. My only hope is that the iPod bubble can’t last forever.

    Update: Okay, I managed to find the Belkin Tunecast II, which was the one I liked in the store for about half that on Amazon. Not so bad after all. The stuff is still overpriced on the shelf though.

  • Why I Miss CrashRecovery

    Session Saver

    CrashRecovery never treated me like this. SessionSaver never was able to recover from this happy fun loop. Then again, it has worked correctly almost all of the other times, so I really shouldn’t be complaining.

  • Django Generic Views: CRUD

    Note: I’ve not yet updated this to reflect the new model syntax. For the time being you can take a look at the new model syntax for tasks here.

    There are lots of gems buried in Django that are slowly coming to light. Generic views and specifically the CRUD (create, update, delete) generic views are extremely powerful but underdocumented. This brief tutorial will show you how to make use of CRUD generic views in your Django application.

    One of my first encounters with Rails was the simple todo list tutorial which managed to relate lots of useful information by creating a simple yet useful application. While I will do my best to point out interesting and useful things along the way, it is probably best that you be familiar with the official Django tutorials. Now would also probably be a good time to mention that this tutorial works for me using MySQL and revision 524. Django is under constant development, so things may change. I’ll do my best to keep up with changes.

    Getting Started

    As with all Django projects, the best place to start is to start with django-admin.py startproject todo. Make sure that the directory you created your project in is in your PYTHONPATH, then edit todo/settings/main.py to point to the database of your choice. Now would be a good time to set your DJANGO_SETTINGS_MODULE to "todo.settings.main". Next move to your apps/ dir and create a new application: django-admin.py startapp tasks and django-admin.py init. The initial setup process is covered in much more detail in tutorial 1.

    The Model

    Now that we have the project set up, let’s take a look at our rather simple model (todo/apps/tasks/models/tasks.py):

    from django.core import meta
    
    # Create your models here.
    
    class Task(meta.Model):
      fields = (
        meta.CharField('title', maxlength=200),
        meta.TextField('description'),
        meta.DateTimeField('create_date', 'date created'),
        meta.DateTimeField('due_date', 'date due'),
        meta.BooleanField('done'),
      )
    
      admin = meta.Admin(
        list_display = ( 'title', 'description', 'create_date', 'due_date', 'done' ),
        search_fields = ['title', 'description'],
        date_hierarchy = 'due_date',
      )
    
      def __repr__(self):
        return self.title

    The model is short and sweet, storing a title, description, two dates, and if the task is done or not. To play with your model in the admin, add the following to INSTALLD_APPS in todo/settings/main.py: 'todo.apps.tasks',

    Feel free to play around with your model using the admin site. For details, see tutorial 2.

    URL Configuration

    Now let’s configure our URLs. We’ll fill in the code behind these URLs as we go. I edited todo/settings/urls/main.py directly, but you’re probably best off decoupling your URLs to your specific app as mentiond in tutorial 3.

    from django.conf.urls.defaults import *
    
    info_dict = {
      'app_label': 'tasks',
      'module_name': 'tasks',
    }
    
    urlpatterns = patterns('',
      (r'^tasks/?$', 'todo.apps.tasks.views.tasks.index'),
      (r'^tasks/create/?$', 'django.views.generic.create_update.create_object',
      dict(info_dict, post_save_redirect="/tasks/") ),
      (r'^tasks/update/(?P<object_id>\d+)/?$',
      'django.views.generic.create_update.update_object', info_dict),
      (r'^tasks/delete/(?P<object_id>\d+)/?$',
      'django.views.generic.create_update.delete_object',
      dict(info_dict, post_delete_redirect="/tasks/new/") ),
      (r'^tasks/complete/(?P<object_id>\d+)/?$',
      'todo.apps.tasks.views.tasks.complete'),
    )

    Note: I had to alter the formatting of the urlpatterns in order to make them fit. It looks a lot better in its original formatting.

    We use the info_dict to pass information about our application and module to the generic view handlers . The CRUD generic views need only provide these two pieces of information, but some generic views need more. See the generic views documentation for an explanation.

    Let’s look at each of these URLs one at a time, along with the code behind them.

    Index

    (r'^tasks/?$', 'todo.apps.tasks.views.tasks.index'),

    This points to our index view, which is an index function in todo/apps/tasks/views/tasks.py:

    from django.core import template_loader
    from django.core.extensions import DjangoContext as Context
    from django.utils.httpwrappers import HttpResponse, HttpResponseRedirect
    from django.models.tasks import tasks
    from django.core.exceptions import Http404
    
    def index(request):
      notdone_task_list = tasks.get_list(order_by=['-due_date'], done__exact=False)
      done_task_list = tasks.get_list(order_by=['-due_date'], done__exact=True)
      t = template_loader.get_template('tasks/index')
      c = Context(request, {
        'notdone_tasks_list': notdone_task_list,
        'done_tasks_list': notdone_task_list,
      })
      return HttpResponse(t.render(c))

    This view creates two lists for us to work with in our template, notdone_tasks_list is (not suprisingly) a list of tasks that are not done yet. Similarly, done_tasks_list contains a list of tasks that have been completed. We will use the template tasks/index.html to render this view.

    Make sure that you have a template directory defined in todo.settings.main (this refers to todo/settings/main.py). Here’s mine:

    TEMPLATE_DIRS = (
     "/home/mcroydon/django/todo/templates",
    )

    Now let’s take a look at the template that I’m using for the index:

    {% if notdone_tasks_list %}
        <p>Pending Tasks:</p>
        <ul>
        {% for task in notdone_tasks_list %}
            <li>{{ task.title }}: {{ task.description }} <br/> 
              Due {{ task.due_date }} <br/> 
              <a href="/tasks/update/{{ task.id }}/">Update</a> 
              <a href="/tasks/complete/{{ task.id }}/">Complete</a>
            </li>
        {% endfor %}
        </ul>
    {% else %}
        <p>No tasks pending.</p>
    {% endif %}
        <p>Completed Tasks:</p>
        <ul>
    {% if done_tasks_list %}
        {% for task in done_tasks_list %}
            <li>{{ task.title }}: {{ task.description }} <br/> 
              <a href="/tasks/delete/{{ task.id }}/">Delete</a>
            </li>
        {% endfor %}
        </ul>
    {% else %}
        <p>No completed pending.</p>
    {% endif %}
    <p><a href="/tasks/create/">Add a task</a></p>

    Don’t let this index scare you, it’s just a little bit of logic, a little looping, and some links to other parts of the application. See the template authoring guide if you have questions. Here’s a picture to give you a better idea as to how the above barebones template renders in Firefox:

    Tasks thumbnail

    Create Generic View

    Now let’s take a look at the following URL pattern:

    (r'^tasks/create/?$', 'django.views.generic.create_update.create_object', dict(info_dict, post_save_redirect="/tasks/") ),

    There’s a lot of magic going on here that’s going to make your life really easy. First off, we’re going to call the create_object generic view every time we visit /tasks/create/. If we arrive there with a GET request, the generic view displays a form. Specifically it’s looking for module_name_form.html. In our case it will be looking for tasks_form. It knows what model to look for because of the information we gave it in info_dict. If however we reach this URL via a POST, the create_object generic view will create a new object for us and then redirect us to the URL of our choice (as long as we give it a post_save_redirect).

    Here’s the template that I am using for tasks_form.html:

    {% block content %}
    
    {% if object %}
    <h1>Update task:</h1>
    {% else %}
    <h1>Create a Task</h1>
    {% endif %}
    
    {% if form.has_errors %}
    <h2>Please correct the following error{{ form.errors|pluralize }}:</h2>
    {% endif %}
    
    <form method="post" action=".">
    <p><label for="id_title">Title:</label> {{ form.title }}
    {% if form.title.errors %}*** {{ form.title.errors|join:", " }}{% endif %}</p>
    <p><label for="id_description">Description:</label> {{ form.description }}
    {% if form.description.errors %}*** {{ form.description.errors|join:", " }}{% endif %}</p>
    <p><label for="id_create_date_date">Create Date:</label> {{ form.create_date_date }}
    {% if form.create_date_date.errors %}*** {{ form.create_date_date.errors|join:", " }}{% endif %}</p>
    <p><label for="id_create_date_time">Create Time:</label> {{ form.create_date_time }}
    {% if form.create_date_time.errors %}*** {{ form.create_date_time.errors|join:", " }}{% endif %}</p>
    <p><label for="id_due_date_date">Due Date:</label> {{ form.due_date_date }}
    {% if form.due_date_date.errors %}*** {{ form.due_date_date.errors|join:", " }}{% endif %}</p>
    <p><label for="id_due_date_time">Due Time:</label> {{ form.due_date_time }}
    {% if form.due_date_time.errors %}*** {{ form.due_date_time.errors|join:", " }}{% endif %}</p>
    <p><label for="id_done">Done:</label> {{ form.done }}
    {% if form.done.errors %}*** {{ form.done.errors|join:", " }}{% endif %}</p>
    <input type="submit" />
    </form>
    <!--
    This is a lifesaver when debugging!
    <p> {{ form.error_dict }} </p>
    -->
    
    {% endblock %}

    Here’s what the create template looks like rendered:

    Create Tasks

    If we fill out the form without the proper (or correctly formatted) information, we’ll get an error:

    Create Tasks

    Update

    (r'^tasks/update/(?P<object_id>\d+)/?$', 'django.views.generic.create_update.update_object', info_dict),

    This URL pattern handles updates. The beautiful thing is it sends requests to tasks_form.html, so with a little logic, 90% of the form can be exactly the same as the create form. If we go to /tasks/create/, we get the blank form. If we visit /tasks/update/1/ we will go to the same form but it will be prepopulated with the data from the task with the ID of 1. Here’s the logic that I used to change the header:

    {% if object %}
    <h1>Update task:</h1>
    {% else %}
    <h1>Create a Task</h1>
    {% endif %}

    So if there’s no object present, we’re creating. If there’s an object present, we’re updating. Same form. Pretty cool.

    Warning: It looks like form.create_date_date and form.create_date_time have broken between the time I wrote this and wrote it up. This form will not prepopulate the form with the stored information. There’s a ticket for this, and I’ll update as neccesary when it has been fixed.

    Delete

    Here’s the URL pattern to delte a task:

    (r'^tasks/delete/(?P<object_id>\d+)/?$', 'django.views.generic.create_update.delete_object', dict(info_dict, post_delete_redirect="/tasks/new/") ),

    There’s another little Django gem in the delete function. If we end up at /tasks/delete/1 using a GET request, Django will automatically send us to the tasks_form_delete.html template. This allows us to make sure that the user really wanted to delete the task. here’s my very simple tasks_form_delete.html template:

    <form method="post" action=".">
    <p>Are you sure?</p>
    <input type="submit" />
    </form>

    Once this form is submitted, the actual delete takes place and we are redirected to the main index page (because we set post_delete_redirect.

    CRUD Generic Views And the Rest of Your Application

    That pretty much covers the basics of the CRUD generic views. The great thing about generic views is that you can use them along side your custom views. There’s no need to do a ton of custom programming for list/detail, date-based, or CRUD since those generic views are available to you. Because we set up our URL patterns, we can make sure that we craft URLs that look pretty and make sense.

    For my sample tasks application I decided that I wanted to create links that would immediately set a task as complete and then redirect to the index. This is pretty much trivial and can be accomplished by adding the following URL pattern and backing it up with the appropriate view. Here’s the pattern:

    (r'^tasks/complete/(?P<object_id>\d+)/?$', 'todo.apps.tasks.views.tasks.complete'),

    And here’s the view that goes along with it (from todo/apps/tasks/models/tasks.py):

    def complete(request, object_id):
      try:
        t = tasks.get_object(pk=object_id)
      except:
        # do something better than this
        raise Http404
      try:
        t.done=True
        t.save()
        return HttpResponseRedirect('/tasks/')
      except:
        # do something better than this
        raise Http404

    I do plan to actually handle errors and respond accordingly, but it was late last night and I just wanted to see it work (and it does).

    Conclusion

    Django rocks. Generic views rock. The framework and specifically the generic views make your life easy. My little tasks app took a few hours to put together, but a significant portion of that was reading up on the documentation, trying to figure out generic views using the existing docs and reading the source, and of course pestering the DjangoMasters about generic views and other stuff on #django (thanks all).

    I hope this overview of CRUD generic views helps, but if anything confuses you, don’t hesitate to comment or get in touch with me (matt at ooiio dot com). Also expect to see updates to this tutorial as APIs change and I get a little more time to clean up my code.

    Feel free to download and play with my little todo app: todo-tutorial.tar.gz or todo-tutorial.zip. Consider them released under a BSD-style license. Above all, don’t sue me.

  • KJS Java Script Engine for Symbian

    I don’t know how I missed this the other day, but in today’s Forum Nokia newsletter (among other things) there is a link to the KJS Java Script Engine for Symbian OS which is based on the JS component of Apple‘s open source WebCore. It’s definitely hardcore, pretty much a source drop, but it’s proof that we’re well on our way to having WebCore in our pockets.

  • Rob Curley Blew My Mind

    A few days back I listened to this IMA Keynote by Rob Curley on IT Conversations. It blew my mind. I started out looking for some insight in to the team behind Django, The Lawrence Journal-World, lawrence.com, and so on. I got a whole lot more than I had bargained for.

    If you’re involved in old media, new media, any media, or just want a glimpse of the future (I hope), please have a listen. It will be very interesting to see what happens in the next few months as Django takes flight, Rob heads to Naples (with technical backup from Eric) and Adrian telecommutes to The Washington Post

  • Nokia Smartphone Hacks

    Smartphone HacksI stumbled upon Nokia Smartphne Hacks by Michael Yuan (with foreword by Christian Lindholm) while windowshopping for books yesterday. It looks like a great book for people with a Smartphone wondering what cool stuff they can do with it. The tin cans on the cover rule. The hacks themselves are quite useful since there are so many gems buried away in these little devices. I have to admit that I knew about most of these hacks before, but there are always gems buried in these devices that you didn’t know about. I’m also far from your average smartphone user, so many people that pick up this book will find it interesting, useful, and inspiring. If you’ve got one of them there Nokia smartphones and are wondering what else you can do with it, check out this book.

  • Scuttle the Shuttle?

    It may be painful to be left without a means for Americans to get in to space (aside from bumming a ride on a Soyuz), but something needs to be done and quick. I would hate to see the shuttle fleet mothballed immediately, but that might just be the best thing for space travel in general. This AFP story on Yahoo! News puts in to words a lot of thoughts I’ve been having about the shuttle program lately.

    At this point in the game plan we’re going to be without our own means in to space between 2010 when the shuttle program finally expires and 2014, the earliest that I could imagine the CEV and cargo carriers might be ready. Here’s what NASA engineer Homer Hicham has to say:

    “The space shuttle is … never going to be reliable no matter how much money, time and engineering careers your throw at it. Let’s put the shuttle on the shelf right away and give engineers the gift of designing new ships to carry humans into space,” he said

    The current next-gen plan seems like a duct tape solution, but given the time and budget restraints I don’t see an alternative. All of this stuff is a total downer for a sci-fi geek like me, and I’m just hoping that China announces serious plans to put a man on Mars by 2020. Short of something like that I don’t see us taking space exploration very seriously at all.

    *Sigh*

  • Don’t Ask if You’re Not Going to Use It

    I was impressed that Matan had managed to get Bochs running on the PSP and thought I’d spread the word a little bit. I hopped over the Engadget and filled out their hot tip form.

    Engadget form

    They didn’t pick up on it last night so I thought they were going to take a pass on it. Lo and behold, they posted about it this morning. I checked it out hoping for a Thanks, Matt link, but no love.

    That kinda bums me out. I wasn’t expecting credit for the tip, but when I saw we’ll give you credit for the assist I thought that was pretty cool. Don’t get me wrong, I’ll still look towards Engadget and others for my tech fix, but I can’t help but feel that they’re not keepin’ it real.

    Update: Hey thanks for the comment, Peter. I had a feeling that it had just fallen through the cracks or something. My bummed out thoughts have been more than cancelled out by the fact that he found his way to this lil’ ol’ blog and left a comment.

  • Bochs on the PSP

    Bochs on PSP

    Matan Gillon (Zi` to us in #mobitopia) has just released Bochs for the PSP. He has successfully run Windows 95 and command line Linux under Bochs on his PSP. It may not be zippy, but the sheer fact that it runs at all is amazing:

    Windows 95 actually runs quite well but don’t expect it to be a speed demon. It takes about 10 minutes to boot but afterwards it’s pretty usable. I was able to do things like: open “My computer” and browse the virtual hard drive, complete a whole game of Minesweeper and run various other applications. Now you too can get your Minesweeper fix on the go 🙂

  • The Enchanted Forest Lives On

    Enchanted Forest

    When I was a kid it was a real treat to make the (seemingly) long journey from Kensington to The Enchanted Forest in Ellicott City. The Enchanted Forest was a storybook theme park with rides, storybook displays, and a lot of stuff that was just magical when I was a child. These pictures take me back. Years later I was bummed to hear that it had closed down. Today there is a shopping center and parking lot covering part of the old grounds, though some of the original signage and the entrace castle remain.

    My heart was warmed when I read an article in The Baltimore Sun (registration probably required) about bits and pieces of the old amusement park being resurrected down the street at Clark’s Elioak Farm. They’re having a big party this weekend to celebrate the 50th anniversary of the park.

    I can’t tell you how much all this brings me back to my childhood. I might try to head out to the farm over the weekend to relive it a bit more and take some pictures.

  • Microcapital

    Very smart things are happening at Y Combinator. Marc at O’Reilly Radar writes:

    But what I will say is, what a great idea and a great program. At least half of the startups in the program are seriously cool and all of them made a ton of progress on very little money and in very little time.

    A little bit of funding and guidance at such an early stage has got to be a huge boost to people looking for the next big thing. While Reedit doesn’t do a lot for me, I know that whatever Aaron is working on is going to kick some major butt.

    I have a feeling that we’ll see more early microfunding ala Y Combinator in the near future, there’s such an obvious need for it. You can’t get everything right, but it will be interesting to look back at the class of Summer 2005 in a few years to see what works out and what tanks.

  • You Know Your Programming Language is Complicated When

    Java in a NutshellThis is an exercise best done at a brick and mortar bookstore. First, find yourself the Java section. Then locate the 5th edition of Java in a Nutshell, newly revised for Java 1.5. Take a close look at it. Thick, isn’t it? Now pick it up. Note that it weighs 3.2 pounds. Now thumb through it, all 1264 pages. That’s a bunch of pages.

    With apologies to Jeff Foxworthy, your programming language just might be complicated when you have trouble telling the difference between its Nutshell book and a telephone book.