start implementing albums
[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_ARTISTS, $STATE_ALBUMS, $STATE_TRACKLIST,
15      $STATE_FILE)=(0..9);
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() eq $STATE_FILE) ||
35        ($self->state() eq $STATE_INVALID))
36     {
37         return 0;
38     }
39     return 1;
40 }
41
42 sub isvalid
43 {
44     my($self)=@_;
45     return($self->state() != $STATE_INVALID);
46 }
47
48 sub dest
49 {
50     my($self)=@_;
51     if($self->state() == $STATE_FILE)
52     {
53         return $self->{db}->filename(@{$self->{elements}});
54     }
55     return "ERROR"; #should never happen?
56 }
57
58 sub dirents
59 {
60     my($self)=@_;
61     my @dents=();
62     given($self->state())
63     {
64         when($STATE_TAG)
65         {
66             @dents=qw(AND ARTISTS ALBUMS TRACKS);
67         }
68         when($STATE_BOOLEAN)
69         {
70             @dents=$self->{db}->tags(@{$self->{elements}});
71         }
72         when($STATE_ROOT)
73         {
74             @dents=("ALL", $self->{db}->tags(@{$self->{elements}}));
75         }
76         when($STATE_ARTISTS)
77         {
78             @dents=$self->{db}->artists(@{$self->{elements}});
79         }
80         when($STATE_ALBUMS)
81         {
82             @dents=$self->{db}->albums(@{$self->{elements}});
83         }
84         when($STATE_TRACKLIST)
85         {
86             @dents=$self->{db}->tracks(@{$self->{elements}});
87         }
88         default
89         {
90             print "DIRENTS: UNHANDLED STATE: $_\n";
91         }
92     }
93     return(@dents);
94 }
95
96 sub parse
97 {
98     my($self)=@_;
99     @{$self->{components}}=split(/\//, $self->{path});
100     shift @{$self->{components}}; # drop empty field before leading /
101     print "PATH: $self->{path}\n";
102 #    print "COMPONENTS: ", join(' | ', @{$self->{components}}), "\n";
103     $self->state($STATE_ROOT);
104     return if($self->{path} eq "/");
105     my @parts=@{$self->{components}};
106     my($tag, $tagval);
107     $self->{elements}=[];
108     while(my $name=shift @parts)
109     {
110         print "NAME: $name\n";
111         given($self->state())
112         {
113             when($STATE_INVALID)
114             {
115                 print "SM: INVALID: $name\n";
116                 return;
117             }
118             when($STATE_ROOT)
119             {
120                 print "SM: ROOT: $name\n";
121                 if($name eq "ALL")
122                 {
123                     $self->state($STATE_ARTISTS);
124                 }
125                 else
126                 {
127                     $tag=ID3FS::PathElement::Tag->new($self->{db}, $name);
128                     if($tag)
129                     {
130                         push(@{$self->{elements}}, $tag);
131                         $self->state($STATE_TAG);
132                     }
133                     else
134                     {
135                         $self->state($STATE_INVALID);
136                     }
137                 }
138             }
139             when($STATE_TAG)
140             {
141                 print "SM: TAG: $name\n";
142                 given($name)
143                 {
144                     when("AND")
145                     {
146                         $self->state($STATE_BOOLEAN);
147 #                       push(@{$self->{elements}}, ID3FS::PathElement::Boolean->new($name));
148                     }
149                     when("ARTISTS")
150                     {
151                         $self->state($STATE_ARTISTS);
152                     }
153                     when("ALBUMS")
154                     {
155                         $self->state($STATE_ALBUMS);
156                     }
157                     when("TRACKS")
158                     {
159                         $self->state($STATE_TRACKLIST);
160                     }
161
162 #                   when("OR")  { ; }
163 #                   when("NOT") { ; }
164                     default
165                     {
166                         $self->state($STATE_INVALID);
167                     }
168                 }
169             }
170
171             when(255) #FIXME - dead code
172             {
173                 print "SM: WANTMORE: $name\n";
174                 $tag=ID3FS::PathElement::Tag->new($self->{db}, $name);
175                 if($tag)
176                 {
177                     push(@{$self->{elements}}, $tag);
178 #                   $self->state($STATE_TAG);
179                 }
180                 else
181                 {
182                     $self->state($STATE_INVALID);
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                 else
201                 {
202                     $self->state($STATE_INVALID);
203                 }
204             }
205             when($STATE_TAGVAL)
206             {
207                 print "SM: TAGVAL: $name\n";
208             }
209             when($STATE_BOOLEAN)
210             {
211                 print "SM: BOOLEAN: $name\n";
212                 my $tag=ID3FS::PathElement::Tag->new($self->{db}, $name);
213                 if($tag)
214                 {
215                     push(@{$self->{elements}}, $tag);
216                     $self->state($STATE_TAG);
217                 }
218                 else
219                 {
220                     $self->state($STATE_INVALID);
221                 }
222             }
223             when($STATE_ARTISTS)
224             {
225                 print "SM: ARTIST: $name\n";
226                 my $artist=ID3FS::PathElement::Artist->new($self->{db}, $name);
227                 push(@{$self->{elements}}, $tag);
228                 if($artist)
229                 {
230                     push(@{$self->{elements}}, $artist);
231                     $self->state($STATE_ALBUMS);
232                 }
233                 else
234                 {
235                     $self->state($STATE_INVALID);
236                 }
237             }
238             when($STATE_ALBUMS)
239             {
240                 print "SM: ALBUM: $name\n";
241                 my $album=ID3FS::PathElement::Album->new($self->{db}, $name);
242                 push(@{$self->{elements}}, $album);
243                 if($album)
244                 {
245                     push(@{$self->{elements}}, $album);
246                     $self->state($STATE_TRACKLIST);
247                 }
248                 else
249                 {
250                     $self->state($STATE_INVALID);
251                 }
252             }
253             when($STATE_TRACKLIST)
254             {
255                 print "SM: TRACKS: $name\n";
256                 my $track=ID3FS::PathElement::File->new($self->{db}, $name);
257                 push(@{$self->{elements}}, $track);
258                 if($track)
259                 {
260                     push(@{$self->{elements}}, $track);
261                     $self->state($STATE_FILE);
262                 }
263                 else
264                 {
265                     $self->state($STATE_INVALID);
266                 }
267             }
268             when($STATE_FILE)
269             {
270                 print "SM: FILE: $name\n";
271                 # Can't have anything after a filename
272                 $self->state($STATE_INVALID);
273             }
274             default
275             {
276                 print "SM: ERROR: UNKNOWN STATE: $self->{state}\n";
277                 $self->state($STATE_INVALID);
278             }
279         }
280     }
281 }
282
283 sub state
284 {
285     my($self, $newstate)=@_;
286     $self->{state}=$newstate if(defined($newstate));
287     return $self->{state};
288 }
289
290 1;