key albums off artists too (otherwise we get dylan's unplugged in radiohead's unplugg...
[id3fs.git] / lib / ID3FS / Path.pm
1 package ID3FS::Path;
2
3 use strict;
4 use warnings;
5 use feature 'switch';
6 use ID3FS::PathElement::Artist;
7 use ID3FS::PathElement::Album;
8 use ID3FS::PathElement::Boolean;
9 use ID3FS::PathElement::File;
10 use ID3FS::PathElement::Tag;
11 use ID3FS::PathElement::Tagval;
12
13 our ($STATE_INVALID, $STATE_ROOT, $STATE_TAG, $STATE_TAGVAL,
14      $STATE_BOOLEAN, $STATE_ALBUMS, $STATE_TRACKLIST,
15      $STATE_FILE)=(0..7);
16
17 sub new
18 {
19     my $proto=shift;
20     my $class=ref($proto) || $proto;
21     my $self={};
22     bless($self,$class);
23
24     $self->{db}=shift;
25     $self->{path}=shift;
26     $self->parse();
27     print "STATE: ", $self->state(), "\n";
28     return $self;
29 }
30
31 sub isdir
32 {
33     my($self)=@_;
34     if(($self->state() == $STATE_FILE) ||
35        ($self->state() == $STATE_INVALID))
36     {
37         return 0;
38     }
39     return 1;
40 }
41
42 sub isfile
43 {
44     my($self)=@_;
45     return 1 if($self->state() == $STATE_FILE);
46     return 0;
47 }
48
49 sub isvalid
50 {
51     my($self)=@_;
52     return($self->state() != $STATE_INVALID);
53 }
54
55 sub dest
56 {
57     my($self)=@_;
58     if($self->state() == $STATE_FILE)
59     {
60         return $self->{db}->filename(@{$self->{elements}});
61     }
62     return "ERROR"; #should never happen?
63 }
64
65 sub dirents
66 {
67     my($self)=@_;
68     my @dents=();
69     print "DIRENTS: STATE: ",  $self->state(), "\n";
70     given($self->state())
71     {
72         when($STATE_TAG)
73         {
74             @dents=(qw(AND ALLTRACKS), # FIXME: NOT and OR
75                     $self->{db}->artists(@{$self->{elements}}));
76         }
77         when($STATE_BOOLEAN)
78         {
79             @dents=$self->{db}->tags(@{$self->{elements}});
80         }
81         when($STATE_ROOT)
82         {
83             @dents=("ALL", $self->{db}->tags(@{$self->{elements}}));
84             print "\nDIRENTS: DENTS: ", join(", ", @dents),"\n\n";
85         }
86         when($STATE_ALBUMS)
87         {
88             @dents=("TRACKS", $self->{db}->albums(@{$self->{elements}}));
89         }
90         when($STATE_TRACKLIST)
91         {
92             @dents=$self->{db}->tracks(@{$self->{elements}});
93         }
94         default
95         {
96             print "DIRENTS: UNHANDLED STATE: $_\n";
97         }
98     }
99     return(@dents);
100 }
101
102 sub parse
103 {
104     my($self)=@_;
105     @{$self->{components}}=split(/\//, $self->{path});
106     shift @{$self->{components}}; # drop empty field before leading /
107     print "PATH: $self->{path}\n";
108 #    print "COMPONENTS: ", join(' | ', @{$self->{components}}), "\n";
109     $self->state($STATE_ROOT);
110     return if($self->{path} eq "/");
111     my @parts=@{$self->{components}};
112     my($tag, $tagval);
113     $self->{elements}=[];
114     while(my $name=shift @parts)
115     {
116         print "NAME: $name\n";
117         given($self->state())
118         {
119             when($STATE_INVALID)
120             {
121                 print "SM: INVALID: $name\n";
122                 return;
123             }
124             when($STATE_ROOT)
125             {
126                 print "SM: ROOT: $name\n";
127                 if($name eq "ALL")
128                 {
129                     $self->state($STATE_TAG);
130                 }
131                 else
132                 {
133                     $tag=ID3FS::PathElement::Tag->new($self->{db}, $name);
134                     if($tag)
135                     {
136                         push(@{$self->{elements}}, $tag);
137                         $self->state($STATE_TAG);
138                     }
139                     else
140                     {
141                         $self->state($STATE_INVALID);
142                     }
143                 }
144             }
145             when($STATE_TAG)
146             {
147                 print "SM: TAG: $name\n";
148                 given($name)
149                 {
150                     when("AND")
151                     {
152                         $self->state($STATE_BOOLEAN);
153 #                       push(@{$self->{elements}}, ID3FS::PathElement::Boolean->new($name));
154                     }
155                     when("ALLTRACKS")
156                     {
157                         $self->state($STATE_TRACKLIST);
158                     }
159                     when("OR")
160                     {
161                         $self->state($STATE_BOOLEAN);
162 #                       push(@{$self->{elements}}, ID3FS::PathElement::Boolean->new($name));
163                     }
164                     when("NOT")
165                     {
166                         $self->state($STATE_TAG);
167 #                       push(@{$self->{elements}}, ID3FS::PathElement::Boolean->new($name));
168                     }
169                     my $artist=ID3FS::PathElement::Artist->new($self->{db}, $name);
170                     if($artist)
171                     {
172                         push(@{$self->{elements}}, $artist);
173                         $self->state($STATE_ALBUMS);
174                     }
175                     else
176                     {
177                         $self->state($STATE_INVALID);
178                     }
179                 }
180             }
181
182 #           when(255) #FIXME - dead code
183 #           {
184 #               my @valid_tagvals=$self->{db}->tag_values($tag);
185 #               print "TAGVALUES: $name: ", join(', ', @valid_tagvals), "\n";
186 #               if(@valid_tagvals)
187 #               {
188 #                   if(grep { $name eq $_; } @valid_tagvals)
189 #                   {
190 #                       print "TAGVAL VALID\n";
191 #                       $self->state($STATE_TAGVAL);
192 #                       push(@{$self->{elements}}, ID3FS::PathElement::Tagval($name));
193 #                   }
194 #                   else
195 #                   {
196 #                       print "ERROR: unknown tagval: $tagval\n";
197 #                       $self->state($STATE_INVALID);
198 #                   }
199 #           }
200             when($STATE_TAGVAL)
201             {
202                 print "SM: TAGVAL: $name\n";
203             }
204             when($STATE_BOOLEAN)
205             {
206                 print "SM: BOOLEAN: $name\n";
207                 my $tag=ID3FS::PathElement::Tag->new($self->{db}, $name);
208                 if($tag)
209                 {
210                     push(@{$self->{elements}}, $tag);
211                     $self->state($STATE_TAG);
212                 }
213                 else
214                 {
215                     $self->state($STATE_INVALID);
216                 }
217             }
218             when($STATE_ALBUMS)
219             {
220                 print "SM: ALBUM: $name\n";
221                 if($name eq "TRACKS")
222                 {
223                     $self->state($STATE_TRACKLIST);
224                 }
225                 else
226                 {
227                     my $album=ID3FS::PathElement::Album->new($self->{db}, $name);
228                     if($album)
229                     {
230                         push(@{$self->{elements}}, $album);
231                         $self->state($STATE_TRACKLIST);
232                     }
233                     else
234                     {
235                         $self->state($STATE_INVALID);
236                     }
237                 }
238             }
239             when($STATE_TRACKLIST)
240             {
241                 print "SM: TRACKLIST: $name\n";
242                 my $track=ID3FS::PathElement::File->new($self->{db}, $name);
243                 push(@{$self->{elements}}, $track);
244                 if($track)
245                 {
246                     push(@{$self->{elements}}, $track);
247                     $self->state($STATE_FILE);
248                 }
249                 else
250                 {
251                     $self->state($STATE_INVALID);
252                 }
253             }
254             when($STATE_FILE)
255             {
256                 print "SM: FILE: $name\n";
257                 # Can't have anything after a filename
258                 $self->state($STATE_INVALID);
259             }
260             default
261             {
262                 print "SM: ERROR: UNKNOWN STATE: $self->{state}\n";
263                 $self->state($STATE_INVALID);
264             }
265         }
266     }
267 }
268
269 sub state
270 {
271     my($self, $newstate)=@_;
272     $self->{state}=$newstate if(defined($newstate));
273     return $self->{state};
274 }
275
276 1;