Class: IPlayer::Downloader

Inherits:
Object
  • Object
show all
Includes:
Errors
Defined in:
lib/iplayer/downloader.rb

Defined Under Namespace

Classes: Version

Constant Summary collapse

IPHONE_URL =
'http://www.bbc.co.uk/mobile/iplayer/'
SELECTOR_URL =
'http://www.bbc.co.uk/mediaselector/3/auth/iplayer_streaming_http_mp4/%s?%s'
BUG_URL =
'http://www.bbc.co.uk/iplayer/framework/img/o.gif?%d'
MAX_SEGMENT =
4 * 1024 * 1024
COPY_BUFFER =
4 * 1024 * 1024

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(browser, pid) ⇒ Downloader

Returns a new instance of Downloader.



32
33
34
35
# File 'lib/iplayer/downloader.rb', line 32

def initialize(browser, pid)
  @browser = browser
  @pid = pid
end

Instance Attribute Details

#browserObject (readonly)

Returns the value of attribute browser.



16
17
18
# File 'lib/iplayer/downloader.rb', line 16

def browser
  @browser
end

#cookiesObject

Returns the value of attribute cookies.



17
18
19
# File 'lib/iplayer/downloader.rb', line 17

def cookies
  @cookies
end

#pidObject (readonly)

Returns the value of attribute pid.



16
17
18
# File 'lib/iplayer/downloader.rb', line 16

def pid
  @pid
end

Class Method Details

.extract_pid(pid_or_url) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/iplayer/downloader.rb', line 19

def self.extract_pid(pid_or_url)
  case pid_or_url
  when %r!/(?:item|episode|programmes)/([a-z0-9]{8})!
    $1
  when %r!^[a-z0-9]{8}$!
    pid_or_url
  when %r!(b0[a-z0-9]{6})!
    $1
  else
    raise NotAPid, pid_or_url
  end
end

Instance Method Details

#available_versionsObject



47
48
49
# File 'lib/iplayer/downloader.rb', line 47

def available_versions
  .versions.map{ |name, vpid| Version.new(name, vpid) }
end

#download(version_pid, path, options = {}, &blk) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/iplayer/downloader.rb', line 51

def download(version_pid, path, options={}, &blk)
  if options[:subtitles]
    download_subtitles(version_pid, path)
  end

  if File.exist?(path)
    offset = File.size(path)
  else
    offset = 0
  end
  
  File.open(path, 'a+b') do |io|    
    location = real_stream_location(version_pid)
    content_length = content_length_from_initial_request(location)
    yield(offset, content_length) if block_given?
    
    offset.step(content_length - 1, MAX_SEGMENT) do |first_byte|
      last_byte = [first_byte + MAX_SEGMENT - 1, content_length - 1].min
      get(location, Browser::QT_UA, 'Range'=>"bytes=#{first_byte}-#{last_byte}") do |response|
        response.read_body do |data|
          offset += data.length
          io << data
          yield(offset, content_length) if block_given?
        end
      end
    end
  end
end

#get(url, user_agent, options = {}, &blk) ⇒ Object



41
42
43
44
45
# File 'lib/iplayer/downloader.rb', line 41

def get(url, user_agent, options={}, &blk)
  options['User-Agent'] = user_agent
  options['Cookie'] = cookies if cookies
  browser.get(url, options, &blk)
end

#metadataObject



37
38
39
# File 'lib/iplayer/downloader.rb', line 37

def 
  @metadata = Metadata.new(@pid, @browser)
end