I wrote this script so I could tell my Mac to "play Stevie Wonder" and it would.  
"quit" stops the script.

Just give it the path to a directory that contains directories.  Each directory 
will contain MP3s (doesn't matter how many levels deep, we are using File::Find 
to get every file /\.mp3$/) and will have the name you want to use to invoke it.

Uses Mac::Glue to control SoundJam.  It keeps reusing a single playlist window 
each time you tell it to play $foo.

-- Chris

#!perl -w
# speak soundjam.plx
# [EMAIL PROTECTED], 2001.06.18
use strict;
use File::Find;
use File::Spec::Functions;
use Mac::Glue ':all';
use Mac::Events;
use Mac::SpeechRecognition;

my $sj = new Mac::Glue 'SoundJam';
my $dir = "Bird:mp3:stuff";

my $artists = getArtists();
createSpeechModel($artists);
my $win = $sj->make(new => 'playlist window');
while (1) {
        WaitNextEvent();
}
exit;


# just load in directory names inside $dir
sub getArtists {
        opendir(D, $dir) or die $!;
        my %artists = map { ($_ => 1) } grep { -d catdir($dir, $_) } readdir D;
        closedir D;
        return \%artists;
}

# load in all .mp3 files under $dir:$artist
sub getArtistFiles {
        my($artist) = @_;
        my($newdir, @files);
        $newdir = catdir($dir, $artist);
        return unless -d $newdir;
        find(sub { push @files, $File::Find::name if /\.mp3$/ }, $newdir);
        return @files;
}

# phun phun phun
sub createSpeechModel {
        my($artists) = @_;
        # Initialize Recognition System
        my $system = SROpenRecognitionSystem() or die $^E;
        SRSetProperty($system, kSRFeedbackAndListeningModes,
                kSRHasFeedbackHasListenModes) or die $^E;

        # Create Recognizer
        my $recognizer = SRNewRecognizer($system);

        # Build Language Model
        my $topModel = SRNewLanguageModel($system, "<TopLM>") or die $^E;

        my %models;

        for my $key (qw(quit play artist)) {
                $models{$key} = SRNewLanguageModel($system, "<$key>") or die $^E;
                for ($key eq 'artist' ? keys %$artists : $key) {
                        my $phrase = SRNewPhrase($system, $_) or die $^E;
                        SRAddLanguageObject($models{$key}, $phrase) or die $^E;
                        SRReleaseObject($phrase) or die $^E;
                }
        }

        for my $key (qw(quit play)) {
                my $path = SRNewPath($system) or die $^E;
                SRAddLanguageObject($path, $models{$key}) or die $^E;
                if ($key eq 'play') {
                        SRAddLanguageObject($path, $models{artist}) or die $^E;
                }
                SRAddLanguageObject($topModel, $path) or die $^E;
                SRReleaseObject($path);
                SRReleaseObject($models{$key});
                if ($key eq 'play') {
                        SRReleaseObject($models{artist});
                }
        }

        SRSetLanguageModel($recognizer, $topModel) or die $^E;

        # Set up AppleEvent handler and start listening
        $AppleEvent{kAESpeechSuite, kAESpeechDone} = \&Listen;
        SRStartListening($recognizer);
        SRSetProperty($recognizer, kSRNotificationParam,
                kSRNotifyRecognitionDone) or die $^E;

        END {
                SRStopListening($recognizer);
                SRReleaseObject($topModel);
                SRReleaseObject($recognizer);
                SRCloseRecognitionSystem($system);
        }
}

sub AEGetSpeechObject {
        my($event, $key, $type) = @_;
        my $desc = AEGetParamDesc($event, $key, $type);
        my $obj  = SRMakeSpeechObject($desc->data->get);
        AEDisposeDesc($desc);
        return $obj;
}

sub Listen {
        my($event, $reply) = @_;
        
        my $rec = AEGetSpeechObject($event, keySRRecognizer, typeSRRecognizer);
        my $res = AEGetSpeechObject($event, keySRSpeechResult, typeSRSpeechResult);

        my $text = SRGetProperty($res, kSRTEXTFormat);

        SRReleaseObject($res);

        if (!$text || $text =~ /\Q???/) {
                print "I don't know what you said.\n";
                return 0;
        } elsif ($text =~ /^quit/i) {
                print "Good-bye.\n";
                exit;
        } else {
                print "I think you said: '$text'.\n";
                $text =~ s/^play\s+//i;
        }

        my @files = getArtistFiles($text) or return;
        $sj->delete( $sj->obj(file_tracks => $win) );
        $sj->add(\@files, to => $win);
        $sj->play($sj->obj(file_track => 1, $win));
        return 1;
}

__END__


-- 
Chris Nandor                      [EMAIL PROTECTED]    http://pudge.net/
Open Source Development Network    [EMAIL PROTECTED]     http://osdn.com/

Reply via email to