Tuesday, December 1, 2009

Love and Hate with Asterisk

For a year or two I have been running an Asterisk server. It has been wonderful. Recently, I wanted to add the new Skype functionality to Asterisk, so it required that I move from an old Apple X Serve to an x86 based machine. In the process, I figured I would upgrade from Asterisk 1.4, to 1.6. It should be simple, right?


Umm.. Yeah... Something like that. My configuration consists of a Sipura/Linksys/Cisco SPA-3102, the Asterisk server, and a collection of random VoIP phones around the house. By just moving the configurations from the old server to the new one, I was able to get the VoIP phones to talk to each other, along with being able to make outbound PSTN calls. This left me with three major headaches for the migration.

1. Calls from VoIP phones to the analog port on the SPA failed.
2. Inbound calls from PSTN->Asterisk weren't routed to the phones.
3. My custom AEL scripts to stop annoying people were broken.


Fixing #1 was pretty easy. The failure was coming from the fact that I had some events in the extension that couldn't be executed, so Asterisk would stop working through the list. (Or, in a nutshell, #3 was the cause of #1.) By changing the events back to a basic "ring the phone" list, this problem was solved.

#2 was a real pain. The solution was ultimately stupid/annoying. (Isn't it always!?) In the sip.conf file, I had "insecure=very" set in the [spa3k-pstn] configuration. It would seem this doesn't mean the same thing in 1.6 that it did in 1.4. Changing the line to "insecure=invite" resolved that problem, and allowed inbound calls to work once again.

#3 is an adventure I have not yet undertaken. Stay tuned...

Sunday, October 18, 2009

Acer Aspire Revo as a MythTV frontend

When Acer released the Aspire Revo, a lot of people seemed to think it would make a good front-end for a MythTV box. The price point seemed reasonable, the hardware seemed capable, and the size was just right.

However, Acer decided not to release it in the US at launch. Unfortunately, my trek to the UK for the year had already passed by the time it was released. (I was also a little too early for the start of the Depeche Mode tour, but that is a different story.) So, I looked around in Japan while I was there this summer, and was unable to locate one in either Akiba or Den-den town.

But, it was unclear that it would have worked well considering only SVN had the needed VDPAU support for MythTV. But, when the Revo FINALLY showed up at Newegg for a mere $199.99, I jumpped and snapped one up.

I'll spare you specs of the box, since it is posted all over the net. If you are really curious which one I have, you can see the specs here : http://www.newegg.com/Product/Product.aspx?Item=N82E16883103228&Tpk=Acer%20Aspire%20Revo .

Once I got the box, I loaded Gentoo Linux on it, and grabbed the 0.22rc1 release of MythTV from the MythTV site. I also loaded up the latest beta driver from NVidia's web site so I could be sure to get support for the ION chip in this box.

In a nutshell, the Revo is a pretty good option for someone looking for a fairly no frills front end for MythTV. There are just a couple of issues to watch out for.

First, MythTV wants your VDPAU enabled board to have 512 Megs of RAM, minimum. In the stock configuration I ordered from NewEgg, the box only comes with 1 Gig of RAM. The maximum amount of RAM that the BIOS will allow to be assigned to video is only 256 Meg. In my initial testing, this worked okay, but it is always a good idea to meet the specs of the software you are running. (It will usually result in less pain.)

My theory was that if I upgraded the RAM, perhaps the BIOS would let me assign more memory to the video card. So, I dug up some SODIMMs that I had laying around the house. (Yes, I know.. Most people don't have SODIMMs laying around the house. ;) A little bit searching around on Google, and I found this video on how to open the case : http://www.youtube.com/watch?v=7ayQOyTEWRw . The video suggests the use of a flat-head screw driver to pry the case open, but I found that less damage was done to the case if I used the slot cover from a desktop case instead.

Once the box was open, I slapped the 1 Gig SODIMM in the available slot, booted the machine up, and checked the BIOS. It allowed me to up the video memory from 256M to 512M. Mission accomplished!

So, how well does it REALLY work? I think the answer to this will come only after a few weeks of using it. But, in my tests, with VDPAU running, and watching live TV from a 1080i source, the CPU sat at about 12-13%. This was without any form of deinterlacing enabled, so it may well be higher when I get around to messing with that. The box also managed to play DVDs, and FLAC audio with no problems.

So, a Myth frontend for $199.99? There has to be SOMETHING wrong with it! It is too good to be true! Well, I am not sure I would say that there is anything "wrong" with the box, but there are some things that you may want to consider before picking up a Revo. One of the most glaring is the lack of any form of digial audio out. For me, this is a non-issue since I am hooking it up to a TV that only has stereo anyway. But, for some, this may be a good enough reason to steer clear of this system. The box also has two other annoyances. First, the only audio jack is on the front. So, if the box sits somewhere that people might see it, the audio cable will be sticking out. Second, the power LED on the box is a bright white LED on one of the corners. If you were going to put this in a room where you wanted it to be dark at night, this could be an issue. However, solving this is fairly easy. A little bit of painters tape from your local hardware store should be enough to dim the light on the box.

If you need a front-end that is similar to the Revo, but has optical or other features, you might check out the mainboards that NewEgg sells. I saw a few of the Atom boards with the ION chips on them. Many of those included all of the outputs you could possibly want.

But, at the end of the day, a board with an Atom processor, and an NVidia ION chip is plenty for driving a MythTV frontend.

Monday, October 12, 2009

Of Androids and USB

In general, I am a fan of the Android phone. (In case you couldn't tell.) But, I just spend 2 hours fighting with a myTouch3g trying to get it set up so I could use it as a debug target.

Now, in general, I suspect most people won't have this type of problem, since I am fairly sure it is the result of previously having my system configured to debug on my ADP1. But, if you happen to run in to this problem, here are some things that might help.

1. Download USBDeview from http://www.nirsoft.net/utils/usb_devices_view.html .
2. Unplug your phone from the computer.
3. Run USBDeview, find everything listed as an Android device, and uninstall it.
4. In the Android SDK, run "adb kill-server"
5. Make sure your phone is configured for development, and plug it back in.

This should cause Windows to find it again as if it had never been plugged in. It should give you the option of installing the ADB driver from the latest version of the SDK.

Once I had done this, the phone didn't immediately show up. To fix that, I left the phone connected, and toggled the development checkbox. After that, it showed up and I could use it.

Friday, September 18, 2009

Calling my app from a MIME type in Android

It seems like this is something that people might want to be able to easily do. But, surprisingly enough when I google this, I get a lot of posts with people saying, "How do I have my app get called when the browser reads a certain MIME type?"

Here is your answer.

It is really fairly simple. In fact, most of what you need to know is included in the Notepad sample app on the Android SDK site! But, there are some minor details missing.


If you follow what is available on the Android SDK site, you would add a new <intent-filter> to your manifest, that would look something like this :

<intent-filter>
<action:name="android.intent.action.VIEW" />
<category:name="android.intent.category.DEFAULT" />
<data:mimetype="testtype/testtype" />
</intent-filter>

Then, you just need to have a web server that can serve up our "testtype/testtype" MIME type to make it work, right?

Well, to test that theory, I hacked up this cute little piece of PHP, and stuck it on a local web server :

<?php

header("Content-type: testtype/testtype");

echo("Testing!");
?>

Note : Your web server will have to be able to run PHP for this to work! You are on your own to figure that out.


I named this PHP script test.php, and dropped it in the root share for my web server. Then, I pulled up the Android browser, and went to the web page : <myserver>/test.php .

What happened, was underwhelming to say the least. The phone downloaded a file called test.php. If I then tapped on the file name, it would start my application. So, I knew I was close.


After more digging around, I discovered the magical incantation. The MIME type line needs to know that we want to look specifically for things downloaded via http. So, I made a small change to my manifest file. The MIME type line now looks like this :

<data:mimetype="testtype/testtype" scheme="http">



Then, I ran the same test again, and my application was now loaded when I attempted to pull up the .php script that issued the testtype MIME type.

Monday, September 7, 2009

Its ALIVE!!!!

Well, I just dropped my first Android application out on the Marketplace. "Movie Track" was my first attempt at an Android program, and has been really useful to me. I only put it out there in hopes that others might also find it useful. When it comes right down to it, the app isn't super flashy, and isn't something you would show your friends to convince them how cool the android is. Instead, it is the first of hopefully many programs I will be releasing to the marketplace.

So, if you happen to have a MythTV box, and a lot of movies, give my app a try!

Tuesday, September 1, 2009

Side-by-side.. The lazy Android method..

One of the coolest things that the Android has out of the box is the "side-by-side" screens that make up the home screen. For a project that I am working on, it seems like this type of layout would be really useful. So, I set out trying to find out how to do it.

A bit of Googling found this article. I grabbed the code, threw it in Eclipse, and tried to make it work. Along the way Eclipse pointed out to me that the AbsoluteLayout has been deprecated. Because of that, I decided not to spend a bunch of time trying to figure out why my first few attempts using the code failed.

A bit more looking around found the HorizontalScrollView class. Using that class, along with a little creativity allowed me to make something that let me have a single really wide screen. But, what I wanted was something that snapped to the left or right to keep a single "screen" in focus.

The previously mentioned article had the code I needed to catch the events of a user dragging their finger across the screen. So, all I had to do was figure out how to put it all together. The end result is the HorizTwo class, which creates two "virtual screens" that snap to the left and right based on how far the user drags.

You can find the code on my download page here.

This code is really simple, and makes some potentially bad assumptions about the size and format of an Android screen. But, it seems like a good place for someone to start if they wanted to be able to have "side-by-side" screens.

There is one key point that may not jump out at you when you first look at the code. When you create the layouts that you want to show in each of the virtual screens, you need to give the layout an id. Normally, the Eclipse tools won't do this, so you will have to manually hunt the id field down, and set it. If you don't do this, you may not get the results you want.

Sunday, August 30, 2009

Orientation of an Android screen...

This issue has been vexing me for a few weeks now. I have found several different e-mail threads, and blog posts that talk about this exact issue, but none of them really seemed to have the answer I was looking for. So, hopefully this helps someone else.

I have been working on a small Android app that, in a nutshell, goes out to the internet, grabs an XML file, parses it, and sticks it in the local database on the phone. Currently, I am writing ~937 records in to the database after reading this XML file. Needless to say, this takes some time. As a result, I throw the work in to a thread, and then put a dialog on the screen indicating that I am working on it.

The code I am using to spin up the thread is here (modified to make it short and sweet) :

new Thread(new Runnable(){
public void run(){
try {
dp = new XMLDataParser(getURLPath());

dp.parse();
System.out.println("Update db.");
updateDatabase();

} catch (Exception e) {
System.out.println("Exception : " + e.getMessage());

// Display an error.
}
}
}).start();


Hopefully, this code is pretty straight forward. It spins up a new thread, initializes the XMLDataParser class, while passing in the URL that I am getting the data from. If you were to add this code to a project, you would find that a thread was spun off, and was doing its thing. (Though, you wouldn't really be able to tell that it was actually doing anything. We'll get to that in a second.)

You could just throw up a progress dialog with a spinner before you start the thread, and then attempt to close the dialog when the thread is done. In my adventures, I attempted this, and actually managed to make it work! There are even supported ways to make the dialog go away when the thread is done. However if you do this, you are going to end up in one of two "difficult" situations :

  1. When the screen orientation changes, the thread will finish running, but your progress dialog will go away.
  2. When the screen orientation changes, the thread will try to access something in the Activity that was destroyed by the OS, and you will crash.
While option #1 would work, it probably isn't really what you would want. What you REALLY want is for the progress dialog to continue to display and update.

So, how the heck do we make that happen?

Well, we know that when the screen orientation changes the current Views and Activities are destroyed, and new ones are created. A little bit of messing around will also show us that the thread we started continues to run even after the Views and Activities are destroyed. So, "all" we need to do is figure out how to make it so that the thread can communicate with the newly created Views and Activities.

So, lets break this down in to two parts.

  1. Making something survive the screen rotation.
  2. Having that something update our newly created Activity and Views.

How to survive a rotation

If you have done much development, you may think the magic way to deal with this is to stick something in your bundle that will be passed to the newly created Activity. While it is possible that you might be able to make that work, we want to have an entire object survive the restart. To do that, we need to add onRetainNonConfigurationInstance() to our activity class. When the screen is rotated, this method is called, and allows us to return a class (derived from Object) that can be retrieved from the new Activity. Generally, you want this method to do as little as possible, since it will be called during the screen rotation. Here is a bit of code from my application showing the call :

 @Override
public Object onRetainNonConfigurationInstance() {
return myGUIUpdateHandler;
}


All we are doing is returning the object that we want to have access to when our current activity is destroyed, and the new one created. Once the new Activity is created, we can get the pointer to the object back by calling getLastNonConfigurationInstance(). Once we have done that, we will again have access to the object that we were attempting to save.

Which brings us to :

Having something update our newly created Activity and Views

Now, for the fun part. We can pass an object between the two Activities, so now we can just pass the ProgressDialog object we were using, call .show(), and everything just works, right?

No, not really. The ProgressDialog will be bound to our old View that was part of the Activity that was destroyed. So, attempting to work with it would end up crashing our application.

Instead, we want to create a handler that will allow us to pass messages between threads. In the Handler class, we want to override the handleMessage() method so that when a message comes in, we can do something with it. Here, again, is a sample from my code :


public class ThreadEvents extends Handler {

// Set up a random unique ID for message handler
public static final int UPDATEDATA = 12346;

// @Override
public void handleMessage(Message msg) {
switch (msg.what) {

case UPDATEDATA:
System.out.println("Thread sent us an update data event.");
break;

default:
break;
}

super.handleMessage(msg);
}
}

In this handler class, when the UPDATEDATA case is called, we want to update our UI thread. This could be something such as updating the status bar in our program.

The last piece of the puzzle is how to actually send events to this handle so that we can process them. The first thing that needs to be done before a thread can send a message through a handle is the handle class needs to be created prior to the thread being started. By doing that, the child thread will also have a pointer to the handler class. Then, any time the thread wants to send something to the parent thread, it only has to do something like this :

message = new Message();
message.what = ThreadEvents.UPDATEDATA;
myGUIUpdateHandler.sendMessage(message);


The final trick to making the ProgressDialog survive a screen rotation is to create a new instance of the dialog when an activity is started, and there is an object available from getLastNonConfigurationInstance(). Then, to update that new ProgressDialog instance as events come in from the child thread.


Final thoughts :

Obviously, I have not provided enough sample code here to do a full implementation. That never was the goal, so please don't post a follow-up asking for it. It is my experience that people that have to work a little to obtain knowledge keep it longer. My goal was to point you in the right direction so you can put the remaining pieces in place.

I also suspect that it might be "better" to use an AsyncTask to achieve the same ultimate result. However, this is the first method I discovered to achieve my goal. In the future, I intend to try doing the same thing with an AsyncTask, and will post another entry when I get around to that. In the mean time, this method seems to work well as I have been able to rotate the screen back and forth several times during a long operation without crashing my application.

The insanity that is....

Welcome to my new and improved blog! (Yeah, lucky you, right?)

While I enjoyed hand blogging via my web site, it turned out to be a bigger pain that I thought it would. So, I decided I would just snag an account on Blogger, and have GeekTaco.info forward people here. The end goal is to spend a little more time blogging, and a lot less time maintaining the site! This will leave the site available for more useful things, like links to useful files.