Wednesday, December 24, 2008

Where the computer ends and the entertainment center begins

A little incident with my nine year old son got me to thinking a bit about how we define computers in our lives and how we interact with them on different levels. There has been a lot of scholarly talk about exactly this, and I'm not really adding anything to the discussion except a tidbit of personal experience. Still, perhaps this thought will get you thinking a bit, too.

First, the story:

Yesterday, the aforementioned nine year old boy was playing his favorite online game.* A certain incident inside the game bubbled over, and my boy completely lost his cool. From my work spot in my bedroom I heard him pick up the keyboard and slam it on the desk. So, I told him to get off the computer and then I banned him from the computer for the rest of the day plus all of today.

Now, let me explain something before I go on. I have a theory of discipline which is very clear. Punishments should, whenever possible, be directly related to the deeds that brought them on. So, when he behaved inappropriately with the computer, my response was simple. No more computer for a period of time. The end. That didn't mean that we couldn't go watch a movie last night, or have other fun. But the computer was lost to him.

However, and heres where the story turns into a philosophical discussion about technology, at this very moment he is watching the Nightmare Before Christmas in the living room.

So what, right? I just said that being banned from the computer didn't mean that he was banned from TV. Well... we don't have a TV per se. Well, we do. The big monitor that we watch movies and serial shows on is, in fact, a TV as well as a monitor. But, we don't use it to connect to the airwaves or to cable TV or to satellite TV. The TV is just a monitor, connected to the desktop computer in the living room. So, my son is watching a movie on the computer.

Is that OK?

Yes, I think it is. I wasn't really banning him from watching shows, like I said before. I also wasn't banning him from listening to the radio. (We also get our "radio" from sites like last.fm) What I really banned him from was using the keyboard and mouse to interact with the computer. I banned him from games and web browsing and story writing on the computer. I set up the movie and hit play, so it's OK.

I wonder if, 20 years from now, I would still have the same approach. I mean, will I still think of the passive forms of entertainment as being different and separate from the computer itself? Will I still think of the computer in terms of its specific uses? Or will I think of it as just being "the computer", whatever I'm doing? I think I know the answer to that.

Despite the fact that devices are converging, mixing multiple, sometimes highly specialized uses into a single gadget, 20 years from now we'll be defining the machines based on their uses not based on the amorphous concept of "computer".

We don't generally think of our cell phones as computers, but they definitely are, and they are becoming more and more PC-like every day. My phone is a camera. It's better than many standalone digital cameras out there with it's 5 megapixel images, automatic or manual focus and zoom, digital video at regular frame rates or 120fps for slow motion video... But my phone is really a computer above all else. If you had any doubt whatsoever, the built in video editing software right on the phone should clue you in.

More and more of us have multiple desktop and/or laptop computers in the house, but far more people have multiple computers in the home and don't even realize it. Whether those computers come in the form of phones or cameras or kitchen gadgets or even computerized heating and air conditioning systems.

In Star Trek, the ship is the computer, and whether you realize it or not, we're there already. Your car is already computerized from bumper to bumper. You may not be talking to your car yet, but that's not for lack of technology. It's so that car companies can keep a certain layer of luxury available for their more expensive cars.

In the 1990's the word "convergence" was a buzzword applied to the idea that we would soon be watching TV over the Internet. As usual, the realities of technology were predicted earlier and much more accurately by Sci-Fi authors than business people.


* I think I ought to write another post soon about parenting in the Internet age, using this game as an example, too. One of the things about this game is that when a kid signs up, their parents are automatically given an account, too, and encouraged to play *with* their kids. That's totally cool but a) I don't have as much free time as my kid and b) when I am involved, I'm not always sure when I should jump in to break up disagreements and when I should let the kids work it out on their own. It's not always as clear as in real life... as I said, another post on that soon.

Thursday, December 18, 2008

Kernel driver changes

I learned how to add in or swap out a Linux kernel module today. Kinda cool.

Let's start with the problem. My new laptop has both a wireless card AND an Ethernet card that are incompatible with Ubuntu Linux. So, after a little bit of testing and research, my ever patient friend, savior and all things *nix tutor discovered that the problem was that Ubuntu picks the wrong kernel driver for the Ethernet card on this machine and that it didn't have the wireless driver at all.

Just for extra learning goodness (or kharma or something), after my friend did the whole process to get my networking up and running, the Ubuntu updater updated the kernel and wiped out all his work. That just meant that I got to do the whole process myself, with him reminding me of the steps as I went.

So, the steps: First we downloaded the source code for the drivers. Unpacked the tarballs, followed the directions to compile the drivers.

With one of the drivers, the make install target did the copying of the kernel object into the right place for us. With the other driver, we needed to do that ourselves. To do that we found the ".ko" file in amongst the compiled code and copied it to the correct directory under /lib/modules/.

In the case of the Ethernet card, we needed to blacklist the wrong module as well, just to make sure that it didn't get loaded again by accident. To do that, we headed over to /etc/modprobe.d/blacklist and edited the list to include the bad driver. (Bad, bad driver! Don't come back!!)

Next
depmod -a
runs through your kernel and makes sure that all of the dependencies are there. It takes kind of a long time to run, because it goes through all of your kernel files.

Then use
modprobe [module]
where [module] is the name of your module, of course, to get the driver up and running.

Use
lsmod
to check to see if your modules are there.

We tested the whole thing by creating a boot image with our modified kernel. We did that with
mkinitramfs -o /boot/initrd.img-2.6.27-9-generic.new `uname -r`
and then we created an entry in grub at /etc/grub/menu.lst for the new image. The command mkinitramfs creates a special file with all the kernel information that the system needs to boot. The name that I used was based on the existing file for the pre-modified kernel, but with .new on the end. That was so that we'd know which was which, of course, and so that we'd know what to copy over top of later.

After booting into the modified kernel with out a problem, we went back and removed the extra grub entry, and moved the .new version of the image over top of the normal version. Now the modified kernel is my kernel and I have Ethernet AND wireless networking. Yay!


In case you are wondering, my new laptop is an LG R510. (My 9yo son says the LG stands for "Lawful Good". You think I'm raising a geek?) The drivers it needed are Realtek Ethernet and Ralink Wireless.

Monday, December 8, 2008

Creating a bootable USB disk

With all the MID stuff I've been doing lately, I've had need to create bootable USB disks from img files twice now. As noted previously, I am a dork, so I always forget how to do things like this that I don't do terribly often. To save myself heartache and search time, here are the destructions instructions in short:

  1. Get .img file for the OS you need. (via download, Moblin image creator, or whatever)

  2. Find out which /dev your USB disk is.

    1. before you put your USB disk into the computer, type
      ls /dev/sd*

    2. after you put your USB disk into the computer, do that again.
      The new entry is your USB disk

  3. Run dd to copy the image to the disk
    sudo dd if=/path/to/imagefile.img of=/dev/yourUSB
    (obviously, you wanna replace those paths with the correct info)



That should do it. It takes a little while, so don't freak out. You can check to make sure it's working by opening another terminal window and running
ls /path/to/usb
where /path/to/usb is the path that you would usually use to see the files on that USB disk. You'll get some gobbeldy gook, but that's fine. It means it's working.

You can get more details at this article on the Intel site.

Sunday, December 7, 2008

Compiz-Fusion: Some basic commands

So, it dawned on me the other day while I was watching a colleague zoom through windows and workspaces with keystrokes that I am not using all the juicy goodness of my desktop GUI. Compiz-fusion is installed by default on Ubuntu 8.10, but I'd never bothered to figure out how to use it properly. So, today I'm learning a bit and writing in commands I find here.

First, a definition. The super key is the Windows key on Windows keyboards. I have not the foggiest notion what it would be on other keyboards.

Next, make sure that you have the compiz config settings manager (aka CCSM). It should be under preferences and it doesn't need sudo acces to run. If you don't have it (I didn't even though I did have compiz-fusion installed) then do this:
sudo apt-get install compizconfig-settings-manager

If you go into CCSM and then choose General Options, and then choose the tab for key bindings, you'll get a listing of all the default key bindings. You can change them there, if you like.

For quick reference, here are some of the defaults I find useful.









Close window   alt-F4
Show Main Menu   alt-F1 (use arrows to navigate, esc to escape)
Run Dialog   alt-F (for apps that may not have a handy-dandy menu link)
Unmaximize window   alt-F5
Minimize window   alt-F9
Maximize window   alt-F10
Window menu   alt-space
Show desktop   ctrl-alt-d


Expo:
See all the Worspaces at once: super-E
Use the arrow keys to navigate around. Use Enter to exit that view and go into the workspace you have highlighted.

Ring Switcher:
This gives you a view kind of like when you flip through CD and DVD covers on iTunes, only the view is of your available windows.
Clockwise rotation: super-tab
Counter-clockwise rotation: super-shift-tab
Let go to land on the window you see in the center of the screen.

Scale:
This is the tool that has Exposition-like effects. Your desktop turns into a rotatable cube.
ctrl-alt + left and right arrows turns the cube.
ctrl-alt-down arrow flattens the cube.


There's a lot more that you can do, but those are the bits that I've played with so far and liked enough to keep activated. I like the water effects, but they are a bit distracting.

I like the annotation tool, but don't really need it on this computer. It would be way cool for presentations, though, so check it out if you do sales presentations, tech-talks or are a teacher.

Have fun with it!

edit: yes, yes, I see the big gaping hole in the view before the table. I'll fix it later, sorry!!

Thursday, December 4, 2008

When to write a script in a language you don't know

Sometimes there is a long, repetitive task that you know would be much better off if done by a small script, but the problem is that you don't know how to use the tools available at the moment.

One of my problems is that I never remember anything about a language or system if I'm not using it often. It's like I do a brain dump in order to make room for new stuff when I switch from one technology to the next. That means that even though I *have* done considerable shell scripting in the past, I can't remember a darn thing when I need it for a one off project. So, I know that I'd be better off writing a script, but I end up doing the job by hand anyway because it would take longer to look up language bits than it does to hit arrow up, back, back, back,... delete, delete,... paste.... a few times through.

The whole time I'm doing that, though, I'm thinking, "I could solve this like this in PHP or like that in Perl" and none of it matters, because at the moment I'm working in a very limited embedded linux system with neither of those languages on board.

So, what do YOU do in a case like that? Do you go look up the language ref for what IS available to you, even if it will take longer than the cut-and-paste for the task? Or do you just do the task manually?

Friday, November 28, 2008

Nvidia controls aren't in the GUI menus

My computer at home has an Nvidia graphics card, and it's running Ubuntu 8.10 at the moment. We have the living room set up as a combo family room/dining room/play space/study/office with an open layout and furniture sort of compartmentalizing the areas for each usage. We do not have cable TV, but we do have a nice TV/computer monitor that we watch movies and YouTube videos on. We pipe in all video content from the computer, whether it's from a DVD or from the Net. In order to make that work, we have the TV monitor set up as a secondary monitor plugged into the video card.

The problem: There was no GUI menu item for the Nvidia driver settings. The display settings that System->Preferences->ScreenResolution gives aren't the right thing at all.

The solution: You *may* have a link in System->Administration for Nvidia X-Server settings. If so, that's what you want. If not, open up a terminal window and type

gksudo nvidia-settings


It will ask you for your password, and then you can set up the secondary monitor as you like.

If you want to make that a selection in the System->Administration menu, right click on the word "System" in the top panel, then choose "edit menus". From there you can add a menu item for the above command.

Thursday, November 20, 2008

Bash Readline Commands

One of the cool things about most versions of the Linux command line is that you get a built in text editor to allow you to move around and edit your line easily. I generally use the Bash shell, and that comes with Readline. I know a few commands by heart and use them constantly, but there are more that never quite stick in my head. So, I figured I'd write about them here so they'd be easy to find and, possibly, pressed a little more firmly into my gray matter by virtue of having written them down.

Ctrl-e Go to the end of the line
Ctrl-a Go to the start of the line
Alt-f Go forward one word (actually Meta-f, but Meta is usually Alt)
Alt-b Go backward one word


Ctrl-k Kill the text from the current cursor point to the end of the line
Alt-d Kill the text from the current cursor to the end of the word
Alt-DEL Kill the text from the current cursor to the start of the word
Ctrl-w Kill the text from the current cursor to the previous white space
Alt-DEL and Ctrl-w are different because the "word boundaries" are different. Alt-DEL will stop at punctuation and other non-word characters. Ctrl-w does not.
Ctrl-y Yank (paste) the most recently killed text into place at the current cursor


Ctrl-l Clear the screen, putting the current line at the top

Sunday, October 19, 2008

Wireless connection from the command line

If ever you find yourself stuck with a *Nix box that won't boot into any kind of comfy graphical interface, and you need to connect to a wireless internet connection so that you can look stuff up and maybe solve your problem, here's a helpful tip:

There is a wireless networking utility very much like ifconfig called iwconfig. When you have a chance (and preferably before you really need it) check out the man page for it. Here are some quick and dirty instructions, in case you are desperate right now.

To find out what wireless networks are available to you, type
iwconfig wlan0 scan (see comments)
iwlist wlan0 scan

To attach to an open, non-encrypted network, type
iwconfig wlan0 essid netname
where netname is the essid of the network you want to connect to.

If you only have encrypted networks available, you might be in a bit more trouble. I haven't actually managed to get that working at all yet, though theoretically, it should work something like this:
iwconfig wlan0 key s:password
iwconfig wlan0 essid netname

where password is your password and netname is the essid of the network you want. The s: means that the password is in string format. If you know the hex version of your password, then instead of saying s:password you'd just type in the hex of the password like this:
iwconfig wlan0 key 0123-4567-89

Good luck getting your GUI fixed!

Sunday, October 12, 2008

Stealing from Ubuntu to pay Midinux

I'm busy trying to get an application to work on Midinux MID devices. There's a problem, though, because a chunk of libraries that I need are not available in Midinux for some reason. So, I'm snagging the libraries I need from the Ubuntu os I'm running on my desktop and converting them to run on the MIDs with Midinux. I can do this because, for reasons I don't understand at all, Midinux is compiled as an i386 system even though it's sitting on a Mobile Internet Device with an Atom CPU (that's lpia architecture, in case you didn't know).

You can find lots of debs (those that you have installed on your Ubuntu desktop, that is) in /var/cache/apt/archives/ . The advantage of that is that you don't have to go hunting very far. If you can't find the deb that you are looking for there, try searching http://packages.ubuntu.com

Once you have the packages that you need, go ahead and change the debs into rpms using Alien. The command looks like this:
> alien --to-rpm the-package.whatever.deb

With that done, stick the package someplace where you can download it to your Midinux device, then pop over into the X-Terminal and into the directory where the rpm you need to install is sitting. Install the rpm with:
> rpm --install the-package-whatever.rpm

And there you go!

Tuesday, October 7, 2008

Ahhhh... This place has PACKAGES

Having gotten my blasted scratchbox working, I didn't seem to be any closer to compiling anything. I needed several packages and they weren't in the default packages available in the initial set up. Why, o why don't they give you any useful repositories right from the start in your scratchbox setup? I mean, COMEON!

So, the good news is that Hacking the N810 pointed me in the direction of http://gronmayer.com/it which is now officially my second savior of the day (right after Gnuton).

At Gronmayer.com I was able to search for the packages I was looking for, find out what repositories they live in and set up my /etc/apt/sources.list in the scratchbox accordingly.

Just remember, you have to set up configuration files like the /etc/apt/sources.list for EACH target you are running in scratchbox, especially if you plan to be doing cross compilation.

Maemo Scratchbox Hell

That was SO much harder than yesterday. So, maybe it wasn't the same problem.

When trying to install the maemo-sdk-runtime in the ARMEL target of my scratchbox, I kept getting this HUGE error that started
[sbox-DIABLO_ARMEL: ~] > fakeroot apt-get install maemo-sdk-runtime
Reading package lists... Done
Building dependency tree... Done
The following NEW packages will be installed:
maemo-sdk-runtime
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
27 not fully installed or removed.
Need to get 0B/1890B of archives.
After unpacking 32.8kB of additional disk space will be used.
WARNING: The following packages cannot be authenticated!
maemo-sdk-runtime
Install these packages without verification [y/N]? y
/scratchbox/tools/bin/sh: line 1: /usr/sbin/dpkg-preconfigure: No such file or directory
Selecting previously deselected package maemo-sdk-runtime.
(Reading database ... 16920 files and directories currently installed.)
Unpacking maemo-sdk-runtime (from .../maemo-sdk-runtime_1.0_all.deb) ...
Setting up gconf2 (2.16.0-1osso14) ...
/scratchbox/tools/bin/chown: `messagebus:messagebus': invalid user
dpkg: error processing gconf2 (--configure):
subprocess post-installation script returned error exit status 1

and ended
E: Sub-process /scratchbox/devkits/debian-etch/bin/dpkg returned an error code (1)



I'll now list ALL the things that it took to get this working...

Let us start with /etc/sysctl.conf
add the lines
vm.mmap_min_addr = 4096
net.ipv4.ip_local_port_range = 1024 65535
vm.vdso_enabled = 0

to this file. I recommend doing a search for each of those setting before you add the new lines. If you have the settings in there, comment them out, and then put the changed setting directly underneath with a comment about WHY you are doing this. (That's to save you heartache later if it breaks something else.)

Next, I ran apt-get install -f in both my normal shell and in the scratchbox. I used apt-get autoremove to get rid of some no-longer-needed packages in my regular shell.

Gnuton reported several problems and fixes and although I didn't have his 'messagebus:messagebus': invalid user problem I still did
cd /var/cache/apt/archives
fakeroot dpkg -i *dbus*

in the scratchbox, just in case.

Finally, I followed his advice and did
cp /usr/sbin/dpkg-preconfigure /scratchbox/users/lisha/targets/DIABLO_ARMEL/usr/sbin

and finally the &$%#! fakeroot apt-get install maemo-sdk-runtime worked.

Sometimes I just don't learn

I created this blog for the specific purpose of saving me from my own terrible memory. Again and again I get myself into deja vu situations where I can distinctly remember getting into this problem before, but I can't remember hoow I solved it. The number of times that has happened has dropped precipitously since I started blogging my most annoying problems here. But, despite that fact, I managed to forget how really important it is to my learning process to write these things here.

Yesterday, my maemo development scratchbox and I had a little disagreement regarding available packages and repositories. In the end, I solved the problem, but only in the i386 target. Today I cant get the armel target to work and I have no idea what the fix was yesterday. This is a serious pain.

Not to worry, I was better than the problem yesterday, and after wasting a bit more time, I shall beat it again. When I do, I'll be sure to blog the solution here.

Thursday, October 2, 2008

Thoughts on MID's

MID stands for Mobile Internet Device.

These devices are small tablet computers, some with and some without a physical keyboard, that allow you to connect to the Internet and run a number of applications in miniature versions. Some smart phones are basically MID's that happen to also be phones. I'd put the iphone into that category, as well as any phone with a screen that size and equivalent functionality. So, in my book, the Nokia N80 doesn't count (too small of a screen for comfortable web-browsing) but the HTC Android phone does count. My broad description, including phones, is not necessarily canonical. I do think that it's logical, however.

These devices generally have a browser, some sort of IM/chat facility, some sort of office document reader and sometimes document editors, a music and/or video player, and games. Some MID's run a version of Windows Vista. Others run a version of Linux. Of course, if you know me at all, you know that I want Linux on my MID, because I want freedom (as in speech) with my software as much as is possible. The good news is that it's possible to run a version of Linux on nearly all MID's today thanks to the work of groups like Moblin.org. So, knowing that, what's really important in an MID?

There are a few harware things that I think are vital. A usable keyboard is way up there, in my estimation, although a really good *handwriting recognition interface would satisfy me just as well. A **screen size that allows for easy reading is important, too. A camera is nice, but not vital, since my main digital camera is generally on my cell phone.

Software-wise, I don't want to be hobbled. I don't want the system to lock me out of the terminal window, or force me into contortions of geekish heroics just to install non-approved software. I don't want Big Brother telling me what I can and cannot run on my MID. It's mine, gosh darn it. If I bought it, I want to use it however I choose. Can you imagine buying a refrigerator and being told that your warranty would be void if you chose to refrigerate any non-food items? What if you choose to refrigerate photographic film? Or pre-cool glasses so that you can have a proper cold one?

The Samsung Q1 is my favorite device in terms of screen size and heft. I feel like I could get WORK done on that thing, as well as play, read RSS feeds on the way to work and otherwise do most of the tasks that make up most of my non-programming computing life. What I don't like about it is the keyboard. Actually, the keyboard is ALMOST right. The placement under the user's thumbs at the top of the screen is fantastic, but it's just too hard to do shifting and number typing. Fix that, and the Samsung Q1 running an imaginary version of Moblin would be first choice all around.

I've played pretty extensively with the Lenovo ideapad U8, and I'd really *like* to like that device, too, but it just doesn't cut it for me. If I spoke and wrote Chinese as my primary language, my opinion would probably be a bit different. The stroke-based keypad on the telephone dial pad is probably a comfortable way to type Chinese. If you've done much smsing, though, you already know what a pain that kind of keypad is for extensive entry in most other writing systems. The fact that the midinux software on the device is super hobbled is also a pain. In early versions of the device you couldn't even get a terminal window unless you know the "cheat code", so to speak. (Ctrl-alt-backspace and then F2) In later versions, at least you'll have an x-terminal available by default. Still, the packaging system is wonky, and the GUI is funky and uncomfortable.

You may have noticed that when I was talking about the Samsung Q1 I wanted an imaginary version of Moblin. Well, that's a thing, see? Moblin just isn't what it could be, yet. I'm personally not all that thrilled about the fact that they've just changed from a debianish system to a red hattish system, either, but that's beside the point. The problem with Moblin on the devices that I've tried it with has been far more basic than that. The applications just aren't quite there yet. They, almost without exception, get things wrong when converting their interface into the smaller space. Buttons don't show up right. Text inputs get messed up. Scroll bars are in the wrong places or not there at all.

One of the biggest problems across the board with Moblin apps and system controls is that they are unaware of whether the screen keyboard is being used. That means that they hide important dialogs and even buttons under that keyboard in the screen real estate, and you simply can't DO anything. The only solution is to plug in an external keyboard to get some tasks done.

So far, the best all around experience I've had has been with the Nokia N810 running the new maemo version, 4.1.1 Diablo. It was easy to find and get software. It was easy to get into a terminal window and easy to do things there. The pull down keyboard was comfortable in my hands and I was able to type fairly quickly with it. The touch screen worked well, and the applications were lovely. I didn't see any of the problems that I've encountered with Moblin apps, which makes me wonder why there maemo apps aren't being ported to Moblin instead of desktop apps getting Moblinized.

I've got this fantasy of a cell phone/MID device that will be bigger than the Nokia N810 but smaller than the Samsung Q1, have enough storage to make it useful as a multimedia device, run on Intel ATOM architecture or an equivalent for power and speed, have a usable keyboard AND handwriting recognition, a camera on the back (they are so useful for things like barcode reading!) and bluetooth so that I can connect an earpiece. Of course it will have wifi and 3G, because let's face it, there's no reason I should have to carry BOTH a telephone and this little baby, when I can have it all in one. Seriously, with a bluetooth earpiece it doesn't matter how big the device running the 3G connection is, and you really shouldn't be talking with the phone up to your face anyway! This device would either run maemo, which I think is an absolutely lovely OS, or else Android, which makes me all weak in the knees and giddy with excitement at the thought.

When this device is born I will love it, take good care of it, and write software for it. It'll come with me on the bus and on the plane and in doctor's and vet's waiting rooms. It will sit with me in coffee shops, and hang out with me on the couch in my living room. I think I've been dreaming of this device since I was a kid, while sitting in front of the tv, watching endless Star Trek reruns. I'm wondering when I'm going to get to adopt buy one.

*Am I the only one on the planet who misses the Palm Graffiti?

**I think I'm killing my eyes reading RSS feeds on my way to work on the tiny N80 screen.

Wednesday, August 27, 2008

Mozilla is Ubiquitous

If you are subscribe to my Google Reader share, are one of my Twitter friends, or are connected to me on FriendFeed, then you might be sick of this topic already, since I've been kinda blabbing and sharing and tweeting ever since I found out about this when I came into work this morning, but... DUDE! Ubiquity is AWESOME!!!!

In case you, like me, have never heard of the Ubiquity project from Mozilla Labs before, let me enlighten you with this here little video:


Ubiquity for Firefox from Aza Raskin on Vimeo.

The reason that this tool is so cool is that it brings together the speed of command line work with the user friendliness of the graphical interface. With a few key strokes you can do the work of tons of mouse moves and clicks. What's more, the key strokes are completely intuitive. There's no memorizing a huge list of things just to make it work. I don't have to memorize the word "Twitter", I use it all the time, and if I start typing "Twitter" in the Ubiquity command box it guesses at what I'm trying to tell it before I'm even done. So, two letters in, I'm done with the "Twitter" part of the command and I can start telling it what I want it to tweet.

The interface for Weather is another great example of how easy to use this interface is. I called up the Ubiquity command box and started to type "we" and it knew I wanted weather. Then I typed Oakland (where the bestest daughter in the whole wide world is right now), and it immediately gave me the weather for Oakland, California. I decided to see about Oakland, New Jersey, though, just for a twist. *Poof* the weather info changed as I added in the state. Very nice.

There are lots of commonly used tools built into the application already. On the downside, non-programmers find themselves stuck with the options that someone else picked when they wrote the command. On the upside, however, with just a little bit of work you can learn how to edit existing commands or write your own, so you can make commands go to the sites that YOU want.

The first thing I plan to do with this? Create a command for mapping here in Israel using http://mapa.co.il, since Google Maps are less than useless in Israel. (Apparently, in Israel we have no streets.) I shall post code and a general review of the coding experience here when I'm done.

Oh, oh, oh, you know what else would be nice? A command to blog things just like you can email things in Ubiquity. Yeah, that would be awesome. Who wants to write that one?

Tuesday, July 22, 2008

mySQL query solution

I had been trying very hard to avoid having to do a nested query, but in the end, I really couldn't figure out a way around it. This is the query that gets the job done:


mysql> select tnid from fr_strings where sid NOT IN (SELECT sid from fr_tr_by_uid where uid = 1 and language = 'es');


If you have a non-nested solution for this problem, I'd still love to see it!

Monday, July 21, 2008

mySQL query trouble

I'm having a hellish time with a sql statement. I need to get nodes ("tnid" here) where a given user (uid = 1) has not translated a given language (language = "he", or rather, != as you'll see)

fr_strings has sid and tnid (those are the only ones important to us now, anyway)
fr_tr_by_uid has sid, uid and language

When someone translates a string, it pops in their user id, the string id and the language that they translated the string to. So, say, if I am translating into es or he (spanish or hebrew) I should no longer see the string pop up for translation in es if I've already done that translation, but the request for the string translation would still pop up when I'm working on the he translation. Get it? OK.

So, I want to select the tnid's where uid != 1 and language != 'he'. Something like that. Let's look at some queries and responses:


mysql> select distinct * from fr_strings as st natural left join fr_tr_by_uid as ui where sid > 279;
+-----+------+------+----------+
| sid | tnid | uid | language |
+-----+------+------+----------+
| 280 | 870 | 2 | es |
| 280 | 870 | 1 | es |
| 281 | 871 | 1 | es |
| 283 | 873 | NULL | NULL |
+-----+------+------+----------+


What I want out of this bunch here is tnid 283. That's all. That's the ONLY one I want. But if I try this:


mysql> select distinct tnid from fr_strings as st natural left join fr_tr_by_uid as ui where sid > 279 AND uid != 1;
+------+
| tnid |
+------+
| 870 |
+------+

That's clearly not what I wanted.

How about This:

mysql> select distinct tnid from fr_strings as st natural left join fr_tr_by_uid as ui where sid > 279 AND uid != 1 OR uid is null;
+------+
| tnid |
+------+
| 870 |
| 873 |
+------+


Still not there. As you can see, since the tnid shows up once in the table under a different uid, I still get that tnid back, even though one record with that tnid does have the uid=1.

I'm sure that this is something really stupid. (I'm always sure when I can't figure something out that the solution is something really stupid.) But, I can't shake the answer out of my head. Any of you know what I'm doing wrong?

*edit* I got a message suggesting that I ought to just do uid is null and ignore the uid != 1 part. But here is why that doesn't work for me...

Let's say that I want user 2 to get all the strings that she hasn't translated into Spanish yet.


mysql> select distinct tnid from fr_strings as st natural left join fr_tr_by_uid as ui where sid > 279 AND (uid is null OR language != "es");
+------+
| tnid |
+------+
| 872 |
| 873 |
+------+


This doesn't work. You see, uid 2 DID translate 870 into Spanish, but not 871 (see the first results table). I need her to get 871 for translation still, but this query won't give it to her. I'm still stuck.

Wednesday, July 2, 2008

Finding a host I couldn't see

Last week I finally broke down and asked IT if they would mind if I switched over to a Linux desktop for my daily development work. Functioning in Windows was driving me absolutely bonkers. He wasn't so sure about it at first. He suggested that I run Windows and then have Linux running in virtualization. That just seemed like a waste of resources to me, though. So, I suggested that I set the computer up for dual boot, and if things went badly I could always go back to Windows.

The IT guy's concern was that, while I might be able to do my programming in Linux, I might not have access to all the company shares, the exchange server for mail, and all that other Windows-based stuff sitting on the company network. And he was right to be concerned. In the past, all those things have been a major pain in the backside to fix.

The good news is that Samba, the tool that lets you hook up Linux or Unix machines to a Windows network, has come a very long way, and the whole thing turned out to be pathetically easy. Not only that, but Evolution for mail kicks the proverbial butt, and I was able to get mail, tasks, contacts, and calendar from exchange working perfectly with the Exchange server with just a few button clicks and no sweat at all.

But, then I need to look something up on the company wiki, and that's when I hit trouble. Firefox turned my http://companywiki/ url into http://www.companywiki.com. Woops! I tried a couple of times before it sunk in to my thick skull that the problem was that my computer wasn't recognizing the internal domain names. Clearly I need another Domain Name Server in my list, but the problem is that I don't want to go back to that IT guy just now. He may just tell me it's all Linux's fault, and that I have to switch back. I don't want that. So, I have a work around.

I checked in Windows what the ip address for companywiki is supposed to be, and then, back in Linux, I edited my hosts file to point the name companywiki to that address. Poof! I have normal access to the wiki using the domain name now. Easy peasy.

There are other uses for the hosts file, too. For instance, if I have server settings in a Web application that I'm working on, I can tell my hosts file that those server names are really my computer. My computer will look where the hosts file tells it to look before asking the Domain Name Server for information, so I can test the application without having to change those server name variables in the code.

Linux is not the only system with a hosts file that can let you find servers by a certain name, either. You can find a list of where to find the hosts file on different operating systems at Wikipedia.

Friday, June 20, 2008

A bit of fring development trivia

So, if you are a developer of things webbish or things mobile phone-ish, you may already know that the company I work for, fring released an API for creating various applications and mashups inside our software platform. The name of our special XML-based language is FAXL, pronounced "Fah-zel". The server that runs the fring applications is called the FIS. One of the FIS servers we used for development was named "inigomontoya".

In the last few days leading up to launch, there was a bastardized quote that rang through the air at seemingly random times, "My name is Inigo Montoya. You killed my FAXL. Prepare to die!"

Yeah, software development deadlines are not conducive to mental stability. Need I say more?

Sunday, May 25, 2008

PHP and AJAX *head desk*

So, Thursday afternoon I broke my brain for the weekend trying to figure out why the heck a script that is working perfectly well on one server isn't working right on another server. Day one was wasted trying to figure out HOW to figure out what the heck was going on. The logs told me nothing. The page itself was not giving any hints. Since the whole thing was happening in AJAX land, behind the scenes and without giving any useful output to the browser, I couldn't use debugging tricks like echo and print_r to figure out what was going on with my variables. This morning, however, my brain was in better gear than it was Thursday afternoon, so I started the day off by actually doing something useful.

When you need a script to give you useful information in the browser, and the page in question is using AJAX to send information (but not, at the moment, receive information), then (DUH!) use AJAX to give you the information you need!!!

In my case I had a handy editor box in which to plunk the response text from the AJAX request.

xmlhttp.onreadystatechange = function(){
if (xmlhttp.readyState == 4) {

document.forms["editorbox"].editorBox.value = xmlhttp.responseText;
}
}

At one point, I used alert(xmlhttp.responseText) instead of the editorbox, but that wasn't as useful because the alert box doesn't let you select and copy stuff if you need it. Also, my editorbox had a handy-dandy scroll bar, and the errors coming out of my responseText were numerous.

In order to make the responseText useful, you may want to echo out certain variables and then exit; so that the info you want -- and only the info you want -- will show up where you need it.

Now, as to what was actually wrong with the script I was messing with today... It appears that a difference in php.ini files was my problem. In the version of the script that was NOT working, all the quotes were getting escaped as they got soaked up into the PHP script. When I then tried to dom->loadXML($myXML) the script was complaining that my XML was no good. Well, of course it's no good, there's all these darned escape characters before the quotes!

I don't want to change the php.ini on the server, so I have to get rid of those escapes some other way. preg_replace to the rescue!


$pat = '/\\\"/';
$rep = "'";
$myXML = preg_replace($pat, $rep, $myXML);


All better. :)

Tuesday, May 13, 2008

Good User Interfaces

I have a friend who loves to complain about the user interfaces in current technology. He has a million great things to say about how things should be made, and he says them with a cantankerous grumble. I adore him for so many reasons, but this is definitely one of them. He opens my eyes again and again to my own tendency to develop for geeks like me instead of the person on the street who really should be getting a better thought out and better built product. Because of him, I also notice even more when someone does something really right.

A couple of weeks ago he and I were in an elevator and he hit the wrong button by accident. He grumbled and hit the correct button and then said, "You know, if elevators were made correctly, I'd be able to cancel that wrong choice. I should be able to hit that button again and make it turn off."

Today, when I got into the elevator at work, someone else got in, pressed the wrong button, noticed the mistake and pressed the button again to cancel the request. Then they pressed the floor they really wanted. Oo! I was so excited I had to twitter it right there in the elevator.

It turns out that all new Mitsubishi elevators have that functionality. Way to go Mitsubishi.

Another one of my friend's pet peeves is that you have to save files. Why should you have to do an action to save a file? It should be automatic, right? Why would I create a file if I didn't want to save it? Well, it's getting to be automatic in some places like Google Docs for instance. Well, today I found another really cool app that deals with the saving thing right along with at least a dozen other major UI annoyances.

Skitch is unfortunately a Mac only application and it's still in beta, but it looks absolutely awesome. They get so many things right. They have a great way to share things, to snap screenshots, to draw and manipulate images, and you don't have to save your file from a menu or a keystroke. You can just drag it to where you want it to live, or drag it to an email to share it. Very, very nice.

Monday, May 12, 2008

Having Trouble Importing Drupal Translation Packs?

OMG I just spent way too long pulling my hair out over the Drupal 6 translation import feature. To put it simply, the handbook and help information is very UNCLEAR about what you are supposed to do.

The instructions say to download the translation pack into your install directory and unzip it. So, if, like me, you don't have access to the server that will allow you to unzip a folder on the server, logic says that you should be able to unzip the folder on your own machine and simply ftp the folder into place, right? Wrong. Well, at least sort of wrong.

Let's say you have the he-6.x-1.0 translation pack. You've unzipped it, and now it's sitting on your PC's desktop. You want to move it to your server. DO NOT copy that whole folder over to the server so that you end up with something like /webroot/drupal/he-6.x-10 on your server.

What you DO want to do is copy the CONTENTS of he-6.x-10 over onto the server so that the internal directory structures plop into place inside the existing directory structure in drupal. That way you will have something like /webroot/drupal/modules/aggregator/translations/modules-aggregator.he.po and so forth.

As you can see here, each directory that has translations (modules, themes, etc. anything that has t() strings, really) gets it own translations directory and language po files go in there.

The easiest way to get all of those files to plonk into the right place is, in fact, to un-zip the file insitu at your server rather than trying to ftp the files over post-expansion.

Thursday, May 1, 2008

Interesting tidbit about PHP objects

I'm doing some XML stuff right now, using SimpleXML in PHP. One of the element groups I need to create is a list of descriptions in different languages. My original attempt looked like this:

$descriptions = array(
'en' => 'An awsome app.',
'es' => 'Una aplicacion chevere.',
'he' => 'אפליקציה מעולה',
);

foreach($descriptions as $loc => $desc) {
$d->addChild('description', $desc);
$d->description->addAttribute('locale', $loc);
}
echo $xml_post->asXML();


But that gave me an error:
Warning: SimpleXMLElement::addAttribute() [function.SimpleXMLElement-addAttribute]: Attribute already exists in...


When I looked at the code, the attribute was only getting plunked into the first <description> tag. The PHP engine thought that each time I went through the loop I was talking about the same $d->description when I asked it to stick a locale attribute in there. Weird. I expected the object to be treated like any other variable and get treated as a fresh thing. Nope.

If you put

echo $d->description . "<br />"

after the addChild() above, you'll see that it echoes out

an awesome app.
an awesome app.


If, however you change that block of code to

foreach($descriptions as $loc => $desc) {
$tag = $d->addChild('description', $desc);
echo $tag . "<br />";
}

you'll see that $tag prints out the correct description line for that pass through the loop:

An awsome app.
Una aplicacion chevere.
אפליקציה מעולה


So, the correct code to create the XML I want is

$descriptions = array(
'en' => 'An awsome app.',
'es' => 'Una aplicacion chevere.',
'he' => 'אפליקציה מעולה',
);
foreach($descriptions as $loc => $desc) {
$tag = $d->addChild('description', $desc);
$tag->addAttribute('locale', $loc);
}
echo $xml_post->asXML();


And then the XML comes out right.

<description locale="en">An awsome app.</description>
<description locale="es">Una aplicacion chevere.</description>
<description locale="he">אפליקציהמעולה</description>

Wednesday, April 30, 2008

CodeBlocks: Cross Platform C++ IDE

This is late, but you know what they say... better than never, right?

CodeBlocks has finally released a new version. For ages they weren't doing releases, just nightly builds. When I was working with Shlomi Peleg at SparkThing this app was a staple of our work environment. I haven't used the new release yet, but Peleg says that it's great.

So, if you write C++ and want an excellent open source IDE to work in, check it out.

Monday, April 28, 2008

Cool iPhone Thingy

We had a training at work today all about how the GSM phone system works. At the end, the speaker showed us how to find out all sorts of information about your GSM connection on an iPhone. You can see information about a call in progress, network information, which cell phone towers your phone can see, information about your GPRS (internet) connection, and what firmware version you are running.

One of the cool things about this is that you can see how walking around in a room, say, makes your connection to any given tower stronger or weaker.

If you have an iPhone, check it out. Dial *3001#12345#* then hit call.

And no, I don't have an iPhone. The company has a few for testing our apps, so we got to play with those. My current phone is a Nokia N80.

Sunday, April 13, 2008

Computing Everywhere?

A friend of mine hates the state of computing today. He points out that it's developed by geeks for geeks, and the rest of the world has to bend to our twisted way of thinking. Really, computers should be more than just ubiquitous, they should be invisible. They should bend to the needs of humans, not the other way around.

One of the areas where this is actually making strides forward is in the area of always accessible data. As my friend would say, "Why should I have to manage three or four address books? I shouldn't! The computer, my home phone, my cell phone, and all of the apps on them should be able to get what I need from one central place where I keep that data." So true.

APIs for cross-application development and mashups are getting us closer to that kind of thing, and tools like OpenID and OAuth are also moving us in the right direction. But, what about that data thing? How can I have my data in one place?

One possibility is the advent of serious online storage solutions and wifi based file sharing through applications like *Fring. There's a blog article about just that at the Fring site called "Is Fring the missing link for mobile online storage services?". Yeah, I think that it can be.

We're still a long way from where my friend dreams, but I truly believe that we are in the midst of an evolution that is heading in that direction. One side of me says that we shouldn't be too impatient because all of these things are moving forward one step at a time, but on the other hand, it's precisely the impatience of developers and entrepreneurs that is pushing us forward in this evolution so quickly.

The next time you look at the design of an application you are working on, ask yourself: "How is this going to tie in with the computing needs of the user at home, on their smart phone, in the car... and everywhere else they are computing?" And "Can we make it work together with a single data source and invisible syncing?" Because if you can deal with those two issues now, you are going to put your app ahead of the curve and make it that much more invaluable to your end user. Which might just be yourself. (or me!) ;)

*Just so you know: I work for Fring now. :)

Wednesday, February 13, 2008

Woops! MySql didn't start when the server rebooted!

One of my customers had this problem today. I got a text message, "Lisha! Can you look at the server and tell me why mysql isn't working? I rebooted the server and now the website has an error. Something about Error #2002 and the mysql.socket."

It turned out that when they rebooted their LAMP server, the mysql demon didn't turn on with the rest of the services like the apache http demon. Luckily, this is easy to fix. I ssh'd to their server and got to work.

First, I checked to see if my hunch was right:
mysqladmin ping
mysqladmin: connect to server at 'localhost' failed
error: 'Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)'
Check that mysqld is running and that the socket: '/var/lib/mysql/mysql.sock' exists!


Yipes! Yup, you have no bananas (or mysql, as the case my be).

Next, I ran the mysql initialization script:
/etc/init.d/mysqld start
Starting MySQL: [ OK ]


Then check to see if it worked:
mysqladmin ping
mysqld is alive


Ah, yes. All better!


Next time, we can make mysql demon startup at boot time. On a Red Hat type system you can run the following code as root (or via sudo) to run the initialization script automatically at boot:
ln -s /etc/rc.d/init.d/mysqld /etc/rc.d/rc3.d/S98mysql

Monday, February 11, 2008

Collecting mail from external servers on Zimbra

Do you have Zimbra users who want to pull mail into their Zimbra accounts without having to press "Get Mail" or "Get External Mail" every time? It's easy.

In the Zimbra server's command line, running as user zimbra, try:
zmprov gc default | grep zimbraDataSourcePollingInterval
If you get a response, the number it gives you is the number of seconds between checks of the external mail boxes. If you don't get any response, that means that the zibraDataSourcePollingInterval isn't set yet. Set it like this:
zmprov mc default zimbraDataSourcePollingInterval 180
Now the external mail accounts will be checked every 3 minutes.

But wait!! There's a problem. If your users created secondary accounts before you did this, their mail might not get picked up on schedule. (This is certainly the case as of 5.0.0_GA_1869.) So, you need to set the polling interval for each of your users' data sources manually -- or with a script that you write yourself.

For each user, check what datasources they have now:
zmprov gds myuser |grep DataSourceName
where myuser is the name of the user, of course. Then, for each user modify the data source with the command:
zmprov mds [username] [dataSourceName] zimbraDataSourcePollingInterval [seconds]

For example:
zmprov mds myuser Migration\ Account zimbraDataSourcePollingInterval 180
Notice the \ and space in "Migration\ Account" in my example. The name of this data source is "Migration Account". If you have spaces in your data source name like I do here, then you need to use the backslash (\) to escape the space. Otherwise, the system thinks that the next word is part of the next option or command in the line. (This is pretty standard *Nix-ish behavior, but if you're a newbie it can throw you off.)


(The info for this post was found at http://www.zimbra.com/forums/installation/11487-solved-receiving-mail-multipop3-server.html and through personal experience with this problem last week...)

Thursday, February 7, 2008

Locking Down Root

Having an active root user is generally not a good thing. If the machine is used by lots of people and several individuals do superuser tasks under the root user, you have no way to track who did what in the event that someone decides to get evil. And of course, hackers like to get root access, because it lets the do anything that they want. You don't want that, so let's lock root up.

First, make sure that you have super user abilities when root is locked. If you don't already have sudo access, use root now to add yourself into the /etc/sudoers file. (I'll write an article about that soon. In the meantime, use man sudo to learn more.)

Now, lock root. Get out of root, if you are in it already, and as a user with sudoers privileges type
sudo passwd -l root
Check your work with
sudo passwd -S root
You should see something like
$ root L 09/11/2007 0 99999 7 -1

The option -S gives you the status of a user. It gives you the user name, then the status (L = locked, NP = no password, P = password), the date of the last change, and then the minimum age, maximum age, warning period and inactivity period for the password.*


Root is now locked. You can't log into root directly any more, and will have to run superuser tasks through sudo. There is still a cheater way around it, though. You can
sudo su
and then you will be root again. (I'll explain how to fix that in the sudo article.)



* Minimum age for a password says that you can only change the password ever so many days. Maximum age says that you have to change your password every so many days. Warning period is how long before maximum age is reached that the system should start warning you that you have to change your password. Inactivity period is how long after a password is expired that the login should be completely locked out. If you don't change your password before maximum age is reached, then the system will generally let you log in and immediately change your password before moving on. Once you've hit the days in inactivity period, though, you don't get a chance. It just won't let you in at all at that point. All of these ages are expressed as a number of days.

Creating A New *Nix User

The easiest way to create a new user on the command line is:
sudo useradd george
sudo passwd george


But that's not always enough. Let's say, for instance that you want people to change their password the first time that they log in and then again every three weeks. Let's set georgette up like that:
sudo useradd georgette -c "Georgette Userina"
sudo passwd georgette
(give her a throw-away password)
sudo passwd -e -x 21 georgette


Here's what we just did:
sudo = "superuser do" (do this as if you are root)
add user georgette with the comment (-c) "Georgette Userina" (-c is usually used for the user's full name)
give georgette a password she can use the first time she logs in
expire georgette's password immediately (so she has to change it when she next logs in) and then expire (-x) her password every 21 days.

Need a short term user? Maybe you have a contractor working with your company for a short time or a friend that's hanging out at your house for the next two weeks and needs access to your Ubuntu desktop while he's there. Here's how to do it:
sudo useradd sammi -c "Sammi Shortimer" -e 2008-03-10


Here we use the -e option with useradd to expire the account after March 10, 2008.

If you do most of your new user adds with the same special options, you can set those things as default in the file /etc/login.defs

Wednesday, January 30, 2008

MacBook Air

Oh, me wants one. Me wants one bad.



Yeah, yeah, it's not Linux or OpenBSD. But it is *Nix-ish, and it's so purty. And I need a new computer, I really, really do.

In real life, though, I don't have that kind of cash to throw down right now. It looks like I might be borrowing an old Mac laptop from Lior Kesos of Linnovate shortly, so that will take care of my laptop needs. For the house I'll purchase a PC and put Linux on it (as usual). My little guy and I can make a homeschooling project out of setting up a Webcam + software to create a multi-touch, gesturable interface. I'll let you know how it goes here when we do it.

Wish list for my new computer:
1. bluetooth (to hook up with our cell phones)
2. webcam for video chat with far off friends and relations
3. multi-touch, gesturable track-pad like input
4. everything I already have on my current laptop
(you know, like 802.11g/n, region-free dvd movie viewing, KDE desktop, some fun games, etc...)

Tuesday, January 22, 2008

Mail, Calendar and Collaboration

We just set up Zimbra at work, and I'm really pleased with it. But I'm a little wary of the fact that Yahoo! just bought Zimbra. What will happen to this platform next? Nothing bad, I hope...

Here's why I like Zimbra, as opposed to the other open source groupware server packages out there. (Where to start?)

1) Zimbra is made up of familiar pieces. It uses the Unix philosophy, which is to write relatively small applications and then glue them together to do big jobs. In that vein, Zimbra uses Postfix, Apache, and other tried and true tools at its base.

2) Zimbra can be used with all your usual clients. It works with IMAP or POP3, and even has an available (non-open) Exchange-like piece that you can use for your (shudder) Outlook users. It also has nice, standards based things like an ical version of your calendar, which you can use to connect up with standards-friendly calendar clients.

3) Zimbra has a fantastic Web-based client. It's all AJAXy and buzzword compliant, but that's not what's great about it. My favorite part about it is actually reason #4...

4) Zimlets. Zimlets let you create all sorts of extensions that will work in Zimbra. Here at this company we're in the process of planning the next generation of their whole in-house software system, and I'm putting Zimlets at the core of several pieces of that software architecture. Customer service, billing, accounts payable, marketing, and supply-chain will all have direct access between their respective job-function-related applications and Zimbra, both ways. For instance, a CS rep will be able to read an email sent to service@..., mouseover the customer name to see that customer's key info or mouseover the order number and get info about that particular order. Click on either one and the cs rep will go straight to the full editable customer or order page. All this, of course, will be based on Zimbra group permissions which will be sync'd up with the user/group permissions on the Web interface for our customer service tools.


As you can see, I'm very excited about the possibilities. This is why I keep working in this industry. Fun stuff. :)

Thursday, January 10, 2008

Improving Web Research

This isn't my usual level of geeky tips, but something that comes up a lot for anyone who has to learn on the Web all the time. "Back in the day" when I was in college, I read books and highlighted them as I went, or else I'd take copious notes on 3x5 cards. Then, when it was time to review or to gather the information to put into a report, I'd have easy access to everything. On the Web it's a bit different. I can read stuff, but until now, it's been a bit more difficult to gather the details I need from a specific page along with notes and references I would have written in margins or on cards. Bookmarks alone just don't cut it.

There are a few tools out there now that are aiming to fix this problem, though. I use Google Notebook right now as my main computer-based note taking tool, but I'm looking around to see if there is anything better.

Google's Notebook tool is actually rather nice. It works with a browser plug-in that sits in the right-hand corner of my browser status bar. I can click it, and the notebook opens up. I can have several "notebooks" that each hold different sorts of information. I can type notes myself, or I can highlight something in my browser and then drag it to an open notebook, or press "clip" in the notebook plug-in, and I get a little note with the text or images I've highlighted plus a link back to that page. In the Web page for the notebook (though not in the little plug-in version) I can see the date that the note was taken, which is important for citations and the like. I like it, I'm just wondering what else is out there before I get so much data into this notebook system that migration would simply be a major pain.

There is a tool called i-lighter that looks very interesting. It allows you to use your mouse like a highlighter on the screen, and then it saves your highlighted text, along with any other notes that you want to write. Problem? It's a Windows application. Sure, I could use it with Wine, but unless it completely rocks the universe, I don't see a reason to do that.

I have heard about other pieces of software in this category that are under development, but I have yet to experiment with any of them. If you have any recommendations, I'd love to hear about them!