| Audio-TagLib-Shell documentation | Contained in the Audio-TagLib-Shell distribution. |
Audio::TagLib::Shell - A mini shell of Audio::TagLib
$> perl -MAudio::TagLib::Shell -e shell $tag:>open <file> file openned successfully $tag:o>title <title in tag> $tag:o>artist <artist in tag> $tag:o>channels 2 $tag:o>setComment blah blah blah comment set successfully $tag:o>comment blah blah blah $tag:o>save data saved successfully $tag:>exit
A mini shell of Audio::TagLib, for viewing and editing common audio meta data on the fly.
The functionality offerred follows the abstract interface designing of Audio::TagLib, for instance, Audio::TagLib::Tag and Audio::TagLib::AudioProperties.
Simply start the shell and push <TAB>. All available commands will appear.
First of all, choose an audio file and open it. Then play your game.
Don't forget to use <TAB> ;-)
No need to escape the space in path.
Every game should have rule. Pls save or close current openned file
before openning another one. close will discard all changes you
made while save does what it should do.
hmmm.. $tag:> vs. $tag:o>
No need to use " " to comment your data. Just setComment your
comment directly. setComment will clear current comment.
shell by default.
Dongxu Ma, <dongxu.ma@gmail.com>
Copyright (C) 2005 by Dongxu Ma
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.7 or, at your option, any later version of Perl 5 you may have available.
| Audio-TagLib-Shell documentation | Contained in the Audio-TagLib-Shell distribution. |
package Audio::TagLib::Shell; use 5.008003; use strict; use warnings; use Carp q(croak); use Cwd q(chdir); require Exporter; use AutoLoader qw(AUTOLOAD); our @ISA = qw(Exporter); # Items to export into callers namespace by default. Note: do not export # names by default without a very good reason. Use EXPORT_OK instead. # Do not simply export all your public functions/methods/constants. our @EXPORT_OK = qw(shell); our @EXPORT = qw(shell); our $VERSION = '1.42'; # support encodings our @ENCODING = qw(Latin1 UTF8); # pre-declared subs my @callback = qw(open save close title artist album comment genre year track setTitle setArtist setAlbum setComment setGenre setYear setTrack length bitrate sampleRate channels cd exit pwd ls); use subs map { "_".$_ } @callback; use subs qw(shell); # global default command callback map #{ # no strict 'refs'; our %CMD = map { +"$_" => \&{"_".$_}, } @callback; #} # nice alias $CMD{quit} = $CMD{exit}; $CMD{bye} = $CMD{exit}; # private reference to current openned file # to make sure there is ONLY ONE file openned my $fileref = undef; # PS1 similar to normal shell # change to q(tag:o>) after a successful open action my $ps1 = q(tag:>); # encoding got from locale settings my $encoding = undef; # Preloaded methods go here. # main sub exported # start the shell sub shell() { # check locale first # follow the normal sequence LC_CTYPE -> LC_ALL -> LANG my $lc; if (exists $ENV{LC_CTYPE}) { $lc = $ENV{LC_CTYPE}; } elsif (exists $ENV{LC_ALL}) { $lc = $ENV{LC_ALL}; } elsif (exists $ENV{LANG}) { $lc = $ENV{LANG}; } if(defined $lc and $lc =~ m/^([a-z]{2}_[A-Z]{2}) (?:\.(?i:([a-z_\-_0-9]+)))? (?:@(?i:[a-z_0-9]+))?$/xo) { if(defined $2 and lc($2) eq 'utf8' or lc($2) eq 'utf-8') { $encoding = 1; binmode STDOUT, ":utf8"; } elsif(not defined $2 and $1 eq 'en_US') { $encoding = 0; } else { croak(sprintf("currently only support %s\n", join(" ", @ENCODING))); } } else { croak("no valid locale setting found"); } # open shell require Term::BashTab; local (*Term::BashTab::COMMAND) = \@callback; my $term = Term::BashTab->new("TagLib mini shell"); my $line; my $OUT = $term->OUT || \*STDOUT; select $OUT; $| = 1; LOOP: while (1) { $line = $term->readline($ps1); chomp $line; next LOOP unless $line; $line =~ s/\s+$//o; #print "'$line'\n"; my ($cmd, $file) = split / /, $line, 2; foreach (keys %CMD) { # exact match here if ($cmd eq $_) { no strict 'refs'; print &{$CMD{$cmd}}($file); next LOOP; } } # no match command found print "no such command!\n"; next LOOP; } } # evaluate the file permission for specific action # read or write sub __permission { my $file = $_[0]; my $perm = $_[1] ? 02 : 04; my ($mode, $uid, $gid) = (stat $file)[2, 4, 5]; if($uid == $<) { # the same user return 0 unless(($mode & 00700) >> 6 & $perm); } elsif($gid == $() { # the same group return 0 unless(($mode & 00070) >> 3 & $perm); } else { # the other return 0 unless(($mode & 00007) & $perm); } return 1; } sub _open { if (defined $fileref) { return << "EOM" ; There is file openned, close or save first. EOM } else { # check before open my $file = shift or return "no file specified\n"; return "not found\n" unless -e $file; return "no read permission\n" unless __permission($file); warn "no write permission\n" unless __permission($file, 1); # open file require Audio::TagLib::FileRef; $fileref = Audio::TagLib::FileRef->new($file); $ps1 = "tag:o>"; return "file openned successfully\n"; } } sub _save { if(defined $fileref) { if($fileref->save()) { undef $fileref; $ps1 = "tag:>"; return "file saved successfully\n"; } else { return "file could not be saved\n"; } } else { return "no file openned\n"; } } sub _close { undef $fileref if(defined $fileref); $ps1 = "tag:>"; } sub _title { if(defined $fileref) { return $fileref->tag()->title()->toCString( $ENCODING[$encoding] eq 'UTF8' ? 1 : 0). "\n"; } else { return "no file openned\n"; } } sub _artist { if(defined $fileref) { return $fileref->tag()->artist()->toCString( $ENCODING[$encoding] eq 'UTF8' ? 1 : 0). "\n"; } else { return "no file openned\n"; } } sub _album { if(defined $fileref) { return $fileref->tag()->album()->toCString( $ENCODING[$encoding] eq 'UTF8' ? 1 : 0). "\n"; } else { return "no file openned\n"; } } sub _comment { if(defined $fileref) { return $fileref->tag()->comment()->toCString( $ENCODING[$encoding] eq 'UTF8' ? 1 : 0). "\n"; } else { return "no file openned\n"; } } sub _genre { if(defined $fileref) { return $fileref->tag()->genre()->toCString( $ENCODING[$encoding] eq 'UTF8' ? 1 : 0). "\n"; } else { return "no file openned\n"; } } sub _year { if(defined $fileref) { return $fileref->tag()->year(). "\n"; } else { return "no file openned\n"; } } sub _track { if(defined $fileref) { return $fileref->tag()->track(). "\n"; } else { return "no file openned\n"; } } sub _setTitle { my $title = $_[0] ? Audio::TagLib::String->new($_[0], $ENCODING[$encoding]) : Audio::TagLib::String->null(); if(defined $fileref) { $fileref->tag()->setTitle($title); return "title set\n"; } else { return "no file openned\n"; } } sub _setArtist { my $artist = $_[0] ? Audio::TagLib::String->new($_[0], $ENCODING[$encoding]) : Audio::TagLib::String->null(); if(defined $fileref) { $fileref->tag()->setArtist($artist); return "artist set\n"; } else { return "no file openned\n"; } } sub _setAlbum { my $album = $_[0] ? Audio::TagLib::String->new($_[0], $ENCODING[$encoding]) : Audio::TagLib::String->null(); if(defined $fileref) { $fileref->tag()->setAlbum($album); return "album set\n"; } else { return "no file openned\n"; } } sub _setComment { my $comment = $_[0] ? Audio::TagLib::String->new($_[0], $ENCODING[$encoding]) : Audio::TagLib::String->null(); if(defined $fileref) { $fileref->tag()->setComment($comment); return "comment set\n"; } else { return "no file openned\n"; } } sub _setGenre { my $genre = $_[0] ? Audio::TagLib::String->new($_[0], $ENCODING[$encoding]) : Audio::TagLib::String->null(); if(defined $fileref) { $fileref->tag()->setGenre($genre); return "genre set\n"; } else { return "no file openned\n"; } } sub _setYear { my $year = shift or return "no year to set\n"; if(defined $fileref) { $fileref->tag()->setYear($year); return "year set\n"; } else { return "no file openned\n"; } } sub _setTrack { my $track = shift or return "no track to set\n"; if(defined $fileref) { $fileref->tag()->setTrack($track); return "track set\n"; } else { return "no file openned\n"; } } sub _length { if(defined $fileref) { return $fileref->audioProperties()->length(). "\n"; } else { return "no file openned\n"; } } sub _bitrate { if(defined $fileref) { return $fileref->audioProperties()->bitrate(). "\n"; } else { return "no file openned\n"; } } sub _sampleRate { if(defined $fileref) { return $fileref->audioProperties()->sampleRate(). "\n"; } else { return "no file openned\n"; } } sub _channels { if(defined $fileref) { return $fileref->audioProperties()->channels(). "\n"; } else { return "no file openned\n"; } } sub _cd { my $dir = shift || $ENV{HOME}; #print $dir. "\n"; return "not a directory\n" unless -d $dir; chdir $dir or return "cd: $!\n"; } sub _exit { if(defined $fileref) { return "there's file openned, save or close first\n"; } else { exit(0); } } sub _pwd { return $ENV{PWD}. "\n"; } # simply list all the entries in cwd sub _ls { local (*CWD); opendir CWD, "." or return "can't open cwd\n"; my @entry = sort grep { m/^[^.]/ } readdir CWD; closedir CWD or warn "closedir: $!\n"; return join("\t"x2, @entry), "\n"; } # Autoload methods go after =cut, and are processed by the autosplit program. 1; __END__ # Below is stub documentation for your module. You'd better edit it!