File Coverage

lib/Mac/iTunes/Library.pm
Criterion Covered Total %
statement 16 164 9.7
branch 0 66 0.0
condition n/a
subroutine 5 39 12.8
pod 21 23 91.3
total 42 292 14.3


line stmt bran cond sub pod time code
1             package Mac::iTunes::Library;
2              
3 2     2   24936 use 5.006;
  2         6  
  2         70  
4 2     2   10 use warnings;
  2         4  
  2         46  
5 2     2   11 use strict;
  2         3  
  2         62  
6 2     2   8 use Carp;
  2         10  
  2         3892  
7              
8             require Exporter;
9             our @ISA = qw(Exporter);
10             our %EXPORT_TAGS = ( 'all' => [ qw() ] );
11             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
12             our @EXPORT = qw( );
13              
14             our $VERSION = '1.0';
15              
16             =head1 NAME
17              
18             Mac::iTunes::Library - Perl extension for representing an iTunes library
19              
20             =head1 SYNOPSIS
21              
22             use Mac::iTunes::Library;
23              
24             my $library = Mac::iTunes::Library->new();
25             my $item = Mac::iTunes::Library::Item->new(
26             'Track ID' => 1,
27             'Name' => 'The Fooiest Song',
28             'Artist' => 'The Bar Band',
29             );
30             $library->add($item);
31             print "This library has only " . $library->num() . "item.\n";
32              
33             =head1 DESCRIPTION
34              
35             A data structure for representing an iTunes library.
36              
37             The library keeps track of the number of tracks by each artist
38             (a hash of Artist => num_tracks) and the number of songs in each genre
39             (Genre => num_tracks). Additionally, the total playcounts for each artist
40             (Artist => playcount_of_all_songs) and genre (Genre => playcount_of_all_songs)
41             are tallied. Finally, all of the items in the library are available, sorted
42             by artist.
43              
44             =head1 EXPORT
45              
46             None by default.
47              
48             =head1 METHODS
49              
50             =head2 new()
51              
52             Creates a new Mac::iTunes::Library object that can store
53             Mac::iTunes::Library::Item objects.
54              
55             =cut
56              
57             sub new {
58 1     1 1 10 my $class = shift;
59 1         13 my $self = {
60             Num => 0, # Number of tracks in this library
61             Size => 0, # Size of all tracks
62             Time => 0, # Length of all tracks in milliseconds
63             Artist => {}, # Artist counts in tracks
64             PArtists => {}, # Artists counts by playcount
65             AlbumArtist => {}, # Album Artist counts in tracks
66             PAlbumArtists => {},# Album Artists counts by playcount
67             Genre => {}, # Genre counts by tracks
68             PGenre => {}, # Genre counts by playcount
69             Type => {}, # Track types, file or URL
70             Items => {},
71             Playlists => {},
72             };
73              
74 1         4 bless $self, $class;
75 1         3 return $self;
76             } #new
77              
78             # Clean up
79 0     0     sub DESTROY {
80             # Nothing to do.
81             } #DESTROY
82              
83             =head2 version()
84              
85             Get/set the plist version number.
86              
87             =cut
88              
89             sub version {
90 0     0 1   my $self = shift;
91              
92 0 0         if (@_) {
93 0           $self->{'plist'}{'version'} = shift;
94             } else {
95 0           return $self->{'plist'}{'version'};
96             }
97             } #version
98              
99             =head2 majorVersion()
100              
101             Get/set the Major Version number
102              
103             =cut
104              
105             sub majorVersion {
106 0     0 1   my $self = shift;
107              
108 0 0         if (@_) {
109 0           $self->{'Major Version'} = shift;
110             } else {
111 0           return $self->{'Major Version'};
112             }
113             } #majorVersion
114              
115             =head2 minorVersion()
116              
117             Get/set the Minor Version number
118              
119             =cut
120              
121             sub minorVersion {
122 0     0 1   my $self = shift;
123              
124 0 0         if (@_) {
125 0           $self->{'Minor Version'} = shift;
126             } else {
127 0           return $self->{'Minor Version'};
128             }
129             } #minorVersion
130              
131             =head2 applicationVersion()
132              
133             Get/set the Application Version number
134              
135             =cut
136              
137             sub applicationVersion {
138 0     0 1   my $self = shift;
139              
140 0 0         if (@_) {
141 0           $self->{'Application Version'} = shift;
142             } else {
143 0           return $self->{'Application Version'};
144             }
145             } #applicationVersion
146              
147             =head2 features()
148              
149             Get/set the Features attribute
150              
151             =cut
152              
153             sub features {
154 0     0 1   my $self = shift;
155              
156 0 0         if (@_) {
157 0           $self->{'Features'} = shift;
158             } else {
159 0           return $self->{'Features'};
160             }
161             } #features
162              
163             =head2 showContentRatings()
164              
165             Get/set the Show Content Ratings attribute
166              
167             =cut
168              
169             sub showContentRatings {
170 0     0 1   my $self = shift;
171              
172 0 0         if (@_) {
173 0           $self->{'Show Content Ratings'} = shift;
174             } else {
175 0           return $self->{'Show Content Ratings'};
176             }
177             } #showContentRatings
178              
179             =head2 musicFolder()
180              
181             Get/set the Music Folder attribute
182              
183             =cut
184              
185             sub musicFolder {
186 0     0 1   my $self = shift;
187              
188 0 0         if (@_) {
189 0           $self->{'Music Folder'} = shift;
190             } else {
191 0           return $self->{'Music Folder'};
192             }
193             } #musicFolder
194              
195             =head2 libraryPersistentID()
196              
197             Get/set the Library Persistent ID
198              
199             =cut
200              
201             sub libraryPersistentID {
202 0     0 1   my $self = shift;
203              
204 0 0         if (@_) {
205 0           $self->{'Library Persistent ID'} = shift;
206             } else {
207 0           return $self->{'Library Persistent ID'};
208             }
209             } #libraryPersistentID
210              
211             =head2 num()
212              
213             Get the number of tracks in the library
214              
215             =cut
216              
217             sub num {
218 0     0 1   my $self = shift;
219 0           return $self->{'Num'};
220             } #num
221              
222             # Increment the number of tracks in the library
223             sub _num {
224 0     0     my $self = shift;
225 0           $self->{'Num'} += 1;
226             } #_num
227              
228             =head2 size()
229              
230             Get the total size of the library
231              
232             =cut
233              
234             sub size {
235 0     0 1   my $self = shift;
236 0           return $self->{'Size'};
237             } #size
238              
239             # Add to the library's total size
240             sub _size {
241 0     0     my $self = shift;
242 0           my $num = shift;
243 0 0         return unless ( defined $num );
244 0           $self->{'Size'} += $num;
245             } #_size
246              
247             =head2 time()
248              
249             Get the total time of the library
250              
251             =cut
252              
253             sub time {
254 0     0 1   my $self = shift;
255 0           return $self->{'Time'};
256             } #time
257              
258             # Add to the library's total time
259             sub _time {
260 0     0     my $self = shift;
261 0           my $time = shift;
262 0 0         return unless ( defined $time );
263 0 0         $self->{'Time'} += $time if (defined $time);
264             } #_time
265              
266             =head2 artist()
267              
268             Get the hash of the number of tracks for each artist.
269              
270             =cut
271              
272             sub artist {
273 0     0 1   my $self = shift;
274 0           return %{$self->{'Artist'}};
  0            
275             } #artist
276              
277             # Increment the track count for the given artist
278             # ($artist)
279             sub _artist {
280 0     0     my $self = shift;
281 0           my $artist = shift;
282 0 0         return unless ( defined $artist );
283 0           $self->{'Artist'}{ $artist } += 1;
284             } #_artist
285              
286             =head2 partist()
287              
288             Get the hash of the number of plays (playcount) for each artist.
289              
290             =cut
291              
292             sub partist {
293 0     0 1   my $self = shift;
294 0           return %{$self->{'PArtists'}};
  0            
295             } #partist
296              
297             # Increment the playcount for the given artist by a given amount
298             # ($artist, $num)
299             sub _partist {
300 0     0     my $self = shift;
301 0           my ($artist, $num) = @_;
302 0 0         return unless ( defined $artist );
303 0 0         return unless ( defined $num );
304 0           $self->{'PArtists'}{ $artist } += $num;
305             } #_partist
306              
307             =head2 albumArtist()
308              
309             Get the hash of the number of tracks for each albumArtist.
310              
311             =cut
312              
313             sub albumArtist {
314 0     0 1   my $self = shift;
315 0           return %{$self->{'AlbumArtist'}};
  0            
316             } #albumArtist
317              
318             # Increment the track count for the given albumArtist
319             # ($albumArtist)
320             sub _albumArtist {
321 0     0     my $self = shift;
322 0           my $albumArtist = shift;
323 0 0         return unless ( defined $albumArtist );
324 0           $self->{'AlbumArtist'}{ $albumArtist } += 1;
325             } #_albumArtist
326              
327             =head2 palbumArtist()
328              
329             Get the hash of the number of plays (playcount) for each albumArtist.
330              
331             =cut
332              
333             sub palbumArtist {
334 0     0 1   my $self = shift;
335 0           return %{$self->{'PAlbumArtists'}};
  0            
336             } #partist
337              
338             # Increment the playcount for the given albumArtist by a given amount
339             # ($albumArtist, $num)
340             sub _palbumArtist {
341 0     0     my $self = shift;
342 0           my ($albumArtist, $num) = @_;
343 0 0         return unless ( defined $albumArtist );
344 0 0         return unless ( defined $num );
345 0           $self->{'PAlbumArtists'}{ $albumArtist } += $num;
346             } #_palbumArtist
347              
348             =head2 genre()
349              
350             Get the hash of the number of tracks in each genre.
351              
352             =cut
353              
354             sub genre {
355 0     0 1   my $self = shift;
356 0           return %{$self->{'Genre'}};
  0            
357             } #genre
358              
359             # Incrment the track count for the given genre
360             # ($genre)
361             sub _genre {
362 0     0     my $self = shift;
363 0           my $genre = shift;
364 0 0         return unless ( defined $genre );
365 0           $self->{'Genre'}{ $genre } += 1;
366             } #_genre
367              
368             =head2 pgenre()
369              
370             Get the hash of the number of plays (playcount) for each genre.
371              
372             =cut
373              
374             sub pgenre {
375 0     0 1   my $self = shift;
376 0           return %{$self->{'PGenre'}};
  0            
377             } #pgenre
378              
379             # Increment the playcount for the given genre by a given amount
380             # ($genre, $playcount)
381             sub _pgenre {
382 0     0     my $self = shift;
383 0           my ($genre, $num) = @_;
384 0 0         return unless ( defined $genre );
385 0 0         return unless ( defined $num );
386 0           $self->{'PGenre'}{ $genre } += $num;
387             } #_pgenre
388              
389             =head2 type()
390              
391             Get the hash of item types in the library
392              
393             =cut
394              
395             sub type {
396 0     0 1   my $self = shift;
397 0           return %{$self->{'Type'}};
  0            
398             } #type
399              
400             # Increment the count of items of the given type
401             sub _type {
402 0     0     my $self = shift;
403 0           my $type = shift;
404 0 0         return unless ( defined $type );
405 0           $self->{'Type'}{ $type } += 1;
406             } #_type
407              
408             =head2 items()
409              
410             Get the hash of Items (Artist->Name->[item, item]) contained in the library;
411             artist names are the top level keys; accessing one gives you a hash-ref with
412             keys of song names and array-refs as values. Those array-refs contain
413             Mac::iTunes::Library::Item objects.
414              
415             =over 4
416              
417             =item Example traversal:
418              
419             # Assuming a previously created library
420             %items = $library->items();
421             while (($artist, $artistSongs) = each %items) {
422             while (($songName, artistSongItems) = each %$artistSongs) {
423             foreach my $item (@$artistSongItems) {
424             # Do something here to every item in the library
425             print $song->name() . "\n";
426             }
427             }
428             }
429              
430             =back
431              
432             =cut
433              
434             sub items {
435 0     0 1   my $self = shift;
436 0           return %{$self->{'Items'}};
  0            
437             } #items
438              
439             # Add an item to our collection
440             sub _item {
441 0     0     my $self = shift;
442 0           my $item = shift;
443              
444 0           my $artist = $item->artist();
445 0           my $name = $item->name();
446 0 0         $artist = 'Unknown' unless (defined $artist);
447 0 0         $name = 'Unknown' unless (defined $name);
448              
449             # Finally, add it to our collection of items
450 0 0         if (exists $self->{'Items'}{$artist}) {
451 0 0         if (exists $self->{'Items'}{$artist}{$name}) {
452 0           push @{$self->{'Items'}{$artist}{$name}}, $item;
  0            
453             } else {
454             # First occurrence of this title
455 0           $self->{'Items'}{$artist}{$name} = [$item];
456             }
457             } else {
458             # First occurrence of this artist
459 0           $self->{'Items'}{$artist}{$name} = [$item];
460             }
461              
462             # print "creating item: " . $item->trackID . "\n";
463 0           $self->{'ItemsById'}{$item->trackID} = \$item; # TODO: this should be a ref
464              
465             } #_item
466              
467             =head2 add( Mac::iTunes::Library::Item )
468              
469             Add an item to the library
470              
471             =cut
472              
473             sub add {
474 0     0 1   my $self = shift;
475 0           my $item = shift;
476 0 0         return carp "Not enough arguments." unless (defined $item);
477 0 0         return carp "Argument isn't a Mac::iTunes::Library::Item."
478             unless ($item->isa("Mac::iTunes::Library::Item"));
479              
480 0           my $artist = $item->artist();
481 0           my $albumArtist = $item->albumArtist();
482 0           my $name = $item->name();
483 0           my $genre = $item->genre();
484 0           my $playCount = $item->playCount();
485              
486             # Deal with possible null values
487 0 0         $artist = 'Unknown' unless (defined $artist);
488 0 0         $albumArtist = 'Unknown' unless (defined $albumArtist);
489 0 0         $name = 'Unknown' unless (defined $name);
490 0 0         $genre = 'Unknown' unless (defined $genre);
491 0 0         $playCount = 0 unless (defined $playCount);
492              
493             # Tally up the item's data
494 0           $self->_artist($artist);
495 0           $self->_albumArtist($albumArtist);
496 0           $self->_genre($genre);
497 0           $self->_num();
498 0 0         $self->_size($item->size()) if (defined $item->size()); # Streams = null
499 0           $self->_time($item->totalTime());
500 0           $self->_partist($item->artist(), $item->playCount());
501 0           $self->_palbumArtist($item->albumArtist(), $item->playCount());
502 0           $self->_pgenre($item->genre(), $item->playCount());
503 0           $self->_type($item->trackType());
504 0           $self->_item($item);
505             } #add
506              
507             sub addPlaylist {
508 0     0 0   my $self = shift;
509 0           my $playlist = shift;
510              
511 0           $self->{'Playlists'}->{ $playlist->{'Playlist ID'} } = $playlist;
512             }
513              
514             sub playlists {
515 0     0 0   my $self = shift;
516 0           return %{$self->{'Playlists'}};
  0            
517             }
518              
519             1;
520              
521             =head1 SEE ALSO
522              
523             L, L,
524             L
525              
526             =head1 AUTHOR
527              
528             Drew Stephens , http://dinomite.net
529              
530             =head1 CONTRIBUTORS
531              
532             =over 4
533              
534             =item *
535              
536             Mark Grimes , (L)
537              
538             =item *
539              
540             Scott Lawrence (L)
541              
542             =item *
543              
544             Garrett Scott , (L)
545              
546             =item *
547              
548             Mark Allen
549              
550             =back
551              
552             =head1 SOURCE REPOSITORY
553              
554             http://mac-itunes.googlecode.com
555              
556             =head1 SVN INFO
557              
558             $Revision: 90 $
559              
560             =head1 COPYRIGHT AND LICENSE
561              
562             Copyright (C) 2007-2008 by Drew Stephens
563              
564             This library is free software; you can redistribute it and/or modify
565             it under the same terms as Perl itself, either Perl version 5.8.8 or,
566             at your option, any later version of Perl 5 you may have available.
567              
568             =cut
569             __END__