partially implement tagvals
[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             my $tag=$self->{elements}->[$#{$self->{elements}}];
75             if(defined($tag) && (ref($tag) eq "ID3FS::PathElement::Tag") &&
76                $self->{db}->tag_has_values($tag->{id}))
77             {
78                 print "DIRENTS: TAG: TAGVALUES\n";
79                 @dents=$self->{db}->tag_values($tag->{id});
80             }
81             else
82             {
83                 print "DIRENTS: TAG: ARTISTS\n";
84                 @dents=(qw(AND ALLTRACKS), # FIXME: NOT and OR
85                         $self->{db}->artists(@{$self->{elements}}));
86             }
87         }
88         when($STATE_BOOLEAN)
89         {
90             @dents=$self->{db}->tags(@{$self->{elements}});
91         }
92         when($STATE_ROOT)
93         {
94             @dents=("ALL", $self->{db}->tags(@{$self->{elements}}));
95         }
96         when($STATE_ALBUMS)
97         {
98             @dents=("TRACKS", $self->{db}->albums(@{$self->{elements}}));
99         }
100         when($STATE_TRACKLIST)
101         {
102             @dents=$self->{db}->tracks(@{$self->{elements}});
103         }
104         default
105         {
106             print "DIRENTS: UNHANDLED STATE: $_\n";
107         }
108     }
109     return(@dents);
110 }
111
112 sub parse
113 {
114     my($self)=@_;
115     @{$self->{components}}=split(/\//, $self->{path});
116     shift @{$self->{components}}; # drop empty field before leading /
117     print "PATH: $self->{path}\n";
118 #    print "COMPONENTS: ", join(' | ', @{$self->{components}}), "\n";
119     $self->state($STATE_ROOT);
120     return if($self->{path} eq "/");
121     my @parts=@{$self->{components}};
122     my($tag, $tagval);
123     $self->{elements}=[];
124     while(my $name=shift @parts)
125     {
126         print "NAME: $name\n";
127         given($self->state())
128         {
129             when($STATE_INVALID)
130             {
131                 print "SM: INVALID: $name\n";
132                 return;
133             }
134             when($STATE_ROOT)
135             {
136                 print "SM: ROOT: $name\n";
137                 if($name eq "ALL")
138                 {
139                     $self->state($STATE_TAG);
140                 }
141                 else
142                 {
143                     $tag=ID3FS::PathElement::Tag->new($self->{db}, $name);
144                     if($tag)
145                     {
146                         push(@{$self->{elements}}, $tag);
147                         $self->state($STATE_TAG);
148                     }
149                     else
150                     {
151                         $self->state($STATE_INVALID);
152                     }
153                 }
154             }
155             when($STATE_TAG)
156             {
157                 print "SM: TAG: $name\n";
158                 my $tag=$self->{elements}->[$#{$self->{elements}}];
159                 if(defined($tag) &&
160                    ref($tag) eq "ID3FS::PathElement::Tag" &&
161                    $self->{db}->tag_has_values($tag->{id}))
162                 {
163                     my $tagval=ID3FS::PathElement::Tagval->new($name);
164                     if(defined($tagval))
165                     {
166                         $self->state($STATE_BOOLEAN);
167                         push(@{$self->{elements}}, $tagval);
168                     }
169                     else
170                     {
171                         $self->state($STATE_INVALID);
172                     }
173                 }
174                 else
175                 {
176                     given($name)
177                     {
178                         when("AND")
179                         {
180                             $self->state($STATE_BOOLEAN);
181 #                           push(@{$self->{elements}}, ID3FS::PathElement::Boolean->new($name));
182                         }
183                         when("ALLTRACKS")
184                         {
185                             $self->state($STATE_TRACKLIST);
186                         }
187                         when("OR")
188                         {
189                             $self->state($STATE_BOOLEAN);
190 #                           push(@{$self->{elements}}, ID3FS::PathElement::Boolean->new($name));
191                         }
192                         when("NOT")
193                         {
194                             $self->state($STATE_TAG);
195 #                       push(@{$self->{elements}}, ID3FS::PathElement::Boolean->new($name));
196                         }
197                         my $artist=ID3FS::PathElement::Artist->new($self->{db}, $name);
198                         if($artist)
199                         {
200                             push(@{$self->{elements}}, $artist);
201                             $self->state($STATE_ALBUMS);
202                         }
203                         else
204                         {
205                             $self->state($STATE_INVALID);
206                         }
207                     }
208                 }
209             }
210
211 #           when(255) #FIXME - dead code
212 #           {
213 #               my @valid_tagvals=$self->{db}->tag_values($tag);
214 #               print "TAGVALUES: $name: ", join(', ', @valid_tagvals), "\n";
215 #               if(@valid_tagvals)
216 #               {
217 #                   if(grep { $name eq $_; } @valid_tagvals)
218 #                   {
219 #                       print "TAGVAL VALID\n";
220 #                       $self->state($STATE_TAGVAL);
221 #                       push(@{$self->{elements}}, ID3FS::PathElement::Tagval($name));
222 #                   }
223 #                   else
224 #                   {
225 #                       print "ERROR: unknown tagval: $tagval\n";
226 #                       $self->state($STATE_INVALID);
227 #                   }
228 #           }
229             when($STATE_TAGVAL)
230             {
231                 print "SM: TAGVAL: $name\n";
232             }
233             when($STATE_BOOLEAN)
234             {
235                 print "SM: BOOLEAN: $name\n";
236                 my $tag=ID3FS::PathElement::Tag->new($self->{db}, $name);
237                 if($tag)
238                 {
239                     push(@{$self->{elements}}, $tag);
240                     $self->state($STATE_TAG);
241                 }
242                 else
243                 {
244                     $self->state($STATE_INVALID);
245                 }
246             }
247             when($STATE_ALBUMS)
248             {
249                 print "SM: ALBUM: $name\n";
250                 if($name eq "TRACKS")
251                 {
252                     $self->state($STATE_TRACKLIST);
253                 }
254                 else
255                 {
256                     my $album=ID3FS::PathElement::Album->new($self->{db}, $name);
257                     if($album)
258                     {
259                         push(@{$self->{elements}}, $album);
260                         $self->state($STATE_TRACKLIST);
261                     }
262                     else
263                     {
264                         $self->state($STATE_INVALID);
265                     }
266                 }
267             }
268             when($STATE_TRACKLIST)
269             {
270                 print "SM: TRACKLIST: $name\n";
271                 my $track=ID3FS::PathElement::File->new($self->{db}, $name);
272                 push(@{$self->{elements}}, $track);
273                 if($track)
274                 {
275                     push(@{$self->{elements}}, $track);
276                     $self->state($STATE_FILE);
277                 }
278                 else
279                 {
280                     $self->state($STATE_INVALID);
281                 }
282             }
283             when($STATE_FILE)
284             {
285                 print "SM: FILE: $name\n";
286                 # Can't have anything after a filename
287                 $self->state($STATE_INVALID);
288             }
289             default
290             {
291                 print "SM: ERROR: UNKNOWN STATE: $self->{state}\n";
292                 $self->state($STATE_INVALID);
293             }
294         }
295     }
296 }
297
298 sub state
299 {
300     my($self, $newstate)=@_;
301     $self->{state}=$newstate if(defined($newstate));
302     return $self->{state};
303 }
304
305 1;