Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

Recently I posted a little program to implement a watched folder/renamer for newly downloaded mp3 files. More recently, eMusic.com went and changed things around a little on their system. Now the mp3 links are ill-named redirects, and they don't play nicely with GetRight anymore, since GetRight wants to create the file before actually checking out the URL and getting the real server-suggested filename.

BUT! One cool thing about eMusic is the RMP link for each album. It allows you to download the full album, provided your player is Zinf.

Or RealPlayer I think, but puh-leeze, yucko.

The thing is, I dig winamp. I don't wanna switch. So I looked at these .rmp files, and saw that they're just XML. A little further googling turned up a groovy java-based utility for RMP files, but that had one problem: It wasn't in perl. So I rolled up my sleeves, found a spec-let for RMP, and wrote a nice little CL-based RMP download utility. It allows you to customize the resulting file names, as well as the option of creating directories for artist/album. I wrote it on windows, but it ought to work in Linux. I'll try that when I can.

I have not done much with XML::* or LWP before, so it was a great learning experience on both fronts. I'm seeking input on the code itself, style, concept, whatever.

the code follows:

#!/usr/bin/perl -w =head1 NAME getrmp.pl =head1 SYNOPSIS Pass it a local filename: getrmp.pl /path/to/somefile.rmp getrmp.pl C:\path\to\somefile.rmp Or a URL: getrmp.pl http://server.com/path/to/somefile.rmp NOTE that URL support is primitive, if the server needs cookies, authentication, or redirects, the program will die. =head1 ABSTRACT RMP is an XML format for playlists, begun initially by RealNetworks I +think. eMusic.com uses it to allow customers to download full albums with one + click. Freeamp/zinf support RMP, but WinAMP does not. And since eMusic.com ch +anged things around recently, it's harder to use dowload managers because th +e mp3 links are given broken names and then redirected. My mouse was getting + tired of clicking each song, so this is quick and dirty an RMP processor tha +t, when passed an RMP file, will download the album and save it somewhere. Be sure to look over the configuration section for customizations. Of course all corporate names used herein are trademarked and copyrigh +ted by their respective owners. And this software is free, with no warranty. +Yeah. =cut use XML::Simple; use LWP::UserAgent; use LWP::Simple; use File::Copy; use strict; ## CONFIGURATION ## Where to put files my $dlpath = "d:\\music\\"; ## Make directories for each artist? my $artistdir = 1; ## Make sub-artist directories for each album? my $albumdir = 0; ## How to name the new music files. my $naming = '[##ARTIST## - ##ALBUM##] ##TRACK## ##TITLE##'; ### Other configs ## User agent to report my $agent = 'Mozilla/8.0'; ### END OF CONFIGURATION my $ua = LWP::UserAgent->new; $ua->agent($agent); my $rmpfilename = $ARGV[0] || die q| Usage: getrmp.pl path/or/URL/to/file.rmp getrmp.pl C:\path\to\somefile.rmp getrmp.pl http://server.com/path/to/somefile.rmp |; my $rmpfile; #### This IF construct may not work if it needs authentication, #### cookie, or redirect support. if ($rmpfilename =~ m|^\w+://|) { # we've got a URL print "Getting rmp file: "; my $res = $ua->request( HTTP::Request->new(GET=>$rmpfilename) ); # Check the outcome of the response if ($res->is_success) { $rmpfile = $res->content; print "OK\n"; } else { die "Can't get remote $rmpfilename"; } } else { #it's a regular /path/to/file on disk $rmpfile = $rmpfilename; } my $xmlref = XMLin($rmpfile) || die "Something bad happened with XML:: +Simple"; my $baseurl = 'http://'. $xmlref->{SERVER}{NETNAME}. $xmlref->{SERVER}{LOCATION}; # got these from http://docs.real.com/docs/rn/realone/RMP_Creation_Gui +de.pdf my %parsecodes = ( fid => 'TRACKID', f => 'FILENAME', # Note, emusic.com does not use these two, and I don't know what they +are. see above URL. lid => 'UNUSED', pid => 'UNUSED', ); my $total = scalar @{$xmlref->{TRACKLIST}{TRACK}}; my $tcount; print "Downloading '$xmlref->{TITLE}' from $xmlref->{SERVER}{NETNAME}\ +n\n"; foreach my $track (@{$xmlref->{TRACKLIST}{TRACK}}) { # Weed out some bad characters for (qw(ARTIST ALBUM TITLE)) { $track->{$_} =~ s([\*\?\/\\])(-)g; } my $TRACKNO = sprintf("%02d",++$tcount); # Here's where we make any new dirs if ($artistdir) { makedir($dlpath.$track->{ARTIST}) or die "Can't make directory $dlpath.$track->{ARTIST}"; if ($albumdir) { makedir($dlpath.$track->{ARTIST}."\\".$track->{ALBUM}) or die "Can't make directory $dlpath.$track->{ARTIST}. +$track->{ALBUM}"; } } # Figure out the new filename (my $newfile = $naming) =~ s/##TRACK##/$TRACKNO/g; for (qw(ARTIST ALBUM TITLE)) { $newfile =~ s/##$_##/$track->{$_}/ge; } my $fullpath = $dlpath . ($artistdir ? "$track->{ARTIST}\\" : '') . ($albumdir ? "$track->{ALBUM}\\" : '') . $newfile; my ($expected_length, $bytes_received); open FH, "> $fullpath.getrmp" or die "Can't open file $fullpath.ge +trmp"; binmode (FH); print "$tcount/$total: $newfile\n"; my $url = $baseurl; # Interpolate the path codes for (qw(fid f lid pid)) { $url =~ s/\%$_/$track->{ $parsecodes{$_} }/g; } my ($extension) = ($track->{FILENAME} =~ /(\.\S*)$/); my $tracktime = time; my $res = $ua->request( HTTP::Request->new(GET => $url), sub { my($chunk, $res) = @_; $bytes_received += length($chunk); unless (defined $expected_length) { $expected_length = $res->content_length || 0; } print FH $chunk; progress($bytes_received, $expected_length); },1024); close FH; my $ttime = time - $tracktime; my $kbps = int ($bytes_received / 1024 / $ttime); print " - $bytes_received bytes OK at $kbps KBps\n"; move("$fullpath.getrmp", $fullpath.$extension) or print " ERROR Moving File. Temp file left.\n"; } #END foreach print "Finished\n"; sub progress { my ($val, $tot) = @_; printf("\b" x 4 . "%3d%%", int(100 * $val / $tot)); } sub makedir { my $dir = shift; if (-e $dir) { return 1; }else{ return mkdir $dir; } }

Updated with <READMORE> tag.

cheers!


In reply to RMP-file music downloader (eMusic.com, mp3.com, etc) by sedhed

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (5)
As of 2024-03-28 19:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found