当前位置:早雪网网络学院编程文档Perl → perl与mp3

perl与mp3

减小字体 增大字体 作者:不详  来源:supcode.com收集整理  发布时间:2005-7-23 10:55:31

是的,所有这些代码都是初始化命令行选项的。通过使用 AppConfig,可以在整个程序中使用和修改这些选项。使用 AppConfig 还有很多好处,不过这些内容超出了本文的范围(有关 AppConfig 的更多信息,请参阅参考资料)。

另外,我还使用 %freedb_searches 散列中的条目来创建合适的配置选项,这样可以使用户和程序员更轻松一些。

在加载配置文件以后,如果用户指定了它,那么就用有意义的默认值来植入字符置换数组和不良字符数组。

最后,处理 -help 开关。注意,通过变量插入不同选项的默认值是如何在帮助文本内打印出来大的。这样就形成了可读性非常强的帮助信息。我总是在增加新的特性之后(但有时候是在之前)立即更新帮助信息。我认为,帮助文本应该和程序的功能同步,否则人们将不理解程序,也不知道帮助文本说了些什么。autotag.pl 程序特别需要更多的文档说明,POD 风格的文档应该比较合适。在您阅读本文时,这样的文档可能已经有了。POD 文档是脚本的一部分,因此下载的 autotag.pl(请参阅参考资料)将包括 POD 文档(如果我已经将它写入的话)。

与 ID3v2 标签相关的函数
get_tag() 函数是 autotag.pl 的基本函数。给出一个 MP3 文件名,它就会根据该文件构建一个散列标签。如果标签只是 ID3v1 标签, get_tag() 函数将会免费把它升级为 ID3 标签(多么好的交易!)。如果没有 ID3 标签,get_tag() 函数将创建一个。而且,get_tag() 知道分别查看 COMM 和 WXXX 元素的 Text 和 URL 子元素。

清单 5. get_tag() 函数
# {{{ get_tag: get a ID3 V2 tag, using V1 if necessary
sub get_tag
{
 my $file    = shift @_;
 my $upgrade = shift @_;
 my $mp3 = MP3::Tag->new($file);

 return undef unless defined $mp3;

 $mp3->get_tags();

 my $tag = {};

 if (exists $mp3->{ID3v2})
 {
  my $id3v2 = $mp3->{ID3v2};
  my $frames = $id3v2->supported_frames();
  while (my ($fname, $longname) = each %$frames)
  {
   # only grab the frames we know
   next unless exists $supported_frames{$fname};

   $tag->{$fname} = $id3v2->get_frame($fname);
   delete $tag->{$fname} unless defined $tag->{$fname};
   $tag->{$fname} = $tag->{$fname}->{Text} if $fname eq 'COMM';
   $tag->{$fname} = $tag->{$fname}->{URL} if $fname eq 'WXXX';
   $tag->{$fname} = '' unless defined $tag->{$fname};
  }
 }
 elsif (exists $mp3->{ID3v1})
 {
  warn "No ID3 v2 TAG info in $file, using the v1 tag";
  my $id3v1 = $mp3->{ID3v1};
  $tag->{COMM} = $id3v1->comment();
  $tag->{TIT2} = $id3v1->song();
  $tag->{TPE1} = $id3v1->artist();
  $tag->{TALB} = $id3v1->album();
  $tag->{TYER} = $id3v1->year();
  $tag->{TRCK} = $id3v1->track();
  $tag->{TIT1} = $id3v1->genre();

  if ($upgrade && read_yes_no("Upgrade ID3v1 tag to ID3v2 for $file?", 1))
  {
   set_tag($file, $tag);
  }
 }
 else
 {
  warn "No ID3 TAG info in $file, creating it";
  $tag = {
      TIT2 => '',
      TPE1 => '',
      TALB => '',
      TYER => 9999,
      COMM => '',
      };
 }
 print "Got tag ", Dumper $tag
  if $config->DEBUG();
 return $tag;
}
# }}}

set_tag() 函数是 get_tag() 函数的兄弟。它编写 ID3v2 标签,查看 COMM 和 WXXX 框架的子元素。它接受散列引用,比如 get_tag() 函数可能产生的那些散列引用。

清单 6. set_tag() 函数
# {{{ set_tag: set a ID3 V2 tag on a file
sub set_tag
{
 my $file = shift @_;
 my $tag  = shift @_;
 my $mp3 = MP3::Tag->new($file);
 print Dumper $tag;
 my $tags = $mp3->get_tags();
 my $id3v2;

 if (ref $tags eq 'HASH' && exists $tags->{ID3v2})
 {
  $id3v2 = $tags->{ID3v2};
 }
 else
 {
  $id3v2 = $mp3->new_tag("ID3v2");
 }

 my %old_frames = %{$id3v2->get_frame_ids()};

 foreach my $fname (keys %$tag)
 {
  $id3v2->remove_frame($fname)
   if exists $old_frames{$fname};

  if ($fname eq 'WXXX')
  {
   $id3v2->add_frame('WXXX', 'ENG', 'FreeDB URL', $tag->{WXXX}) ;
  }
  elsif ($fname eq 'COMM')
  {
   $id3v2->add_frame('COMM', 'ENG', 'Comment', $tag->{COMM}) ;
  }
  else
  {
   $id3v2->add_frame($fname, $tag->{$fname});
  }
 }

 $id3v2->write_tag();
 return 0;
}
# }}}

print_tag_info() 函数简单地打印输出标签的摘要。不像我在 autotag.pl 程序中的其他地方使用的 Data::Dumper 函数(必须指出,有时没有必要使用),print_tag_info() 函数可以提供漂亮的、面向用户的散列标签元素的打印输出。注意,该函数接受散列引用,而不是实际的文件名。

给出文件名和某些可能的 ID3 标签信息,guess_track_number() 函数和guess_artist_and_track() 函数会尽力工作。注意,guess_track_number() 函数知道曲目的数量很少大于 30。

清单 7. print_tag_info()、 guess_track_number()、和 guess_artist_and_track() 函数
# {{{ print_tag_info: print the tag info

sub print_tag_info
{
 my $filename = shift @_;
 my $tag      = shift @_;
 my $extra    = shift @_ || 'Track info';

 # argument checking
 return unless ref $tag eq 'HASH';

 print "$extra for '$filename':\n";

 foreach (keys %$tag)
 {
  printf "%10s : %s\n", $_, $tag->{$_};
 }
}

# }}}

# {{{ guess_track_number: guess track number from ID3 tag and file name
sub guess_track_number
{
 my $filename = shift @_;
 my $tag      = shift @_ || return undef;

 $filename = basename($filename);   # directories can contain confusing data

 # first try to guess the track number from the old tag
 if (exists $tag->{TRCK} && contains_word_char($tag->{TRCK}))
 {
  my $n = $tag->{TRCK} + 0;    # fix tracks like 1/10
  return $n;
 }
 elsif ($filename =~ m/([012]?\d).*\.[^.]+$/)
                     # now look for numbers in the filename (0 through 29)
 {
  print "Guessed track number $1 from filename '$filename'\n"
   if $config->DEBUG();
  return $1;
 }

 return undef; # if all else fails, return undef
}
# }}}

# {{{ guess_artist_and_track: guess artist and track from file name
sub guess_artist_and_track
{
 my $filename = shift @_;
 my $artist;
 my $track;

 $filename = basename($filename);   # directories can contain confusing data

 if ($filename =~ m/([^-_]{3,})\s*-\s*(.{3,})\s*\.[^.]+$/)
 {
  print "Guessed artist $1 from filename '$filename'\n"
   if $config->DEBUG();
  $artist = $1;
  $track = $2;
 }

 return ($artist, $track);
}
# }}}

上一页  [1] [2] [3] [4] [5]  下一页


Tags:perl,mp
[数据载入中...] [返回上一页] [打 印]