1 # id3fs - a FUSE-based filesystem for browsing audio metadata
2 # Copyright (C) 2010 Ian Beckwith <ianb@erislabs.net>
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
17 package ID3FS::AudioFile::Mp3;
26 my $class=ref($proto) || $proto;
31 $self->{mp3}=MP3::Tag->new($self->{path});
40 my ($self, $func, $value)=@_;
41 return $self->choose($func) unless($value);
42 unless(exists($self->{mp3}->{ID3v1}))
44 $self->{mp3}->new_tag("ID3v1");
46 unless(exists($self->{mp3}->{ID3v2}))
48 $self->{mp3}->new_tag("ID3v2");
50 my $method=$func . "_set";
51 $self->{mp3}->$method($value, 1);
59 if(exists($self->{mp3}->{ID3v2}))
61 $thing=$self->{mp3}->{ID3v2}->$func();
63 if(exists($self->{mp3}->{ID3v1}) && (!defined($thing) || !length($thing)))
65 $thing=$self->{mp3}->{ID3v1}->$func();
70 sub year { return(shift->set("year", @_)); }
71 sub artist { return(shift->set("artist", @_)); }
72 sub album { return(shift->set("album", @_)); }
73 sub track { return(shift->set("title", @_)); }
74 sub tracknum { return(shift->set("track", @_)); }
75 sub comment { return(shift->set("comment", @_)); }
77 sub audiotype { return "mp3"; }
78 sub haspic { return undef; } # NEXTVERSION
85 $self->{mp3}->new_tag("ID3v1") unless(defined($self->{mp3}->{ID3v1}));
86 $self->{mp3}->{ID3v1}->genre($val);
90 $genre=$self->{ID3v1}->genre() if(defined($self->{ID3v1}));
97 return() unless(exists($self->{mp3}->{ID3v2}) && defined($self->{mp3}->{ID3v2}));
98 return($self->{mp3}->{ID3v2}->genre());
104 # MP3::Tag->get_tags shows cryptic debug info via print when it finds
105 # an unhandled id3v2 version, in addition to the warning, so use
106 # select to send prints to /dev/null
108 if(open(NULL,">/dev/null"))
110 $oldout=select(NULL);
112 eval { $self->{mp3}->get_tags; };
113 warn("$self->{path}: $@\n") if($@);
124 my $existing=$self->tags();
125 my @existing=split(/\s*,\s*/, $existing) if($existing);
126 my @merged=$self->uniq(@tags, @existing);
127 my $genre=join(', ', @merged);
128 return($self->set("genre", $genre));
135 $self->{mp3}->update_tags();
138 sub delete_artist { shift->delete("artist"); }
139 sub delete_album { shift->delete("album"); }
140 sub delete_track { shift->delete("song"); }
141 sub delete_tracknum { shift->delete("track"); }
142 sub delete_year { shift->delete("year"); }
143 sub delete_v1genre { shift->delete("v1genre"); }
144 sub delete_comment { shift->delete("comment"); }
145 sub delete_genre { shift->delete("genre"); }
150 my $current=$self->tags();
151 my @current=split(/\s*,\s*/, $current);
156 delete($hash{$tag}) if(exists($hash{$tag}));
158 my @tagsout=sort keys(%hash);
159 my $genre=join(', ', @tagsout);
162 return($self->set("genre", $genre));
166 return($self->delete_genre());
173 if(exists($self->{mp3}->{ID3v1}))
175 $self->{mp3}->{ID3v1}->remove_tag;
177 if(exists($self->{mp3}->{ID3v2}))
179 $self->{mp3}->{ID3v2}->remove_tag;
185 my($self, $thing)=@_;
187 if(exists($self->{mp3}->{ID3v1}))
190 $action="genre" if($action eq "v1genre");
191 if($action eq "track")
193 $self->{mp3}->{ID3v1}->track("00");
197 $self->{mp3}->{ID3v1}->$action(" ");
201 if(exists($self->{mp3}->{ID3v2}))
203 if($thing eq "artist")
205 $self->{mp3}->{ID3v2}->remove_frame("TPE1");
206 $self->{mp3}->{ID3v2}->remove_frame("TPE2");
208 elsif($thing eq "album")
210 $self->{mp3}->{ID3v2}->remove_frame("TALB");
212 elsif($thing eq "song")
214 $self->{mp3}->{ID3v2}->remove_frame("TIT2");
216 elsif($thing eq "track")
218 $self->{mp3}->{ID3v2}->remove_frame("TRCK");
220 elsif($thing eq "year")
222 $self->{mp3}->{ID3v2}->remove_frame("TYER");
223 $self->{mp3}->{ID3v2}->remove_frame("TDRC");
225 elsif($thing eq "comment")
227 $self->{mp3}->{ID3v2}->remove_frame("COMM");
229 elsif($thing eq "genre")
231 $self->{mp3}->{ID3v2}->remove_frame("TCON");
238 my ($self, @things)=@_;
241 return(sort keys(%hash));