Showing posts with label Linux. Show all posts
Showing posts with label Linux. Show all posts

2009-05-04

Shell History Stats

Inspired by reading an old thread on my local Linux user group mailing list:

$ history | awk '{a[$2]++ } END{for(i in a){print a[i] " " i}}' | sort -rn | head

94 povray
58 source
55 ./wacdump
32 l
31 cd
25 dcraw
22 cp
21 gimp
20 less
19 gvim

:) I should run that more often. Maybe feed to Twitter. Or not.

2009-05-02

Arduino mouse control for Pure Data using Expect

Here’s a little Expect script for getting a control stream into Pure Data, in my case from a butchered Genius serial mouse that I wrote an interrupt-driven Arduino driver for. The driver sends a “+” or “-” down the serial line each time the optical rotary encoder in the mouse guts moves a click. This assumes the Arduino is connected on /dev/ttyUSB0 (e.g. on Linux). Use a [netreceive 3000] (or whatever port you like) in Pure Data to receive.

Note: this only uses one mouse axis, requiring two interrupts. Apparntley the Arduino Mega has six interrupt lines externally available, so I'll be adding another axis of control soon.

#!/usr/bin/expect

# Take Arduino mouse '+'/'-' stream and convert into Pure Data FUDI format, without buffering.

# To run:
# expect mouse-pd.expect | pdsend 3000

# TODO: this should probably use Expect's stty command to set the serial port up to match the Arduino program.

eval spawn -noecho cat /dev/ttyUSB0
log_user 0
while (true) {
 expect {
  + {send_user "1;\n"}
  -- {-} {send_user -- "-1;\n"}
 }
}

Here’s the Arduino code:

// Simple interrupt-driven driver for quadrature encoder input (e.g. from a disassembled photoelectric ball mouse).
// Many Arduino boards provide only two interrupts, I believe: INT0 (on pin 2) and INT1 (on pin 3):
const int intA = 0, intAPin = 2;
const int intB = 1, intBPin = 3;

volatile int A = 0, B = 0;  // For storing the pin states for future reference to determine rotation direction
int A_Prev = 0, B_Prev = 0;  // Should these be volatile, too?



void setup()
{
  // Configure digital input pins for interrupt-driven timing:
  pinMode(intAPin, INPUT); digitalWrite(intAPin, LOW);
  pinMode(intBPin, INPUT); digitalWrite(intBPin, LOW);
  
  Serial.begin(115200);
  
  // Read initial state of the pins:
  A_Prev = digitalRead(intAPin);
  B_Prev = digitalRead(intBPin);
  A = digitalRead(intAPin);
  B = digitalRead(intBPin);

  attachInterrupt(intA, changeA, CHANGE);
  attachInterrupt(intB, changeB, CHANGE);
}


void changeA()
{
  A = !A;
  output();
  A_Prev = A;
}


void changeB()
{
  B = !B;
  output();
  B_Prev = B;
}


void output()
{
  if (A == B_Prev)
    Serial.print("+");
  else if (B == A_Prev)
    Serial.print("-");
  else
    Serial.print('?');
}


void loop() {}

Microcontroller programming is fun, BTW! I’d never written a driver or an interrupt handler until two days ago.

2007-12-02

Accessing PostgreSQL from Tcl

From version 8.0 of PostgreSQL, the Tcl client library (pgtcl) has apparently been dropped from the core distribution. On Gentoo GNU/Linux, the Tcl client library does not seem to be built, even with the tcl USE flag. There are apparently three PostgreSQL-for-Tcl packages now available separately on PgFoundry:

AFAICT, pgtclng is the current one to get. I downloaded, built and installed this from pgtcl1.6.0.tar.gz and tested availability as follows:

$ tclsh
% package require Pgtcl
1.6.0

So far so good...

2007-10-26

Building QEMU on Gentoo

QEMU won't compile properly with GCC version 4. On Gentoo, you can revert to another installed GCC version using the gcc-config command:

$ gcc-config -l
 [1] x86_64-pc-linux-gnu-3.4.6
 [2] x86_64-pc-linux-gnu-3.4.6-hardened
 [3] x86_64-pc-linux-gnu-3.4.6-hardenednopie
 [4] x86_64-pc-linux-gnu-3.4.6-hardenednopiessp
 [5] x86_64-pc-linux-gnu-3.4.6-hardenednossp
 [6] x86_64-pc-linux-gnu-4.1.2 *

$ gcc-config 1
$ source /etc/profile
$ emerge -av app-emulation/qemu

2007-09-30

New Zealand Daylight Savings Time changes

From 2007, daylight savings time in New Zealand starts one week earlier and finishes two weeks later. My Gentoo system still had the old timezone information, and so wasn't going to switch over on Sunday September 30 as it should:

$ zdump -v /etc/localtime | grep 2007
/etc/localtime  Sat Mar 17 13:59:59 2007 UTC = Sun Mar 18 02:59:59 2007 NZDT isdst=1
/etc/localtime  Sat Mar 17 14:00:00 2007 UTC = Sun Mar 18 02:00:00 2007 NZST isdst=0
/etc/localtime  Sat Oct  6 13:59:59 2007 UTC = Sun Oct  7 01:59:59 2007 NZST isdst=0
/etc/localtime  Sat Oct  6 14:00:00 2007 UTC = Sun Oct  7 03:00:00 2007 NZDT isdst=1

Solution: update the timezone-data package:

$ emerge -av sys-libs/timezone-data

(Alternatively, download the timezone data source directly from ftp://elsie.nci.nih.gov/pub/tzdata2007g.tar.gz and compile using zic.)

And restart the Network Time Protocol server, for good measure:

$ /etc/init.d/ntpd stop
$ ntpd -qgx
$ /etc/init.d/ntpd start
$ # wait a few minutes, then check the time...
$ ntptime

Once NTP’s timekeeping has settled down, you might also want to set the hardware clock.

$ hwclock --systohc
$ hwclock --show

2007-09-13

Simulating profiles with Echomixer

Echomixer is a mixer control utility for Echo Audio sound interfaces (I have a Gina24 PCI) on Linux. These cards have quite a few settings to control, and don't seem to fit into the generic controller approach taken by alsamixer.

AFAICT, Echomixer doesn’t support anything like a profile or the loading of a specific settings file: it always uses the file ~/.Emixer_Gina24. I would like to be able to configure the card for different applications, such as multitrack recording, gaming, playing a DVD, etc. For example, for DVD playback, I want to use the internal audio clock so that the sampling rate can be set exactly, without the need to resample the audio (e.g. for 46.08 kHz audio playback for 24 FPS movies deployed as 25 FPS PAL @ 48 kHz), with the PCM output level at 0 dB. For multitrack recording, I want to use the external ADAT clock so I can record the additional 8 channels I have on a chained ADAT interface, with the PCM output level at around -9 dB so I can hear live stuff easily over the backing tracks.

TODO: details, scripts, etc.

Bah, only it looks like Echomixer doesn’t save the clock source in its settings file. Dang.

2007-09-12

Installing PAM package on NetBSD a bad idea?

While installing and testing the RoundCube Web-mail system on my NetBSD-based Web server and network router, I found myself unable to shut down Apache (even with kill -9). Eventually I relented and restarted the OS, ruining my uptime of about 160 days in the process.

When the system came back up, I couldn’t log in! After entering the username, I just got returned to the login prompt after the following rudeness:

login: Undefined PLT symbol "openpam_ttyconv (symnum=47)"

The kernel mesages also included something like:

PAM unable to dlopen(/usr/pkg/lib/security/pam_cracklib.so)

Network access to the machine seemed to be down as well. Not the best scenario for trying to fix anything!

A reboot into single-user mode (-s kernel bootloader option) or two later, and some fun trying to research and resolve the problem with my main network router out of action(!), and I discovered that networking was OK after all, and I could ssh in and try to fix things.

It seems installing the PAM pluggable authentication modules system from pkgsrc was the culprit. I can’t remember when or why in the last 160 days I did this, but apparently I did, and it didn’t cause any problems until the recent reboot. It seems the login program was being dynamically linked to the PAM library from the package, not the main system one (which apparently already existed). With the extra PAM package installed, ldd /usr/bin/login showed that it was linking to /usr/pkg/lib/libpam.so.0, which didn't work. After uninstalling the extra PAM package, it was linked instead to /usr/lib/libpam.so.0, which worked fine.

AFAICT, there are two PAM libraries in pkgsrc, in addition to the main system one: openpam and Linux PAM (I think the one I had installed was the Linux one, PAM-0.77nb5).

Windows WinPopUp messages and Linux

I've known for a while that Samba provides a WinPopUp client, for sending instant messages to Microsoft Windows clients over the network. It’s a facility of the smbclient utility, and can be used like so:

$ smbclient -M SomeWindowsBox
Connected. Type your message, ending it with a Control-D
Hi, Windows user!
sent 19 bytes

The user on the computer named SomeWindowsBox will see the message pop up on their screen (possibly stealing focus and making an annoying dinging sound).

smbclient will also accept input from stdin. For example, to report disk free space remotely:

$ df -h | smbclient -M AdminMachine

It turns out you can also receive such messages on Linux, via Samba’s smbd server daemon. To enable this, add a message command directive in the Samba configuration file of the receiving system (usually /etc/samba/smb.conf). Here is the example from the smb.conf manual page:

message command = csh -c 'xedit %s;rm %s' &

This didn’t work on my Gentoo box for a number of reasons: I hadn't installed the csh or xedit commands, for a start! I also have two X Window System displays, and wanted the pop-up messages to appear on a specific display, requiring the DISPLAY environment variable to be set. Also, I had to use xhost to tell the X server to allow xmessage from the local system to display its goodies.

Here is the setting that I ended up using in smb.conf:

message command = /bin/bash -c 'export DISPLAY=:0.1; /usr/bin/xmessage -file %s; rm %s' &

TODO: integrate with the Ion window manager, perhaps to get the message to appear in an appropriate frame without stealing focus, etc.