#! /usr/bin/perl # Quick hack to make an .M3U for a directory full of .ogg files. # Reads all the .ogg files and then produces an M3U for them. # Always uses the current directory, and writes a file. # If that file exists, aborts. If there are no oggs, writes no file. # If you want recursion... use find. use strict; use warnings; use File::Glob ':glob'; use Date::Manip; our $OGGINFO = '/usr/local/bin/ogginfo'; my $cwdname = `pwd`; chomp $cwdname; if($cwdname =~ /([^\/]*)$/) { $cwdname = $1; } if(-e "$cwdname.m3u") { warn "File $cwdname.m3u exists; not processing."; exit 0; } my @files = bsd_glob('./*.ogg', GLOB_NOSORT|GLOB_ERR); if(GLOB_ERROR) { die "Can't read directory: $!"; } unless(@files) { warn "No .ogg files; not processing."; exit 0; } my @refs = (); foreach my $file (@files) { push @refs, getfileinfo($file); } @refs = sort trackorder @refs; open(OUTFL, ">$cwdname.m3u") or die "Can't write $cwdname.m3u: $!"; print OUTFL "#EXTM3U\n"; foreach my $ref (@refs) { if($ref->{artist}) { print OUTFL "#EXTINF:$ref->{length},$ref->{artist} - $ref->{title}\n"; } else { print OUTFL "#EXTINF:$ref->{length},$ref->{title}\n"; } print OUTFL "$ref->{filename}\n"; } # Sort function to put items in track order. sub trackorder { # First, sort by album name. if ($a->{album} ne $b->{album}) { return $a->{album} cmp $b->{album}; } # Then, sort by track number. return $a->{tracknumber} <=> $b->{tracknumber}; } # use oggenc to get some file info, and return a reference to that info. sub getfileinfo { my $filename = shift; my @lines = `$OGGINFO $filename`; chomp @lines; my %info = (); $info{filename} = $filename; foreach my $line (@lines) { if($line =~ /\s+(title|artist|genre|album|tracknumber)=(.*)/) { $info{$1} = $2; } if($line =~ /\s+Playback length: (.*)/) { $info{length} = toseconds($1); } } return \%info; } # Given a duration in m:s format, make it seconds. sub toseconds { my $elapsed = shift; $elapsed =~ s/:/ /g; $elapsed =~ s/m /mn /g; my $delta = ParseDateDelta($elapsed); my $seconds = Delta_Format($delta,0,'%st'); $seconds = sprintf("%0.0d", $seconds); return $seconds; }