May 2006

General

Comments (2)

Permalink

using Convert.ChangeType() on nullable types in C#

While writing a data loading routine in C# with .NET 2.0, I came across an apparent bug which prevented this method from converting a nullable type. A bit of Googling turned up a post by my brother Peter about this issue and a possible workaround.

I took his solution a step further and basically wrote my own ChangeType method which properly handles nullable types. I then got in touch with Peter about my solution and he suggested a better way of detecting the nullable type (I was just using a regex at first). Anyway, the end result is listed below.

In case you’re wondering why I check for a null value only after I determine that conversionType is nullable, it’s because I want the final Convert.ChangeType to throw the exception when conversionType can’t accept a null value, rather than causing the exception to be thrown in the caller.

public object ChangeType(object value, Type conversionType)
{
    if ( conversionType.IsGenericType &&
        conversionType.GetGenericTypeDefinition( ).Equals( typeof( Nullable<> ) ) ) {
 
        if(value == null)
            return null;
 
        System.ComponentModel.NullableConverter nullableConverter
            = new System.ComponentModel.NullableConverter(conversionType);
 
        conversionType = nullableConverter.UnderlyingType;
    }
 
    return Convert.ChangeType(value, conversionType);
}

General

Comments (1)

Permalink

quote of the week

Firefox Developer Blake Ross on his attending Time Magazine’s “Time 100″ dinner and walking down the carpet just ahead of Will Smith:

“That’s the first rule of red carpet walking: always look straight ahead. Keep your cool, and pretend that you actually belong one step ahead of the guy on television you idolized every school day for six years.

“I’ve spent the last two [years] trying to make sense of the whirlwind absurdity that has become my life. Dinner with the Fresh Prince on Monday, coding object serialization on Tuesday, venture capital strategizing on Wednesday, Belgian interview on Thursday… dorm meeting on Friday.”

General

Comments (4)

Permalink

converting vonage voicemails to mp3 (or ogg vorbis)

We have used Vonage as our phone provider for a couple years now and have loved the service. One of the many features they add at no extra charge is the ability to have all voicemail messages sent as an email attachment. Unfortunately, they only send these attachments in WAV format, which means they take up a ton of room.

I like to store all voicemails I receive in case I need them later, and so I was looking for a way to shrink those emails down. I found this post describing how to do just that using Perl and LAME to convert the attachments to MP3.

Unfortunately, that script didn’t work quite right for me. I have cleaned it up a bit and posted it here for anyone interested.

You need to call this script from your MTA as an “external filter”. The details of how to do this depend on your implementation. It will read the current email (with WAV attachment) on STDIN, and write the email with an MP3 attachment on STDOUT. It will also change the subject line to include the Caller ID info of the caller.

Up until sometime towards the end of 2005, I used the popular LAME MP3 encoder which is available for most Linux distros. However, Vonage then changed the format of their WAV files to use an algorithm called “CCITT μ-Law”, which LAME is unable to handle. So I switched to a new program called SOX, which bills itself as the “swiss army knife of sound processing programs”.

Requirements:

  • SOX
  • Perl with MIME::Parser module

As written, this script will convert Vonage WAV files to MP3. Converting to Ogg Vorbis or any other standard instead should be rather simple; simply read the SOX man page or website.

In the event that the incoming email does not contain an attachment, or the attachment is not WAV format, it will be written to STDOUT unchanged. In either case, the return status will be 0. But the best solution is to send only Vonage voicemail emails through this filter. Your MTA software may have a way to do server-side header checks and conditional filtering. Currently, voicemail emails come from an address which ends with “vm.vonage.com”.

This script differs from the one mentioned above in that it uses a tempfile instead of IPC::Open2. I was unable to get IPC::Open2 to work correctly, since it deadlocked when attempting to write to it. According to the author of IPC::Open2, this is a danger in using it with “streamy” programs such as LAME or SOX.

Because this script uses a tempfile for the SOX output before reading it back it, there’s a possibility of someone reading this tempfile while the script is running. This is a security problem if you have untrusted users. This isn’t an issue for me, since this is on a private server, but if it is for you (i.e. you have users which you don’t want listening to your voicemails) then be sure to create the tempfile in a directory which only your MTA has read/write access to (instead of /tmp), and/or use “umask” to ensure that only your MTA can read/write the file.

UPDATE 9/15/2006: I have also written a Perl script to grab Caller ID information from Switchboard.com, which can be used to add this info to your emails as well.

#!/usr/bin/perl

use MIME::Parser;

$parser = new MIME::Parser;
$parser->output_to_core(1);

$email = $parser->parse(\*STDIN);
$time = time();
$tmp_file = "/tmp/wavmailtomp3-$time.$$.tmp.mp3";

$attachment = $email->parts(1);

if (!defined $attachment or $attachment->effective_type() ne 'audio/wav') {
  # no attachment or non-WAV attachment; print original mail and quit
  $email->print;
  exit(0);
}

open(PIPE, "|/usr/bin/sox -t .wav - $tmp_file");
print PIPE $attachment->bodyhandle->as_string;
close PIPE;

if( open(PIPE,"<:bytes",$tmp_file) ) {
    if( $fh = $attachment->bodyhandle->open("w") ) {
        my $buffer;
        while( read(PIPE, $buffer, 10240) > 0 ) { ### read chunks of 10KB at a time
            $fh->print($buffer);
        }
        $fh->close;
    } else {
        warn "Error opening MIME part for writing: $!";
    }

    close PIPE;
} else {
    warn "Error opening mp3 file $tmp_file: $!";
}

$attachment->head->replace("Content-type","audio/mpeg");
$attachment->head->mime_attr("content-type.name"=>"voicemail.mp3");
$email->parts(0)->bodyhandle->as_string =~ m/From: (.*)/m;
$from = $1 || 'UNKNOWN';
$b=$email->head->replace("Subject","$from -- new voicemail");

$email->sync_headers(Length=>"COMPUTE");

$email->print;
unlink($tmp_file);

General

Comments (2)

Permalink

welcome

Welcome to the PumaCode.org Blog!

I’m Toby Johnson, a software developer in Louisville, KY, USA. I’m the webmaster of PumaCode.org, a site which hosts various open-source projects that I also maintain.

The one I spend most time on at the moment is Vss2Svn, a tool which converts version-control data from Microsoft’s Visual SourceSafe (VSS) to the popular Subversion version-control system.

I’ll use this blog to discuss various issues related to programming, open source, and other generally geeky stuff.