Advertisement
Guest User

Script get_mp3, main routines

a guest
Jul 16th, 2014
299
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 7.13 KB | None | 0 0
  1. #!/usr/bin/ruby
  2. #encoding: UTF-8
  3. =begin
  4. /***************************************************************************
  5.  *   ©2011-2014 Michael Uplawski <michael.uplawski@uplawski.eu>            *
  6.  *                                                                         *
  7.  *   This program is free software; you can redistribute it and/or modify  *
  8.  *   it under the terms of the GNU General Public License as published by  *
  9.  *   the Free Software Foundation; either version 3 of the License, or     *
  10.  *   (at your option) any later version.                                   *
  11.  *                                                                         *
  12.  *   This program is distributed in the hope that it will be useful,       *
  13.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
  14.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
  15.  *   GNU General Public License for more details.                          *
  16.  *                                                                         *
  17.  *   You should have received a copy of the GNU General Public License     *
  18.  *   along with this program; if not, write to the                         *
  19.  *   Free Software Foundation, Inc.,                                       *
  20.  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  21.  ***************************************************************************
  22. =end
  23. require 'open-uri'
  24. require 'io/console'
  25. require_relative 'busy_indicator'
  26. require_relative 'download_history'
  27. require_relative 'download'
  28.  
  29. $VERSION = 0.5
  30. CULT = "http://www.franceculture.fr/"
  31. INTER = "http://www.franceinter.fr/"
  32.  
  33. =begin
  34.     Returns a connection to 'host' via 'port', taking into account the
  35.     possibility of a system-wide proxy-setting.  For the time being, the
  36.     proxy must be defined in the environment variable 'http_proxy', like
  37.     this: http_proxy="http://proxy.url:port".
  38.     Example: http_proxy="http://localhost:8080"
  39.     Example: http_proxy="http://my.proxy.provider.com:3128"
  40.  
  41.     If not defined in this way, no proxy is used and the connection will be
  42.     direct.
  43. =end
  44. def http(host, port)
  45.     hos = nil
  46.     begin
  47.         hos = RbConfig['host_os']
  48.     rescue Exception => ex
  49.         hos = RUBY_PLATFORM
  50.     end
  51.  
  52.         connection = nil   
  53.     if(hos && /linux/ =~ hos )
  54.         proxy = ENV['http_proxy']
  55.         if(proxy)
  56.             parray = proxy.split(':')
  57.             if(parray.size == 3)
  58.                 http, phost, pport = parray
  59.                 if(phost.start_with?('//'))
  60.                    phost = phost[2..phost.size]
  61.                 end
  62.                 puts 'Using proxy at ' << phost << ', port ' << pport
  63.                 connection = Net::HTTP.new(host, nil, phost,pport)
  64.             end
  65.         end
  66.     end
  67.     puts 'direct connection, no useable proxy-setting found' if !connection
  68.     connection ||= Net::HTTP.new(host,port)
  69. end
  70.  
  71. =begin
  72.     Download url, save to filename.
  73.     Copied&Pasted from https://stackoverflow.com/questions/2263540/how-do-i-download-a-binary-file-over-http/6964173#6964173
  74. =end
  75. def http_to_file(filename,url,opt={})
  76.     opt = {
  77.         :init_pause => 0.1,    #start by waiting this long each time
  78.         # it's deliberately long so we can see
  79.         # what a full buffer looks like
  80.         :learn_period => 0.3,  #keep the initial pause for at least this many seconds
  81.         :drop => 1.5,          #fast reducing factor to find roughly optimized pause time
  82.         :adjust => 1.05        #during the normal period, adjust up or down by this factor
  83.     }.merge(opt)
  84.     pause = opt[:init_pause]
  85.     learn = 1 + (opt[:learn_period]/pause).to_i
  86.     drop_period = true
  87.     delta = 0
  88.     max_delta = 0
  89.     last_pos = 0
  90.  
  91.     File.open(filename,'w') do |f|
  92.         uri = URI.parse(url)
  93.         http(uri.host, uri.port).start do |http|
  94.             bi = BusyIndicator.new(true)
  95.             http.request_get(uri.path) do |res|
  96.                 res.read_body do |seg|
  97.                     f << seg
  98.                     delta = f.pos - last_pos
  99.                     last_pos += delta
  100.                     $HISTORY.update(url, :position => last_pos)
  101.                     if delta > max_delta then max_delta = delta end
  102.                     if learn <= 0 then
  103.                         learn -= 1
  104.                     elsif delta == max_delta then
  105.                         if drop_period then
  106.                             pause /= opt[:drop]
  107.                         else
  108.                             pause /= opt[:adjust]
  109.                         end
  110.                     elsif delta < max_delta then
  111.                         drop_period = false
  112.                         pause *= opt[:adjust]
  113.                     end
  114.                     sleep(pause)
  115.  
  116.                 end
  117.             end
  118.             bi.stop('Okay')
  119.         end
  120.     end
  121. end
  122.  
  123. =begin
  124.     Creates and outputs on STDOUT a usage-message containing two exemplary
  125.     command-lines.
  126. =end
  127. def usage
  128.     puts "\nUsage:"
  129.     puts "Call with the URL of the audio-player"
  130.     puts "\t" << __FILE__.split(File::SEPARATOR).last << " http://www.france[culture|inter].fr/sites/..../xxxxxxxxx"
  131.     puts "or an URL and a local file-name:"
  132.     puts "\t" << __FILE__.split(File::SEPARATOR).last << " http://www.france[culture|inter].fr/sites/..../xxxxxxxxx local_file.mp3"
  133.     puts
  134. end
  135.  
  136. def check_history(url)
  137.     previous_download = $HISTORY.previous_download(url)
  138.     if(previous_download)
  139.         puts "\nA previous attempt to download this file has been interrupted."
  140.         puts previous_download.date.to_s << " local file: " << previous_download.local_file << " current size: " << File.size(previous_download.local_file)
  141.         puts "Do you want to continue downloading to " << previous_download.local_file << "(Y/n)?"
  142.         resp = STDIN.getch
  143.         return previous_download if('y' == resp || 'Y' == resp)
  144.     end
  145.     return nil
  146. end
  147.  
  148. =begin
  149.     This program allows you to download broadcasts in MP3-format from the
  150.     web-site of either France-Culture or France-Inter, two popular french
  151.     radio-stations.
  152.     These broadcasts are usually made available in the form of Podcasts
  153.     but the proposed procedure is inconvenient in several ways.
  154.  
  155.     With get_mp3 (or however I choose to name the program in the future) you
  156.     just name the URL to a 'player' and the script will try to locate the
  157.     mp3-file, then download it either to a file of your choice, or
  158.     'download.mp3' in the current directory.
  159.     You can execute the program (get_mp3.rb) once without arguments or with
  160.     the option -h to see two examplary command-lines.
  161.  
  162.     Note, that there is a specific 'player-URL' for each individual broadcast,
  163.     each ending in a numeric suffix (not .html).
  164.     I cannot foresee the decisions which might be taken at Radio France in
  165.     the future, but the program is functional in march 2014. Should they
  166.     choose a different way to publish their audio-files, it will probably
  167.     render this program useless, immediately.
  168. =end
  169. def get_mp3(args)
  170.     if(args.empty?)
  171.         puts "\nMissing parameters!!"
  172.         usage
  173.         exit false
  174.     elsif '-h' == args[0]
  175.         usage
  176.         exit true
  177.     elsif '-v' == args[0]
  178.         puts "version " << $VERSION.to_s
  179.         exit true
  180.     else
  181.         p_url = args[0]
  182.     end
  183.  
  184.     site = nil
  185.  
  186.     local = args[1] if args.length > 1
  187.     local ||= "download.mp3"
  188.     if(p_url.match("^" + CULT))
  189.         site = CULT
  190.     elsif(p_url.match("^" + INTER))
  191.         site = INTER
  192.     end
  193.     page = open(p_url).read
  194.     match = page.match(/(sites%2Fdefault.*\.mp3)/)
  195.     match ||= page.match(/(sites%2Fdefault.*\.MP3)/)
  196.  
  197.     if match
  198.         line = match[1]
  199.         uri = URI.unescape(line)
  200.         file = site + uri
  201.         rd = check_history(file)
  202.         if(rd )
  203.             local = rd.local_file
  204.         end
  205.         puts 'Will download ' << file
  206.         $HISTORY.update(file, :local=>local)       
  207.         http_to_file(local, file)
  208.     end
  209. end
  210.  
  211. # -----------------------
  212. if($0 == __FILE__ )
  213.     get_mp3(ARGV)
  214. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement