Monday 15 December 2008

Media MVP Slideshow

I want to create a simple slideshow viewer for the Hauppauge Media MVP.
The user interface has to be simple, requiring no intervention other than powering up, because it is for our Autistic son and he does not press buttons. I am intending to make a really big bright, easy to press button for him to power on the unit, and it will shutdown after a set period.

Mvpmc almost does what I want, but you have to use the remote control to select an image to display before it will go into slideshow mode. I am not keen on the mvpmc code - it has lots of 'modules' to do different functions, but the code is all interwoven, so it takes a bit of un-picking. Therefore I thought I would go for something simpler. Fbi is a simple frame buffer image viewer which should do the trick. After much messing about I got it to compile, but unfortunately it complained that the MVP /dev/fb0 was not behaving like a standard linux frame buffer. I gave up on fbi at this point and decided that un-picking the mvpmc code would be easier - at least I know it is capable of displaying images.

I updated main.c and gui.c in mvpmc to add a new command line startup option --startup slideshow:file=.

Sunday 30 November 2008

Cross Compiling for MediaMVP

I have a couple of Hauppauge Media MVP media players and I want to turn one into a customised photo view for our son - it will have to be very simple because he will not press buttons, so I want it to just start as soon as it is switched on, and provide a customised "Hello Benjamin" screen as it boots.

The mvpmc project should provide most of what I need, so I just wanted to build a cross compiler and have a play. I downloaded the binary distribution and got it running ok (needed a dhcp and tftp server on my little computer in the atic to do that), and the binary distribution of mvpmc works fine.
I downloaded the source. It says it is supposed to build its own toolchain if you do not have one, but this did not work - it ran for a long time, then complained about bits of the toolchain not being there.

I thought I was too clever for that and I would just do it myself using crosstool. This failed with obscure syntax errors, which was hard to believe.
I eventually read that building cross compilers with recent versions of gcc is troublesome, so I installed an old one instead (gcc.3.4.6 from the Ubuntu repositories). It worked ok and built a PPC-405 cross compiler for me.
Unfortunately my "hello world" program compiled ok but would not run - the MVP responded with "not found" when I executed ./hello_world. I think this is because the MVP is using uClibc, but I had just build a cross compiler with gLibc. "oh dear...".
Next tried the Embedded Linux Development Kit (ELDK). Again "hello world" compiled ok, but got the same "not found" error.

Looks like I will have to find out why the mvp toolchain build failed.

Hunting a very long way back in the build log showed that the first error (that I spotted) was when it tried to download the linux headers to compile against. It looks like the uClibc website has been rearranged and the ones that the MVP needs have been moved to a "old-releases" directory. Downloading the file and putting it in ~/downloads like the mvpmc build script does resulted in the build running apparently ok - still hasn't finished though....

OK, it's finished now, and the new toolchain compiles a "hello world" that runs ok!

Now I just have to strip out the mvpmc code down to a very simple viewer, and it should work.....sounds easy, but it's getting late now...

Friday 28 November 2008

autoconf / automake / aclocal

I am trying to build Music Player Daemon for the FreeCom MusicPal. I have written an output plugin that I think will drive the hardware, but now I am having trouble compiling this into the MPD source code. I have never really understood the GNU configure scripts (./configure and all that), so I have probably messed something up.
I have added new bits to configure.ac, Makefile.in etc. But now what do I do?

As far as I can tell from the simplest tutorial I can find suggests that I should just be able to edit configure.ac and Makefile.am then run autoconf, but it complains that the files are designed for automake version 1.6, and I have 1.10. The error suggests running aclocal, but this just leads to more errors....

Sunday 23 November 2008

Progress with MusicPal Sound Programming

After a couple of hours of using strace to try to understand what Nashville was doing, and looking at the "base_audio" directory in the MusicPal kernel source directory, I have finally got it to make a noise.

Basically you have to use /dev/audio and send some ioctl's to initialise the hardware, and set up the graphic equaliser. You can then write raw data to /dev/audio just like you would with OSS. In fact, I used the OSS sinegen.c example program as the basis and just altered the ioctls. http://www.musicpal.webhop.net/audiotest.c is my sample program (it needs audio.h from the MusicPal kernel source code to compile) - it makes a continuous tone come out of the MusicPal speaker, which is progress! There are some comments in the code to show what it is doing (as far as I can work out anyway!).

MusicPal Debug Tools

I am trying to get sound playback working in my own code on the MusicPal. I have been advised to use a utility called 'strace' which allows you to monitor what system calls an application is executing - this should allow me to see how nashville initialises and uses the sound system on the MusicPal (http://forum.freecompromo.com/viewtopic.php?p=22633#22633).

I downloaded the source code for strace from sourceforge. It uses the standard gnu ./compile system to configure and compile it.
I got it to compile for the MusicPal using:
source ~/alinux/setvars; CFLAGS=-I~/alinux/linux/include ./configure --host=arm-linux
make

It compiled ok, and won't run on my PC, which is a good indication that it has cross compiled.
The problem is that I can not transfer it to the MusicPal because the executable is about 290kB, and there is only 176kB free on the MusicPal /home directory.

Oh Dear....I think the MusicPal has quite a lot of RAM - I'll see if I can make a RAM disk - either that or I have to get NFS working on the MusicPal so I can mount a decent sized directory, or even more drastic, pull the MusicPal appart and put a USB socket in it to use a USB disk - easier in the long run, but this is supposed to be a present for my wife, so I'd better not.

Silly me - there is already a ram disk mounted as /tmp....

Saturday 22 November 2008

MusicPal Sound Programming

The MusicPal has a few devices that look like they are to do with sound:
  • /dev/dsp
  • /dev/mixer
  • /dev/audio
I know very little about audio on Linux, but from a quick read I thought that these looked like OSS devices. I downloaded the simple OSS sine wave generator example singen.c. It runs ok on my laptop, and cross compiled ok, but when I tried to run it on the MusicPal I got a "/dev/dsp: No such device or address" error. This makes me think that maybe it is not OSS - I'm going to have to learn more.

A couple of hours later and I might be getting somewhere. I tried doing fuser /dev/dsp and fuser /dev/audio. These both returned nothing with the main application (nashville) sutdown. Re-starting it with /etc/init.d/mainapp start, then repeating showed that /dev/dsp was still not used, but /dev/audio was used by the 12 running versions of /bin/nashville. This has persuaded me that Freecom use /dev/audio, not /dev/dsp.

So, what is /dev/audio, and how do I use it?

The source code provided by freecom contains a directory .arch/arm/mach-mv88w8xx8/base_audio. This might be a clue. It even contains a file called audio_api.h - is this a modified version of OSS, or something unique?

Tried doing cat file.au > /dev/audio and cat file.mp3 > /dev/audio - no sound at all if the machine had just been re-booted and nashville stopped, and had to CTRL-C to get back to the shell.

Re-started nashville, played a tune, put nashville into sleep mode, then stopped it. Repeated the cat xxx process - no sound, but dmesg showed "audio released irq disabled" messages, which come from audio.c in the base_audio directory.

Re-started nashville, and now this does not make any sound either - I'm definitely doing something to its sound driver....

Re-Booted. Set nashville playing, then stopped it with /etc/init.d/mainapp stop. Then did cat /usr/share/wakeup.mp3 > /dev/audio - got awful noise out of the speaker!

This is progress - I must have to do some initialisation to get it working, then send it data in the right format - just a matter of finding out how and what now - looks like audio.c might have some answers though...

My_MusicPal

I have added a page to the My_Musicpal Wiki on what I have found out so far:

Friday 21 November 2008

More on Writing to MusicPal Display

I've made some progress on writing to the MusicPal display now.
This is all written in C - haven't got as far as trying to make Python work yet.
I downloaded the Embedded Linux Development Kit and the MusicPal Linux source code from the FreeCom web site by clicking on the 'Legal Notice' link.
The source code included a directory .../alinux/linux-2.6.16.16/arch/arm/mach-mv88w8xx8/lcd_framebuffer which appears to be the framebuffer driver source code for the MusicPal LCD Display.
It included an example file "mvlcd_test.c" which did not work, but I managed to comment out the errors to get it to compile and run on the MusicPal - I transferred the executable to the MusicPal using wget on the MusicPal to download it from my web server. Most of the options to do with filling in the screen did not work, but the 'Write String' one did once I realised that you have to do 'manually refresh display' afterwards to see what you have done. It is also best to kill the MusicPal main application with:

/etc/init.d/watching stop
/etc/init.d/mainapp stop

Otherwise it overwrites the things you have written.

I have got a simple example running which shows text in three different fonts. The example program is:

#include
#include "glcd.h"
main() {
lcd_clear_screen();
lcd_set_font(0);
lcd_write_string("font0",0,0);
lcd_set_font(1);
lcd_write_string("font1",0,10);
lcd_set_font(2);
lcd_write_string("22:00",0,20);
lcd_redraw_screen();
}


This in turn relies on a simple library that I have started - glcd.c and glcd.h:
glcd.h

/*
* glcd.h
* Desc: Graham's simple interface to display text on the MusicPal LCD
* Display.
* HIST: 21nov2008 GJ ORIGINAL VERSIO
*/

extern int lcd_font_number; /* Default font - 0,1 or 2 */

int lcd_set_font(int);
int lcd_write_string(char *str,int x,int y);
int lcd_clear_screen(void);
int lcd_redraw_screen(void);
int lcd_poll_buttons(void);



glcd.c


#include
#include
#include "lcdwrite.h"
#include "glcd.h"

int lcd_font = 0;

int lcd_write_string(char *str, int x, int y) {
int fbfd = 0;
int retval = 0;
struct disp_string_lcd disp_lcd;
strcpy(disp_lcd.str,str);
disp_lcd.x = x;
disp_lcd.y = y;

switch (lcd_font) {
case 0:
disp_lcd.flags = STR_FLAG_FONT_6X8;
break;
case 1:
disp_lcd.flags = STR_FLAG_FONT_8X8;
break;
case 2:
disp_lcd.flags = STR_FLAG_FONT_24X24;
break;
default:
disp_lcd.flags = STR_FLAG_FONT_6X8;
}

printf("write_string: str=%s, x=%d, y=%d, flags=%d\n",
disp_lcd.str, disp_lcd.x, disp_lcd.y, disp_lcd.flags);
// Open the file for reading and writing
fbfd = open("/dev/fb0", O_RDWR);
if (!fbfd) {
printf("Error: cannot open framebuffer device.\n");
retval = -1;
} else {
if (ioctl(fbfd, MVLCD_DISP_STRING, &disp_lcd)) {
printf("Error refreshing.\n");
return 1;
}
}
close(fbfd);
return 0;
}


int lcd_clear_screen() {
int fbfd = 0;
int retval = 0;
// Open the file for reading and writing
fbfd = open("/dev/fb0", O_RDWR);
if (!fbfd) {
printf("Error: cannot open framebuffer device.\n");
retval = -1;
} else {
if (ioctl(fbfd, MVLCD_CLEAR_SCREEN, 0)) {
printf("Error refreshing.\n");
return 1;
}
}
close(fbfd);
return 0;

}

int lcd_redraw_screen() {
int fbfd = 0;
int retval = 0;
// Open the file for reading and writing
fbfd = open("/dev/fb0", O_RDWR);
if (!fbfd) {
printf("Error: cannot open framebuffer device.\n");
retval = -1;
} else {
if (ioctl(fbfd, MVLCD_REFRESH, 0)) {
printf("Error refreshing.\n");
return 1;
}
}
close(fbfd);
return 0;

}

int poll_buttons() {
int fbfd = 0;
int retval = 0;
int buttons;
// Open the file for reading and writing
fbfd = open("/dev/fb0", O_RDWR);
if (!fbfd) {
printf("Error: cannot open framebuffer device.\n");
retval = -1;
} else {
if (ioctl(fbfd, MVLCD_POLL_BUTTONS, &buttons)) {
printf("Error refreshing.\n");
return 1;
}
}
close(fbfd);
return buttons;

}


int lcd_set_font(int font) {
if (font<0>2) {
fprintf(stderr,"WARNING: Font Number %d is an odd number - this might not work\n", font);
}
lcd_font = font;
}




This doesn't do much, but I can now display text on the MusicPal display, so I am progressing towards a replacement firmware for it - just a little way to go still!

NT

Wednesday 19 November 2008

Writing to the MusicPal Display

Made a bit of progress with writing to the MusicPal display.
There is a device /dev/lcd which looked promising, but I didn't know what to do with it, but then I noticed that /dev/fb0 links to it. /dev/fb0 should be a linux framebuffer interface to the graphics hardware. Unfortunately most of the guides I could find on the internet were not about how to program the framebuffer, but how to set it up. I thought I was going to have to resort to reading /usr/include/linux/fb.h to try to understand it. I was pleased to find that someone (lesky?) has done that and published a bit of code to work with the framebuffer here.
He provided some example code to open the framebuffer device and extract information about it from the hardware as shown below:

#include
#include
#include
#include
#include

int main()
{
int fbfd = 0;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
long int screensize = 0;
char *fbp = 0;
int x = 0, y = 0;
long int location = 0;

/* Open the file for reading and writing */
fbfd = open("/dev/fb0", O_RDWR);
if (!fbfd) {
printf("Error: cannot open framebuffer device.\n");
exit(1);
}
printf("The framebuffer device was opened successfully.\n");

/* Get fixed screen information */
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {
printf("Error reading fixed information.\n");
exit(2);
}

/* Get variable screen information */
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
printf("Error reading variable information.\n");
exit(3);
}

/* Figure out the size of the screen in bytes */
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;

printf("xres=%d, yres=%d, bits_per_pixel=%d\n",
vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);

/* Map the device to memory */
fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,
fbfd, 0);
if ((int)fbp == -1) {
printf("Error: failed to map framebuffer device to memory.\n");
exit(4);
}
printf("The framebuffer device was mapped to memory successfully.\n");

x = 100; y = 100; /* Where we are going to put the pixel */

/* Figure out where in memory to put the pixel */
location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +
(y+vinfo.yoffset) * finfo.line_length;

*(fbp + location) = 100; /* Some blue */
*(fbp + location + 1) = 15; /* A little green */
*(fbp + location + 2) = 200; /* A lot of red */
*(fbp + location + 3) = 0; /* No transparency */

munmap(fbp, screensize);
close(fbfd);
return 0;
}

Sunday 16 November 2008

MusicPal Internet Radio

I have bought a Freecom MusicPal internet radio as a present for Sandie.
It turns out that it is actually a little single board computer running linux, so I have to see what I can do with it.
Fortunately some other people have made a start as shown here. Most importantly they show that if you point your web browser at the musicpal and log in, you can run an extra CGI script as http:////admin/cgi-bin/debug.cgi. This allows you to switch the telnet server on and off in the MusicPal.
Once you have switched the telnet server on you can log into the machine as root and have a look around.
To do anything interesting with it there will be three main requirements:
  1. Read the keyboard (well the buttons on the device anyway!)
  2. Display things on the screen.
  3. Play music files.
I have made a start on this. The buttons can easily be read from /dev/keypad. Typing cat /dev/keypad shows the key currently being pressed. Note that there seems to be a delay between typing cat /dev/keypad and anything starting to appear - not sure why.
The codes returned are:
  • Fav - 1
  • Menu - 2
  • Volume Button Press - 4
  • Volume Button Clockwise - V
  • Volume Button Anti-Clockwise - v
  • Select Button Press - 8
  • Select Button Clockwise - N
  • Select Button Anti-Clockwise - n
  • No Key Pressed - T
That's a start anyway - displaying things on the screen will be more difficult - I'll ahve to find out what sort of driver is provided - there /proc/mvlcd looks like something to do with it, but I don't know what.....

NT

Thursday 6 November 2008

Fujitsu Li2727 Sound Problems in Ubuntu 8.10

I just realised that the sound on my Futitsu Siemens Li2727 laptop had stopped working - probably when I upgraded to Ubuntu 8.10, but not sure.
All you get when you play sound is crackling.
Dmesg gave the following:
[ 13.411005] HDA Intel 0000:00:1b.0: PCI INT A -> GSI 22 (level, low) -> IRQ 22
[ 13.411038] HDA Intel 0000:00:1b.0: setting latency timer to 64
[ 13.442811] hda_codec: Unknown model for ALC268, trying auto-probe from BIOS.
The 'Unknown model' looked like a problem, so I spent a while searching for solutions to do with this, but to no avail.

Found a bug report - https://bugs.launchpad.net/ubuntu/+source/linux/+bug/281322, which sounded like my problem, but was solved by adjusting alsamixer.
When I used alsamixer I only saw a single channel, which I think was the PC speaker, so it didn't sound right. Looked at https://wiki.ubuntu.com/DebuggingSoundProblems which said there was another program, gnome-alsamixer. Tried this and it showed me lots of different sound card channels. The volume of the PCM channel was zero - setting this to full volume cured the problem - Solved!

Monday 3 November 2008

Cross Browser JavaScript

I have been having terrible trouble making my daughter's 'Countdown to Christmas' google gadget work on internet explorer - works fine on firefox, but alas quite a lot of the world use IE, and on IE you just get a blank square.

IE is not helpful with debugging - it seems to be fussier about little problems that firefox let me get away with, so there were quite a few typos (no closing '>' etc.).

One significant issue was that I was attempting to scale the background image in html using width='100%' height='100%' - firefox stretches the image to fit, but within a google gadget at any rate, internet explorer just displays a blank square - no helpful error messages or anything - useful!
This means that my very clever bit of code to put the text in the correct position on the image doesn't work...Cured by forcing the image to a specified size in pixels rather than % - just means you have to size your page to fit it....This was not pretty, so had to solve it. Went for specifying width=100%, which works, and let the height float to preserve the aspect ratio of the image - just had to add yet more code to pick the vertical position of the text correctly.

The last problem was the dates - IE said there were about 600000 days to christmas, which was not quite right - this was because getYear() returns 108 in Firefox and 2008 in IE. Using getFullYear() cured it.

Sunday 2 November 2008

Wireless Networking in Linux on Fujitsu Siemens Amilo Li2727 laptop

I have a Fujitsu Siemens Amilo Li2727 laptop, which has a built in wireless network card.
Ubuntu Linux 8.10 detects the card as an AR242X (by typing lspci), but the madwifi driver compatibility page says it should be an AR5007EG.

The symptoms are that wireless networking does not work at all. dmesg reports:
"wifi%d: unable to attach hardware: 'Hardware revision not supported' (HAL status 13)".
No wifi devices present when doing ifconfig, iwconfig etc. There is one odd device (pan0) - I don't know what this is!

There are quite a few forum posts about this problem - they say that the madwifi driver can solve the problem, but you need to download a patch and re-compile the driver. When you download the patch the README file says the instructions are out of date, and you should use the updated madwifi driver as described in http://madwifi.org/ticket/1192. That page gives a link to the driver source code and the compilation instructions are stored in http://madwifi.org/wiki/UserDocs/FirstTimeHowTo. I followed these - they were very easy - first deleting the Ubuntu supplied copy of the madwifi driver, then compiling and installing the new one.

After re-booting I have two devices - wifi0 and ath0. iwconfig reports that ath0 has wifi extensions, so this looks promising.

Tried iwlist ath0 scanning - it reported that the network was down.
did ifconfig ath0 up. Then iwlist ath0 scanning says has no scan results, which is wrong because I am sat next to a wireless router...

Had a look at http://ubuntuforums.org/showthread.php?t=669267.
This got me looking at the Hardware Drivers manager in System/Administration - this said that there was a proprietary driver for the wireless card activated, so maybe this is intefering with things? Deactivated it..and rebooted again..

To start with, no wireless at all, but doing 'modprobe ath-pci' gave the following when I typed dmesg:

ath_hal: module license 'Proprietary' taints kernel.
[ 159.942692] AR5210, AR5211, AR5212, AR5416, RF5111, RF5112, RF2413, RF5413, RF2133, RF2425, RF2417)
[ 160.035904] ath_pci 0000:08:00.0: PCI INT A -> GSI 18 (level, low) -> IRQ 18
[ 160.035939] ath_pci 0000:08:00.0: setting latency timer to 64
[ 160.534217] MadWifi: ath_attach: Switching rfkill capability off.
[ 160.541042] wifi0: Atheros AR2425 chip found (MAC 14.2, PHY SChip 7.0, Radio 10.2)
[ 160.559097] ath_pci: wifi0: Atheros 5424/2424: mem=0xfa000000, irq=18
[ 198.800025] ath0: no IPv6 routers present

At least there are no errors....but still iwlist reports no scan results.

Another thing I have read about is that the Amilo does not power up the wireless adapter automatically - could the radio transmitter be switched off?

The madwifi compatibility page pointed to this article:
http://madwifi.org/wiki/UserDocs/MiniPCI#FujistsuSiemensAmiloLi2727withAtherosAR2425AR5007EG802.11abgPCI-erev01
This talks about downloading the acerhk hotkey driver source and compiling it, but
I found that it is already installed in ubuntu and doing 'modprobe acerhk' ran it without error.
I pressssed Fn-F1 a few times and nothing happened (apparantly), then I realised that to make the wifi led light you have to do that in software (echo on > /proc/driver/acerhk/wirelessled). Doing this put the led on, and iwlist ath0 scanning gave me a list of access points - Success!!!

It seems that the acerhk driver has the code to switch on the wireless transmitter by doing the echo command above, but the Fn-F1 key does not work.

Now the procedure to get wireless networking working after boot is:
modprobe ath-pci
modprobe acerhk
echo on > /proc/driver/acerhk/wirelessled
ifdown ath0
ifup ath0

This needs automating!...

Thursday 23 October 2008

framework.system.filesystem

Making a bit of progress now - framework.system.filesystem look like it should do what I want.
I have tried this:
function buttonClicked() {
debug.trace("ButtonClicked");
fname=framework.BrowseForFile("*|*.*");
oFs = framework.system.filesystem;
alert("oFs="+oFs);
if oFs.FileExists(fname) {
alert("file exists!");
oFile = oFs.GetFile("/home/graham/Countdown.js");
oStream = oFile.OpenAsTextStream(1,-2);
linstr = oStream.ReadLine;
alert("ofile="+ofile+" linstr="+linstr);
} else {
alert("file "+fname+" does not exist");
}
}
It looks promising - oFs is a real native object, which is encouraging, but I get an 'uncaught exception' error - still needs some digging into how it works!

Wednesday 22 October 2008

gadget.storage.openText()

A bit of progress with local file access.
It is nice and easy to get a file browser to open to select a file name, using framwork.BrowseForFile().
Still can't read it though. The nearest I have found is gadget.storage.openText(), which works nicely reading files stored in the gadget .gg file, but I can't get it to open other files....
Code for a simple button to demonstrate the above:

function buttonClicked() {
debug.trace("ButtonClicked");
fname=framework.BrowseForFile("*|*.*");
debug.trace("fname="+fname);

file=gadget.storage.openText("main.xml");

alert("file="+file);
}
Unfortunately code.google.com seems to be dead, or I was going to ask on the developer's forum....

Tuesday 21 October 2008

Google Desktop Gadgets

I've just discovered Google Desktop Gadgets. This site is for me to record things I have tried, so I can find them again.
Desktop Gadgets are simple javascript applications that run on Windows, Linux or Mac, which is neat. I use the Linux version.

A gadget is a simple zip file renamed to have a .gg extension. As a minimum it needs to contain three files, gadget.gmanifest, main.xml and main.js. .

gadget.gmanifest is a little file describing the gadget, so the Google Desktop application knows what to do with it.
main.xml defines the user interface of the gadget.
main.js is hte javascript code to provide the functionality.

When you install a gadget you get a warning saying that the gadget is being granted access to the local file system. This is good because the reason I am interested in them is that I have a web application which is a GPX route editor (http://www.maps.webhop.net) but I would like it to have access to the local file system so it can save its output file for you to put on your GPS device. I think it should be possible to port the application to work as a Gadget so it will retain its network capability with local file access.
It's just a matter of making it work.....

I am struggling to make local file access work, never mind anything more complicated!