Thursday, February 23, 2006

lab 57 - createuser

NAME

lab 57 - createuser

NOTES

I've tried setting up some services for the Inferno community. See Getting Started on the Inferno wiki for how to create a user id.

There is a public signer, registry, and kfs. If you mount the registry you might find a couple more.

Use the certificates for your services too. You can create an id, get a certificate and announce some of your own services using the registry then anyone else using the same signer should be able to mount your service.

Acme makes a remarkable collaborative environment. With wiki and irc clients and the shared kfs, a common naming convention for mounted services, it's a wonderful thing to type paths or commands using one or these channels and have others read and execute the commands. I hope these servcies and the Acme environment mean people interested in inferno and connect in new ways.

Most of the services are commands that come with the standard Inferno. What I had to create for this experiment is the createuser file system, which is a single file that accepts writes of username and password pairs. If the write is successful then the new id is created otherwise the write returns an error message.

The command is based on changelogin. I took that code and added a file2chan interface.

FILES

caerwyn.com/lab/57

Local mount tcp!canto.hopto.org!6669 /n/canto
/n/canto/usr/caerwyn/lab

Sunday, February 19, 2006

lab 56 - acme web

NAME

lab 56 - acme web

NOTES

I started using charon again because I wanted a web browser that started faster and used less memory than firefox. I wanted the browser to check my gmail account and scan reddit etc.

But after implementing cut & paste (lab 55) I found it frustrating all over again to not be able to cut & paste from charon. So I started looking for a solution to that. I began by just dumping the text to stdout. Since I was always starting charon from inside acme the stdout would go to an acme window. Then I thought I might as well write directly to a new acme window, so I built an acme client to charon. Then I added the links handling, which was pretty easy, and tada! a charon hack turns into an acme web browser. And a surprisingly good one too, since charon is doing all the work.

The links appear in acme as superscript numbers to the anchor text. Right-click on the number or word to follow the link. Only one link can be handled at a time. You can minimize charon once it's started and browse within acme, falling back to charon when needing to enter form input. But with plumbing turned on in acme, and the right plumbing rules, it's also easy to just type in the URL in acme and right-click on it, which then opens a new acme window on the URL.

There is no forms handling yet. But it should not be too difficult. I'll do an update to this lab, hopefully soon, with some support for forms.

Follow these instructions assuming you are in the /usr/caerwyn/lab/56 directory.

% cp acmewin.m /module
% cp acmewin.b /appl/lib
% {cd /appl/lib; mk acmewin.install}
% cp charon.b chutils.* /appl/charon
% {cd /appl/charon; mk install}

Then inside Acme run the following.

charon -doacme 1

FILES

caerwyn.com/lab/56

lab 55 - cut & paste

NAME

lab 55 - cut & paste

NOTES

this work includes some enhancements for running inferno hosted on windows. these are small details, but do seem to make a difference.

first is cut & paste between host and inferno. I copied the code from drawterm to do this. the file /dev/snarf contains the windows clipboard. typically one would say bind /dev/snarf /chan/snarf and everything works just great.

second is window resizing. in this case the host window is resized but the inferno windows all stay the same. but this still improves it. it's nice to be able to resize the window. however, for this to work the toolbar needs to be moved to the top instead of the bottom of the screen.

finally, i added /dev/fullscreen. writing anything to the file cases inferno to toggle fullscreen mode.

to use the changes copy devarch.c and win.c to /emu/Nt, and devcons.c to /emu/port.

FILES

caerwyn.com/lab/55

Wednesday, February 08, 2006

lab 54 - mux for 4th Edition

NAME

lab 54 - mux for 4th Edition

NOTES

Noah Evans is working on the GBA port. Inferno running on GBA and DS would be cool to see. It's exciting to think about the possibilities of running inferno on small mobile devices, especially if networking is included because that would draw on the strengths of inferno.

Inferno has already been ported to at least one PDA: the ipaq. But as far as I know there are no applications designed for use on a mobile device. Running acme or wm/sh on such a thing isn't worth making the port for. A GUI dedicated to the architecture has to be developed.

Let's use DS as an example, but also imagine mobile phones/PDAs, where we assume Inferno networking is available to the application developer. What applications are useful to run on the DS? (games count as useful) What's the GUI going to look like?

The device's constraints make an interesting challenge. Given a 240x160 resolution and cursor keys and A/B/L/R keys a new GUI and style of interaction different from anything else inside inferno must be developed.

Actually, maybe something suitable does exist. As a starting point to help explore the area I've updated the mux UI, which was intended for interactive TV using an IR remote. It's seems the closest thing that inferno currently has which does not assume mouse and keyboard interaction.

Mux was dropped from 4th edition. It requires the libprefab module in Inferno. To build an emu that includes do the following.

  • add the prefab.$O to the /libinterp/mkfile
  • add prefab to the lib and mod sections in /emu/Host/emu config file
  • recompile

The files for this lab include a mkfs archive that can be extracted on top of an inferno distribution. It's been mostly updated to 4th edition. Not everything works. But the demos show off apps that if scaled down to a smaller resolution would make a cool demo for the DS too.

I've put together a few screenshots.

mux4

Interaction with most of mux is using just a simulated IR remote using the keyboard keys i, m, j, k for up, down, left, right respectively. This is the kind of thing you can imagine operating with just your thumb.

I hope to come back to this, with a scaled down mux running in the smaller resolution, and maybe get the web, email, and a flickr image feed working.

FILES

caerwyn.com/lab/54

Sunday, February 05, 2006

lab 53 - granulator

NAME

lab 53 - granulator

NOTES

I want to revisit the DSP code I worked on in earlier labs (3, 4, 5, 6, 7, 10, 12, and 13). The STK C++ library it's based upon has been updated since then. The latest versions include an implementation of a granulator, which is something I've wanted to do for a while.

Granulation samples the music at tiny intervals then plays the grains back as many overlapping voices. With granulation the music speed can be dramatically slowed down but still retain its pitch. A good example of this is 9 beet stretch a granulation of Beethoven's 9th symphony played over 24 hours. I often listen to it at work. It blocks out surrounding chit-chat, and it isn't as distracting to me as most music. I can't listen to pop or classical music because I get tired of the repetition or else the music might interrupt my train of thought. With granulated music I can setup a playlist of three hours of barely interesting noise and get into "the zone". (At home I tend to listen to Drone Zone from Soma which has much the same effect as granulated Beethoven.)

I want to dump the signalfs code I did last year, and go back to just implementing the DSP library, translating the STK C++ code to limbo. This means I need to re-implement the sequencer module to load Instrument modules that are based directly on the DSP library. I think signalfs didn't work out too well. In the context of this application the whole filesystem structure and converting between real and PCM byte stream didn't seem worthwhile.

In this lab I include the implementation of the granulator. At the moment it's setup to read and play one channel at 22050 rate. It's a start. Here's an example of recording some noise from the microphone, granulating it and playing it back. Granulator takes as argument the stretch factor and the number of voices, as well as the raw PCM file to granulate. The scope just provides some visual feedback to the noise you're making.

% bind -a '#A' /dev
% echo rate 22050 > /dev/audioctl
% echo chans 1 > /dev/audioctl
% scope < /dev/audio > record1
# kill scope when done
% granulate -s 20 -v 16 record1 > record2
% stream record2 > /dev/audio

I'll be working on instruments and a new sequencer slowly over the next 40 years.

If there's an overall goal I have for this it's not to build a sequencer or synthesizer like the many already available. I'd like to build something for the computer to generate music. Implementing the STK is my starting point to learn about computer music. I like projects like 9 beet stretch, or Eigenradio. I'd like a continual stream of Inferno music generated from combinations of environmental sounds, radio, samples, keyboard playing. Because Inferno rocks!

FILES

caerwyn.com/lab/53

Friday, February 03, 2006

lab 52 - text files

NAME

lab 52 - text files

NOTES

Some limbo programs can be replaced with shell one liners, and others can be replaced with more general programs that reduce the limbo line count but increase functionality. I'll look at the few I've discovered.

The /prog filesystem exposes a textual interface that allows existing software tools to work with it. This implies I do not need a custom set of limbo tools to read and write to this filesystem. For example, ps is a 61 line limbo program, but I can do the same thing in one line of shell,

fn ps {sed '' /prog/*/status |sort -n}

This is the great power of Inferno. Simple textual interfaces exposed as files and a small set of software tools working together. Therefore, I can also try rewriting kill and broke. In this case I make the functionality more like Plan 9. Each command writes to output the commands that can be sent back to the shell to actually perform the kill action.

fn kill {
 sed -n '/' ^ $1 ^ '/s/^ +([0-9][0-9]*) +(.*)/echo '^
'kill >\/prog\/\1\/ctl # \2/p' /prog/*/status
}

fn broke {
 sed -n '/broke/s/^ +([0-9][0-9]*) +(.*)/echo '^
'kill >\/prog\/\1\/ctl # \2/p' /prog/*/status
}

This reduces the limbo line count a little more. It also is more suggestive of what can be done when filesystems are implemented with an appreciation of the encompassing system. Take this example from Plan 9 translated for Inferno which shows who is logged into the system:

fn who {
 ps | sed '/Broken/d
 /Exiting/d
 s% +[0-9]+ +[0-9]+ +([a-zA-Z0-9]+) +.*$%\1%' | 
          sort | uniq
}

The /net filesystem also exposes a textual interface. I can implement netstat as a script too (almost, it doesn't include the user name, but i wanted to keep it short).

fn netstat {
  for i in /net/*/[0-9] {
    echo  $i `{cat $i/status $i/local $i/remote}
  }
}

Lookman has bothered me because it could be more general. This is obvious if you're aware of the look command from Plan 9. Why not just port look and wrap it in a shell script to implement lookman?

fn lookman {
 look $* /man/index | sed 's/^.* //' |sort 
          |uniq |sed 's;/man/;;
           s;(.*)/(.*);man \1 \2 # \2(\1);'
}

I've again taken the idea from Plan 9. In my opinion this is better than the Inferno original. It prints the man page reference syntax, which works beautifully with Acme plumbing. I've included the source for the look port in this lab's files.

Another not-general-enough implementation is src. It is supposed to print the source file for a named dis file. The problem here is that the dis file is binary format so it needs a limbo library to extract the source file name. How is this done in Plan 9's src script? It uses adb. Well I don't have that. But I do have mdb. Maybe I should extend it with a few commands to examine a dis file. This would replace wm/rt which doesn't really fit in the system because it can't be used within scripts. So now src can be made a script, and changed slightly

fn src {
 file := $1
 if {ftest -e $file} {
  mdb $file '$s'
 } {ftest -e $file.dis} {
  mdb $file.dis '$s'
 } {ftest -e /dis/$file} {
  mdb /dis/$file '$s'
 } {ftest -e /dis/$file.dis} {
  mdb /dis/$file.dis '$s'
 } 
}

Okay, one more. This is a script to implement calendar but not as feature rich as the UNIX version. The calendar file is a list of multi-line records separated by blank lines, with any line in the record matching the date format 20060203, or just 0203 for recurring appointments, for example. This uses the xp command from lab 50.

fn calendar {
smon:='s/Jan/01/
 s/Feb/02/
 s/Mar/03/
 s/Apr/04/
 s/May/05/
 s/Jun/06/
 s/Jul/07/
 s/Aug/08/
 s/Sep/09/
 s/Oct/10/
 s/Nov/11/
 s/Dec/12/'
 (d m md tim tz yr) := `{date |sed $smon}
 xp ',x/(.+\n)+/ g/('^ $yr ^')?'^ $m ^ 
   $md  ^ '/p' $home/calendar
}

Textual manipulation with pattern-action languages is the hallmark of Plan9 and Inferno. File systems that expose textual interfaces play well with the rest of the system. However, sometimes in Inferno it feels like this isn't exploited or is hidden below the surface. Either because commands are implemented in Limbo when they don't need to be, or because a more general tool could exist based around the command line and not the wm GUI.

I have made the mistake in earlier labs of implementing tools around binary formats, or exposing binary interfaces from filesystems. After looking more closely at the elegance of /prog and /net I'd try to emulate their example.

FILES

caerwyn.com/lab/52