#!/usr/bin/perl # Make N702iD music data from iTunes playlist # # ver. 0.2 2006/12/30 Shinji Kono kono@ie.u-ryukyu.ac.jp # # Everyone is permitted to do anything on this program # including copying, modifying, improving, # as long as you don't try to pretend that you wrote it. # i.e., the above copyright notice has to appear in all copies. # Binary distribution requires original version messages. # You don't have to ask before copying, redistribution or publishing. # THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE. =head1 NMAE n702id.pl -- Make N702iD music data from iTunes playlist =head1 SYNOPSIS n702id.pl [-t destination] [-m max-size-megabyte] playlist-name =head1 DESCRIPTION This makes directories MUSIC/DATA, MUSIC/PLAYLIST, copies AAC music data from iTunes playlist-name and creates necessary playlist file. Then you can copy the directory to the miniSD of N702iD. N901p should work in the same way. cp -r MUSIC /Volume/NO\ NAME/PRIVATE/NEC You may need check mini SD in tools menu on N702iD. Only AAC files are copyied. MP3 needs conversion to AAC. Music bought in iTMS cannot played in N702iD. NKF module and MP4::Info is required. =head1 AUTHORS Shinji KONO =cut use strict; use MP4::Info; use NKF; use Getopt::Std; $MP4::Info::use_mp4_utf8 = 1; my $dest = "MUSIC"; my $opts = {}; getopts('dm:st:',$opts); my $debug = $opts->{d}; my $max = 250*430; $max = $opts->{m}*250; # max size in megabyte ($max is 4k blocks) my $shuffle = $opts->{s}; if (! $debug) { if ( -d $opts->{t}) { $dest = $opts->{t}."/MUSIC" ; } system("mkdir -p $dest/DATA"); if ( ! -d $dest ) { die("can't create $dest\n"); } system("mkdir -p $dest/DATA"); system("rm -rf $dest/DATA/*"); system("mkdir -p $dest/PLAYLIST"); system("rm -rf $dest/PLAYLIST/*"); } binmode(STDOUT, ":utf8"); my $data_id; my $playlist_id; my $num ="000" ; my $song ="000" ; if (0) { # search last song while(-f "$dest/PLAYLIST/NECPL$num.M3U") { $num++; } while(-f "$dest/DATA/NECMD$song.M4A") { $song++; } } my %album; my $total_size; # if ($shuffle) { # while(@ARGV) { # push(@dirs,splice(@ARGV,rand(@ARGV),1)); # } # } else { # @dirs = @ARGV; # } # for my $dir (@dirs) { # if (-d $dir) { # &directory($dir); # last if ($max && $total_size>$max); # } # } print "Get files in $ARGV[0] play list\n"; my $arg = ' -e "tell application \"iTunes\""'. ' -e " set aPlaylist to some playlist whose name is \"'.$ARGV[0].'\""'. ' -e " set aList to tracks of aPlaylist"'. ' -e " -- set pathList to {}"'. ' -e " set outputString to \"\""'. ' -e " repeat with anItem in aList"'. ' -e " set aPath to POSIX path of (location of anItem as string)"'. ' -e " -- set pathList to pathList & aPath"'. ' -e " -- set outputString to outputString & quoted form of aPath & \"\\n\""'. ' -e " set outputString to outputString & aPath & \"\\n\""'. ' -e " end repeat"'. ' -e " outputString"'. ' -e "end tell"'; # print "$arg\n"; open(OSA,"osascript $arg |"); binmode(OSA, ":utf8"); # print while(); my @files = ; # print "@files\n"; &all($num++); ©(@files); for my $album (sort keys %album) { next if ($album eq ' ALL'); &playlist($album,$num++); } my $playlist = "$dest/PLAYLIST/NECPL.TXT"; my $exists = -e $playlist; if ($debug) { open(PL,">/dev/stdout"); print PL "\n>$playlist\n"; } else { open(PL,">$playlist"); } print PL "#PLAYLISTINDEX:1.0\n" if (! $exists); foreach my $track ( sort keys %album) { next if ($album{$track}->{num}==0); print PL "#PLAYLIST:$album{$track}->{num},",nkf("-s","$track\n"); print PL $album{$track}->{playlist},"\n"; } sub copy_file { my ($from,$to) = @_; my ($buf); open(IN,'<',$from) || return; open(OUT,'>',$to) || return; while(sysread(IN,$buf,4096)>0) { syswrite(OUT,$buf); } close(OUT); } sub fix_tilde { my ($input) = @_; $input =~ s/\x{301C}/\x{FF5E}/g; $input; } sub copy { my @files = @_; my $numsong = 0; for my $original (@files) { chop($original); print "processing $original\n"; $original = fix_tilde($original); next if ($original !~ /\.m4a$/); my $file = "$dest/DATA/NECMD$song.M4A"; my $size = -s $original; $total_size += (($size+4095)/4096); if ($max && $total_size>$max) { print "$original ingnored due to the size\n"; next; } if ($debug) { if (! -f $original) { print "can't find $original\n"; next; } print "cp \"$original\" $file\n"; } else { # system("cp \"$original\" $file"); copy_file($original,$file); } my $mp4 = new MP4::Info $original; my $track; my $disk; my $album; $track = defined($mp4->TRKN)?${$mp4->TRKN}[0]:0; $disk = defined($mp4->DISK)?${$mp4->DISK}[0]:0; $album = $mp4->album; my $line = "#EXTINF:".$mp4->secs.",".$mp4->artist." - ".$mp4->title."\n"; my %song = (mp4 => $mp4,file=>"..\\DATA\\NECMD$song.M4A\n", line=>$line); if ($track) { $album{$album}->{tracklist}-> {sprintf("%04d,%04d",$disk,$track)} = \%song; $album{$album}->{ num } ++; print ALL nkf("-s",$line); print ALL $song{file}; $album{' ALL'}->{ num } ++; } else { push(@{$album{$album}->{nontracklist}}, \%song); print ALL nkf("-s",$line); print ALL $song{file}; $album{' ALL'}->{ num } ++; } $song++; } } sub all { my ($num) = @_; my $playlist = "$dest/PLAYLIST/NECPL$num.M3U"; $album{' ALL'}->{playlist} = "NECPL$num.M3U"; if ($debug) { open(ALL,">/dev/stdout"); print ALL "\n>$playlist\n"; } else { open(ALL,">$playlist"); } print ALL "#EXTM3U\n"; } sub playlist { my ($album,$num) = @_; my $playlist = "$dest/PLAYLIST/NECPL$num.M3U"; my $tracklist = $album{$album}->{tracklist}; my $nontracklist = $album{$album}->{nontracklist}; $album{$album}->{playlist} = "NECPL$num.M3U"; if ($debug) { open(PL,">/dev/stdout"); print PL "\n>$playlist\n"; } else { open(PL,">$playlist"); } print PL "#EXTM3U\n"; # print PL join(" ",keys %tracklist),"\n"; foreach my $track ( sort { $a cmp $b } keys %{$tracklist}) { # print $track, $tracklist{$track}->{file},"\n"; my $line = $tracklist->{$track}->{line}; # print PL "track: $track\n"; print PL nkf("-s",$line); print PL $tracklist->{$track}->{file}; } foreach my $track ( @{$nontracklist} ) { my $line = $track->{line}; print PL nkf("-s",$line); print PL $track->{file}; } } # end