Fixed shh to use different location for shh touchfile
[clearscm.git] / bin / mkplaylist
1 #!/usr/bin/perl
2 ################################################################################
3 #
4 # File:         $RCSfile: mkplaylist,v $
5 # Revision:     $Revision: 1.5 $
6 # Description:  Script to generate a random playlist of x nbr files
7 # Author:       Andrew@DeFaria.com
8 # Created:      Wed Sep 13 09:56:55 CDT 2006
9 # Modified:     $Date: 2011/01/09 00:54:42 $
10 # Language:     Perl
11 #
12 # (c) Copyright 2006, ClearSCM, Inc., all rights reserved.
13 #
14 ################################################################################
15 use strict;
16 use warnings;
17
18 use MP3::Info;
19
20 use FindBin;
21 use lib "$FindBin::Bin/../lib";
22
23 use Getopt::Long;
24 use Display;
25 use OSDep;
26 use Utils;
27
28 my $version             = "1.0";
29 my $default_music_root  = "/web/Music";
30
31 my %opts;
32 my @mp3files;
33
34 sub Usage {
35   my $msg = shift;
36
37   if (defined $msg) {
38     dipslay $msg;
39   } # if
40
41   display "Usage: $FindBin::Script: [ -verbose | -v ] [ -n <limit> ]";
42   display "\t\t   [ -f <filename> ] [ -m <music_root> ]";
43   display "\nWhere:\n";
44   display "  -n <limit>\t\tLimit playlist to <n> entries (Default: 100 entires)";
45   display "  -verbose\t\tTurn on verbose mode (Default: verbose off)";
46   display "  -f <filename>\t\tWrite playlist to <filename> (Default: playlist.wpl)";
47   display "  -m <music_root>\tStart searching at <music_root> (Default: $default_music_root)";
48   exit 1;
49 } # usage
50
51 sub GetMusic {
52   my $music_dir = shift;
53
54   opendir MUSIC, "$music_dir"
55     or error "Unable to open music directory $music_dir", 1;
56
57   my @entries = grep {!/^\./} readdir MUSIC;
58
59   my $mp3info;
60
61   closedir MUSIC;
62
63   foreach (@entries) {
64     my $entity = "$music_dir/$_";
65     if (-d "$entity") {
66       debug "Subdirectory found - recursing to $entity...";
67       GetMusic ($entity);
68     } else {
69       if (/\.mp3$/) {
70         debug "\t$_";
71         $mp3info = MP3::Info->new ($entity);
72         verbose_nolf ".";
73         # WPL files don't like &.
74         if (!defined $mp3info->{FILE}) {
75           $mp3info->{FILE} = "Unknown";
76         } else {
77           $mp3info->{FILE} =~ s/&/&amp;/g;
78           # When we run on Linux is /web but from XP it's //Jupiter
79           $mp3info->{FILE} =~ s/\/web/\/\/Jupiter/;
80         } # if
81
82         push @mp3files, $mp3info;
83       } else {
84         debug "-\t$_ skipped";
85       } # if
86     } # if
87   } # foreach
88 } # GetMusic
89
90 sub RandomizePlaylist {
91   my @mp3files = @_;
92
93   my @return_titles;
94
95   my @genres_to_skip = (
96     "Audio Book",
97     "Educational",
98     "Podcast",
99     "Talk Radio",
100   );
101
102   verbose_nolf "Randomizing playlist (${opts {n}})...";
103
104   # if we are asking for more than we have then just return everything
105   if ($opts {n} > $#mp3files) {
106     $opts {n} = $#mp3files;
107     return @mp3files;
108   } # if
109
110   # Fill @return_titles with randomly selected songs.
111   for (my $i = 0; $i < ${opts{n}};) {
112     my $random = int (rand ($#mp3files));
113
114     # These are random songs - not random speach. Certain genres are
115     # always skipped.
116     next unless defined $mp3files[$random]->{GENRE};
117     next if InArray ($mp3files [$random]->{GENRE}, @genres_to_skip);
118
119     # Crude beginnings to a more sophisticated selection mechanism. If
120     # the t option was given then only consider songs that are in the
121     # Genre specified by t. Note this currently loops forever if more
122     # songs are requested than we have.
123     if (defined $opts {t}) {
124       if ($opts {t} eq $mp3files [$random]->{GENRE}) {
125         # Eliminate dups. No sense in giving back the same song more
126         # than once.
127         if (!InArray $mp3files [$random], @return_titles) {
128           push @return_titles, $mp3files [$random];
129           $i++;
130         } else {
131           debug "Eliminating dup";
132         } # if
133       } # if
134     } else {
135       # Eliminate dups. No sense in giving back the same song more
136       # than once.
137       if (!InArray $mp3files [$random], @return_titles) {
138         push @return_titles, $mp3files [$random];
139         $i++;
140       } else {
141         debug "Eliminating dup";
142       } # if
143     } # if
144   } # for
145
146   verbose " done";
147
148   return @return_titles;
149 } # RandomizePlaylist
150
151 sub WritePlaylistXML {
152   my @playlist = @_;
153
154   verbose "Writing playlist ${opts {f}}";
155   open PLAYLIST, ">${opts {f}}"
156     or error "Unable to open playlist file ${opts {f}}", 1;
157
158   # Write heading
159   print PLAYLIST <<END;
160 <?wpl version="1.0"?>
161 <smil>
162   <head>
163     <meta name="Generator" content="Microsoft Windows Media Player -- 10.0.0.3990"/>
164     <author>Andrew\@DeFaria.com Copyright (c) 2006 ($FindBin::Script V$version)</author>
165     <title>Random Playlist of ${opts {n}} songs</title>
166   </head>
167 <body>
168 <seq>
169 END
170
171   my $total_size = 0;
172
173   # Write the songs...
174   foreach (@playlist) {
175     print PLAYLIST "  <media src=\"$_->{FILE}\"/>\n";
176     $total_size += $_->{SIZE}
177   } # foreach
178
179   # Write the footing
180   print PLAYLIST <<END;
181 </seq>
182 </body>
183 </smil>
184 END
185
186   close PLAYLIST;
187   verbose "${opts {n}} entries writen to ${opts {f}} totaling " .
188     int ($total_size / (1024 * 1024)) . " Meg";
189 } # WritePlaylistXML
190
191 # Turn off buffering
192 $| = 1;
193
194 # Set the defaults
195 $opts {n}       = 100;
196 $opts {f}       = "random_playlist.wpl";
197 $opts {m}       = $default_music_root;
198
199 my $result = GetOptions (
200   \%opts,
201   "usage"        => sub { Usage },
202   "verbose"      => sub { set_verbose },
203   "debug"        => sub { set_debug },
204   "n=i",
205   "f=s",
206   "t=s",
207   "m=s",
208 ) || Usage;
209
210 verbose "Gathering information about music in ${opts {m}}...";
211 GetMusic ($opts {m});
212 verbose "\n" . $#mp3files . " files found";
213
214 WritePlaylistXML (RandomizePlaylist (@mp3files));