Skip Menu |

This queue is for tickets about the AudioFile-Info CPAN distribution.

Report information
The Basics
Id: 13960
Status: rejected
Priority: 0/
Queue: AudioFile-Info

People
Owner: DAVECROSS [...] cpan.org
Requestors: altblue [...] n0i.net
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: (no value)
Fixed in: (no value)



Subject: plugins system change
I've attached a patch against AudioFile::Info v 1.08 that offers a nicer method of adding/removing plugins, something similar to XML::SAX add/remove_parser. This way I was able to make plugins packaging a lot easier, adding postambles like: # post install AudioFile::Info->add_plugin( q[AudioFile::Info::MP3::ID3Lib], {read_mp3 => 1, write_mp3 => 1, pure_perl => 0} ); # before uninstall AudioFile::Info->remove_plugin(q[AudioFile::Info::MP3::ID3Lib]); (For conformity, the packages I mentioned are to be working on Fedora Core Linux and are currently available at: http://linux.reb00t.com/SRPMS/) best regards.
diff -urw AudioFile-Info-1.08.orig/lib/AudioFile/Info.pm AudioFile-Info-1.08/lib/AudioFile/Info.pm --- AudioFile-Info-1.08.orig/lib/AudioFile/Info.pm 2005-03-01 11:49:41.000000000 +0200 +++ AudioFile-Info-1.08/lib/AudioFile/Info.pm 2005-07-31 19:21:34.000000000 +0300 @@ -144,8 +144,9 @@ use strict; use warnings; use Carp; - -use YAML 'LoadFile'; +use YAML (); +use File::Basename (); +use File::Spec (); our $VERSION = sprintf "%d.%02d", '$Revision: 1.8 $ ' =~ /(\d+)\.(\d+)/; @@ -174,10 +175,6 @@ my $param = shift || {}; - my $path = $INC{'AudioFile/Info.pm'}; - - $path =~ s/Info.pm$/plugins.yaml/; - my ($ext) = $file =~ /\.(\w+)$/; die "Can't work out the type of the file $file\n" unless defined $ext; @@ -187,7 +184,7 @@ my $pkg = $param->{$ext}; unless (defined $pkg) { - my $config = LoadFile($path); + my $config = $class->_get_plugins; die "No default $ext file handler\n" unless exists $config->{default}{$ext}; @@ -201,11 +198,137 @@ return $pkg->new($file); } +=head2 AudioFile::Info->add_plugin(MODULE_NAME, MODULE_CONFIGURATION_HASHREF) + +This methods adds an L<AudioFile::Info> plugin. + +It takes two mandatory arguments, which are the full module name of the plugin +to be added and its configuration (provided as HashRef). + +The configuration should look something like: + + { + read_mp3 => 1, + write_mp3 => 1, + pure_perl => 1, + } + +Replace I<mp3> above with whatever audio format your plugin deals with. + +Same goes with the value of I<pure_perl>, which determines if your plugin is +written is pure perl or uses some L<XS|perlxs> code. + +=cut + +sub add_plugin { + my ($class, $pkg, $cf) = @_; + die 'Forgot to provide the configuration hashref' + unless $cf && ref $cf && ref $cf eq 'HASH'; + my $plugins = $class->_get_plugins; + if (exists $plugins->{$pkg}) { + warn "$pkg already added!\n"; + return; + } + # set default plugin if scores higher + foreach my $format ($class->_parse_plugin_config($cf)) { + if (!exists $plugins->{default}{$format} + || $cf->{"score_$format"} >= $plugins->{default}{$format}{score}) + { + $plugins->{default}{$format} = { + name => $pkg, + score => $cf->{"score_$format"} + }; + warn "$class - Default $format handler is now $pkg\n"; + } + } + $plugins->{$pkg} = $cf; + $class->_save_plugins($plugins); +} + +=head2 AudioFile::Info->remove_plugin(MODULE_NAME) + +This methods removes an L<AudioFile::Info> plugin. + +It takes one mandatory argument, which is the full module name of the plugin +to be removed. + +=cut + +sub remove_plugin { + my ($class, $pkg) = @_; + my $plugins = $class->_get_plugins; + unless (exists $plugins->{$pkg}) { + warn "$pkg was never added.\n"; + return; + } + # drop it from plugins list + delete $plugins->{$pkg}; + # drop it also from "default plugin for XXX" tree + foreach my $format (keys %{$plugins->{default}}) { + next unless $plugins->{default}{$format}{name} eq $pkg; + # take care to replace it with something else if available + my $next_plugin = ''; + my $next_plugin_score = 0; + while (my ($name, $cf) = each %$plugins) { + next if $name eq 'default'; + next unless exists $cf->{"score_$format"}; + next if $next_plugin_score >= $cf->{"score_$format"}; + $next_plugin = $name; + $next_plugin_score = $cf->{"score_$format"}; + } + if ($next_plugin_score) { + $plugins->{default}{$format} = { + name => $next_plugin, + score => $next_plugin_score, + }; + } else { + delete $plugins->{default}{$format}; + } + } + $class->_save_plugins($plugins); +} + +sub _parse_plugin_config { + my ($class, $cf) = @_; + # find out what formats this plugin supports + my %support = map { s/^(?:read|write)_//; $_ => 1} + grep { /^(?:read|write)_/ && $cf->{$_} } keys %$cf; + my @support = sort keys %support; + die 'Invalid configuration hash: Does not support anything?!' unless @support; + # compute scores if necessary + foreach my $format (@support) { + my $key = 'score_' . $format; + next if $cf->{$key}; + $cf->{$key} += 10 unless $cf->{pure_perl}; + foreach (qw[read write]) { + $cf->{$key} += 50 if $cf->{"${_}_$format"} + } + } + return wantarray ? @support : \@support; +} + +sub _get_plugins_filepath { + File::Spec->catfile( + File::Basename::dirname($INC{'AudioFile/Info.pm'}), + 'plugins.yaml' + ); +} + +sub _get_plugins { + my $plugins_file = shift->_get_plugins_filepath; + return -f $plugins_file ? YAML::LoadFile($plugins_file) : {}; +} + +sub _save_plugins { + my $plugins_file = shift->_get_plugins_filepath; + YAML::DumpFile($plugins_file, shift); +} + 1; __END__ -=head2 EXPORT +=head1 EXPORT None. Only in AudioFile-Info-1.08: Makefile.PL
If I ever get round to changing the plug-in system for AudioFile::Info, I'll probably use something like Module::Pluggable. Thanks for the suggestion tho'. Sorry I took so long to reject it :-/