airplay 0.1.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -17,6 +17,18 @@ airplay.send_image("fancy_pants.jpg")
17
17
  airplay.send_video("http://www.yo-yo.org/mp4/yu2.mp4")
18
18
  ```
19
19
 
20
+ ## Password Authentication
21
+
22
+ ```ruby
23
+ require 'airplay'
24
+
25
+ airplay = Airplay::Client.new
26
+ airplay.use "Apple TV"
27
+ airplay.password "password"
28
+
29
+ airplay.send_image("lolcatz.jpg")
30
+ ```
31
+
20
32
  ## Useful methods
21
33
 
22
34
  ```ruby
@@ -28,3 +40,9 @@ airplay.browse
28
40
  airplay.use "elCuervo"
29
41
  airplay.use "Apple TV"
30
42
  ```
43
+
44
+ ## Contributors
45
+
46
+ Thanks to all the contributors:
47
+
48
+ * File handler support when sending an image. By [pote](http://github.com/pote)
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "airplay"
3
- s.version = "0.1.6"
3
+ s.version = "0.2.0"
4
4
  s.summary = "Airplay client"
5
5
  s.description = "Send image/video to an airplay enabled device"
6
6
  s.authors = ["elcuervo"]
@@ -10,6 +10,11 @@ Gem::Specification.new do |s|
10
10
  s.test_files = `git ls-files spec`.split("\n")
11
11
 
12
12
  s.add_dependency("dnssd")
13
+ s.add_dependency("net-http-digest_auth")
14
+
13
15
  s.add_development_dependency("cutest")
16
+ s.add_development_dependency("mocha")
14
17
  s.add_development_dependency("capybara")
18
+ s.add_development_dependency("fakeweb")
19
+ s.add_development_dependency("vcr")
15
20
  end
@@ -1,5 +1,6 @@
1
1
  require 'dnssd'
2
2
  require 'net/http'
3
+ require 'net/http/digest_auth'
3
4
  require 'uri'
4
5
 
5
6
  module Airplay; end;
@@ -1,5 +1,5 @@
1
1
  class Airplay::Client
2
- attr_reader :servers, :active_server
2
+ attr_reader :servers, :active_server, :password
3
3
 
4
4
  def initialize(server = false)
5
5
  browse unless server
@@ -10,6 +10,10 @@ class Airplay::Client
10
10
  @active_server = server.is_a?(Airplay::Node) ? server : find_by_name(server)
11
11
  end
12
12
 
13
+ def password(password)
14
+ @password = password
15
+ end
16
+
13
17
  def find_by_name(name)
14
18
  found_server = @servers.detect do |server|
15
19
  server if server.name == name
@@ -36,16 +40,20 @@ class Airplay::Client
36
40
  @servers
37
41
  end
38
42
 
43
+ def handler
44
+ Airplay::Protocol.new(@active_server.ip, @active_server.port, @password)
45
+ end
46
+
39
47
  def send_image(image, transition = :none)
40
- Airplay::Protocol::Image.new(@active_server.ip, @active_server.port).send(image, transition)
48
+ Airplay::Protocol::Image.new(handler).send(image, transition)
41
49
  end
42
50
 
43
51
  def send_video(video, position = 0)
44
- Airplay::Protocol::Video.new(@active_server.ip, @active_server.port).send(video, position)
52
+ Airplay::Protocol::Video.new(handler).send(video, position)
45
53
  end
46
54
 
47
55
  def scrub
48
- Airplay::Protocol::Scrub.new(@active_server.ip, @active_server.port).send
56
+ Airplay::Protocol::Scrub.new(handler).send
49
57
  end
50
58
 
51
59
  end
@@ -5,13 +5,25 @@ class Airplay::Protocol
5
5
  SEARCH = '_airplay._tcp.'
6
6
  PORT = 7000
7
7
 
8
- def initialize(host, port = PORT)
8
+ def initialize(host, port = PORT, password)
9
+ @password = password
9
10
  @http = Net::HTTP.new(host, port)
10
11
  @http.set_debug_output($stdout) if ENV.has_key?('HTTP_DEBUG')
11
12
  end
12
13
 
13
14
  def make_request(request)
15
+ uri = URI.parse "http://#{@http.address}:#{@http.port}#{request.path}"
16
+ uri.user = "Airplay"
17
+ uri.password = @password
18
+
14
19
  response = @http.request(request)
20
+ if response['www-authenticate']
21
+ digest_auth = Net::HTTP::DigestAuth.new
22
+ authentication = digest_auth.auth_header uri, response['www-authenticate'], request.method
23
+ request.add_field 'Authorization', authentication
24
+ response = @http.request(request)
25
+ end
26
+
15
27
  raise Airplay::Protocol::InvalidRequestError if response.code == "404"
16
28
  response.body
17
29
  end
@@ -1,4 +1,8 @@
1
- class Airplay::Protocol::Image < Airplay::Protocol
1
+ class Airplay::Protocol::Image
2
+
3
+ def initialize(protocol_handler)
4
+ @http = protocol_handler
5
+ end
2
6
 
3
7
  def resource
4
8
  "/photo"
@@ -16,8 +20,18 @@ class Airplay::Protocol::Image < Airplay::Protocol
16
20
  end
17
21
 
18
22
  def send(image, transition = :none)
19
- body = File.exists?(image) ? File.read(image) : image
20
- put(resource, body, transition_header(transition))
23
+ content = case image
24
+ when String
25
+ if File.exists?(image)
26
+ File.read(image)
27
+ else
28
+ image
29
+ end
30
+ when File
31
+ image.read
32
+ end
33
+
34
+ @http.put(resource, content, transition_header(transition))
21
35
  end
22
36
 
23
37
  end
@@ -1,4 +1,9 @@
1
- class Airplay::Protocol::Scrub < Airplay::Protocol
1
+ class Airplay::Protocol::Scrub
2
+
3
+ def initialize(protocol_handler)
4
+ @http = protocol_handler
5
+ end
6
+
2
7
  def resource
3
8
  "/scrub"
4
9
  end
@@ -8,7 +13,7 @@ class Airplay::Protocol::Scrub < Airplay::Protocol
8
13
  end
9
14
 
10
15
  def send
11
- response = get(resource, plist_headers)
16
+ response = @http.get(resource, plist_headers)
12
17
  result = {}
13
18
  response.delete(":").split.each_slice(2) do |key, value|
14
19
  result[key] = value
@@ -1,4 +1,8 @@
1
- class Airplay::Protocol::Video < Airplay::Protocol
1
+ class Airplay::Protocol::Video
2
+
3
+ def initialize(protocol_handler)
4
+ @http = protocol_handler
5
+ end
2
6
 
3
7
  def resource
4
8
  "/play"
@@ -15,7 +19,7 @@ class Airplay::Protocol::Video < Airplay::Protocol
15
19
  def send(video, position = 0)
16
20
  body = location_body(video)
17
21
  body += position_body(position.to_s)
18
- post(resource, body)
22
+ @http.post(resource, body)
19
23
  end
20
24
 
21
25
  def play
@@ -28,7 +32,4 @@ class Airplay::Protocol::Video < Airplay::Protocol
28
32
  def stop
29
33
  end
30
34
 
31
- def scrub
32
- end
33
-
34
35
  end
@@ -0,0 +1,17 @@
1
+ require File.expand_path("helper", File.dirname(__FILE__))
2
+
3
+ scope do
4
+ setup do
5
+ @airplay = Airplay::Client.new
6
+ end
7
+
8
+ test "connect to an authenticated source" do
9
+ VCR.use_cassette("authenticate all the things!") do
10
+ @airplay.use("Apple TV")
11
+ @airplay.password("password")
12
+
13
+ assert @airplay.scrub.has_key?("duration")
14
+ assert @airplay.scrub.has_key?("position")
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,115 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: http://10.1.0.220:7000/scrub
6
+ body: !!null
7
+ headers:
8
+ user-agent:
9
+ - MediaControl/1.0
10
+ content-type:
11
+ - text/x-apple-plist+xml
12
+ response: !ruby/struct:VCR::Response
13
+ status: !ruby/struct:VCR::ResponseStatus
14
+ code: 401
15
+ message: Unauthorized
16
+ headers:
17
+ date:
18
+ - Tue, 13 Sep 2011 15:39:56 GMT
19
+ content-length:
20
+ - '0'
21
+ www-authenticate:
22
+ - Digest realm="AirPlay", nonce="MTMxNTkyODM5NiA2qY0zAelgDNZNNIydwmb6"
23
+ body: !!null
24
+ http_version: '1.1'
25
+ ignored: false
26
+ - !ruby/struct:VCR::HTTPInteraction
27
+ request: !ruby/struct:VCR::Request
28
+ method: :get
29
+ uri: http://10.1.0.220:7000/scrub
30
+ body: !!null
31
+ headers:
32
+ user-agent:
33
+ - MediaControl/1.0
34
+ content-type:
35
+ - text/x-apple-plist+xml
36
+ host:
37
+ - 10.1.0.220:7000
38
+ authorization:
39
+ - Digest username="Airplay", realm="AirPlay", uri="/scrub", nonce="MTMxNTkyODM5NiA2qY0zAelgDNZNNIydwmb6",
40
+ nc=00000000, cnonce="90ee1f84b26b39569e91c80b6e557dd4", response="40a9f0af92540c432013a1f3b104a0f9"
41
+ response: !ruby/struct:VCR::Response
42
+ status: !ruby/struct:VCR::ResponseStatus
43
+ code: 200
44
+ message: OK
45
+ headers:
46
+ date:
47
+ - Tue, 13 Sep 2011 15:39:56 GMT
48
+ content-type:
49
+ - text/parameters
50
+ content-length:
51
+ - '38'
52
+ body: ! 'duration: 0.000000
53
+
54
+ position: 0.000000
55
+
56
+ '
57
+ http_version: '1.1'
58
+ ignored: false
59
+ - !ruby/struct:VCR::HTTPInteraction
60
+ request: !ruby/struct:VCR::Request
61
+ method: :get
62
+ uri: http://10.1.0.220:7000/scrub
63
+ body: !!null
64
+ headers:
65
+ user-agent:
66
+ - MediaControl/1.0
67
+ content-type:
68
+ - text/x-apple-plist+xml
69
+ response: !ruby/struct:VCR::Response
70
+ status: !ruby/struct:VCR::ResponseStatus
71
+ code: 401
72
+ message: Unauthorized
73
+ headers:
74
+ date:
75
+ - Tue, 13 Sep 2011 15:39:57 GMT
76
+ content-length:
77
+ - '0'
78
+ www-authenticate:
79
+ - Digest realm="AirPlay", nonce="MTMxNTkyODM5NyChKLPuK9vasGcaXca1BxHX"
80
+ body: !!null
81
+ http_version: '1.1'
82
+ ignored: false
83
+ - !ruby/struct:VCR::HTTPInteraction
84
+ request: !ruby/struct:VCR::Request
85
+ method: :get
86
+ uri: http://10.1.0.220:7000/scrub
87
+ body: !!null
88
+ headers:
89
+ user-agent:
90
+ - MediaControl/1.0
91
+ content-type:
92
+ - text/x-apple-plist+xml
93
+ host:
94
+ - 10.1.0.220:7000
95
+ authorization:
96
+ - Digest username="Airplay", realm="AirPlay", uri="/scrub", nonce="MTMxNTkyODM5NyChKLPuK9vasGcaXca1BxHX",
97
+ nc=00000000, cnonce="42d18af5171f6a79f01b98bbb3cd45e0", response="9d9eab10e3aaeeabc36de5860ea5c8e7"
98
+ response: !ruby/struct:VCR::Response
99
+ status: !ruby/struct:VCR::ResponseStatus
100
+ code: 200
101
+ message: OK
102
+ headers:
103
+ date:
104
+ - Tue, 13 Sep 2011 15:39:57 GMT
105
+ content-type:
106
+ - text/parameters
107
+ content-length:
108
+ - '38'
109
+ body: ! 'duration: 0.000000
110
+
111
+ position: 0.000000
112
+
113
+ '
114
+ http_version: '1.1'
115
+ ignored: false
@@ -0,0 +1,57 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: http://10.1.0.220:7000/scrub
6
+ body: !!null
7
+ headers:
8
+ user-agent:
9
+ - MediaControl/1.0
10
+ content-type:
11
+ - text/x-apple-plist+xml
12
+ response: !ruby/struct:VCR::Response
13
+ status: !ruby/struct:VCR::ResponseStatus
14
+ code: 200
15
+ message: OK
16
+ headers:
17
+ date:
18
+ - Wed, 31 Aug 2011 14:36:38 GMT
19
+ content-type:
20
+ - text/parameters
21
+ content-length:
22
+ - '38'
23
+ body: ! 'duration: 0.000000
24
+
25
+ position: 0.000000
26
+
27
+ '
28
+ http_version: '1.1'
29
+ ignored: false
30
+ - !ruby/struct:VCR::HTTPInteraction
31
+ request: !ruby/struct:VCR::Request
32
+ method: :get
33
+ uri: http://10.1.0.220:7000/scrub
34
+ body: !!null
35
+ headers:
36
+ user-agent:
37
+ - MediaControl/1.0
38
+ content-type:
39
+ - text/x-apple-plist+xml
40
+ response: !ruby/struct:VCR::Response
41
+ status: !ruby/struct:VCR::ResponseStatus
42
+ code: 200
43
+ message: OK
44
+ headers:
45
+ date:
46
+ - Wed, 31 Aug 2011 14:36:38 GMT
47
+ content-type:
48
+ - text/parameters
49
+ content-length:
50
+ - '38'
51
+ body: ! 'duration: 0.000000
52
+
53
+ position: 0.000000
54
+
55
+ '
56
+ http_version: '1.1'
57
+ ignored: false
@@ -0,0 +1,104 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :put
5
+ uri: http://10.1.0.220:7000/photo
6
+ body: !binary |-
7
+ R0lGODdhIANYAuMAAMzMzJaWlr6+vrGxsaOjo5ycnLe3t8XFxaqqqgAAAAAA
8
+ AAAAAAAAAAAAAAAAAAAAACwAAAAAIANYAgAE/hDISau9OOvNu/9gKI5kaZ5o
9
+ qq5s675wLM90bd94ru987//AoHBILBqPyKRyyWw6n9CodEqtWq/YrHbL7Xq/
10
+ 4LB4TC6bz+i0es1uu9/wuHxOr9vv+Lx+z+/7/4CBgoOEhYaHiImKi4yNjo+Q
11
+ kZKTlJWWl5iZmpucnZ6foKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9
12
+ vr/AwcLDxMXGx8jJysvMzc7P0NHS09TV1tfY2drb3N3e3+Dh4uPk5ebn6Onq
13
+ 6+zt7u/w8fLz9PX29/j5+vv8/f7/AAMKHEiwoMGDCBMqXMiwocOHECNKnEix
14
+ osWLGDNq3Mixo8eP/iBDihxJsqTJkyhTqlzJsqXLlzBjypxJs6bNmzhz6tzJ
15
+ s6fPn0CDCh1KtKjRo0iTKl3KtKnTp1CjSp1KtarVq1izat3KtavXr2DDih1L
16
+ tqzZs2jTql3Ltq3bt3Djyp1Lt67du3jz6t3Lt6/fv4ADCx5MuLDhw4gTK17M
17
+ uLHjx5AjS55MubLly5gza97MubPnz6BDix5NurTp06hTq17NurXr17Bjy55N
18
+ u7bt27hz697Nu7fv38CDCx9OvLjx48iTK1/OvLnz59CjS59Ovbr169iza9/O
19
+ vbv37+DDix9Pvrz58+jTq1/Pvr379/Djy59Pv779+/jz69/Pv7///wAG/ijg
20
+ gAQWaOCBCCao4IIMNujggxBGKOGEFFZo4YUYZqjhhhx26OGHIIYo4ogklmji
21
+ iSimqOKKLLbo4oswxijjjDTWaOONOOao44489ujjj0AGKeSQRBZp5JFIJqnk
22
+ kkw26eSTUEYp5ZRUVmnllVhmqeWWXHbp5ZdghinmmGSWaeaZaKap5ppstunm
23
+ m3DGKeecdNZp55145qnnnnz26eefgAYq6KCEFmrooYgmquiijDbq6KOQRirp
24
+ pJRWaumlmGaq6aacdurpp6C6IoAAVwowAAEFBKBqAQQMQKoLBxiAQAGp0trq
25
+ ATDEOmutrA6AayECqIrAryzoSmsAtvqaq6zH/iZLLH8GpKrqtNQia8AKAhBQ
26
+ 7bYEvKpCtttW2+0gB0ir6gDYahvutOOmuy673uJ3gLrvUkvAsyQMUG+1CKig
27
+ 777T9gtIudsWcO0J/wIcgMAoJAwww/YJYK7CyMYrAr0U33sCxgpr3AfB6xJg
28
+ AscAe1wCyfuaPF+wFG9r8QcTt1wAviDETPHMfaA8bQEl2KwwziT4DDDQ8rHc
29
+ sssXHy0uCTp3zAcC+9LsQdMlM620vfOBfPXOITi8Nbpdb00t2Hh4jfQIZitN
30
+ 9gdpH722e1CLTS3EGxwgN7VSZ2D33armDYfR6x4swt58+30B4Xcbbh7g4RJg
31
+ gAAGUB2A4hNQbTDk/lSL/IHlj0der+Z1aB0u3SBwjvnnpdd7uefvgt5e3Ou+
32
+ DfvoHTDObwVtq/oyBrbPjXu9u7+ReQm9B/z7u8FbULywx6+bfHmIb0s6AFR3
33
+ MPvSFlyPtfWtX6A9u3XkjizlGXyvqusTmB8A+uV3n7377BlQr9TRVys4BvXj
34
+ ffj8HOQ/Lf38k8PydFcC//Vtf++inAEnh8B1kQ886pueBCK4gdxJEADqe9sF
35
+ LNi+2M1BaOcyAQcxkEEOjNB779LgeUB4vwrIL2QbAGHyDMizGCJPb++qIRzU
36
+ t74TyBCH69JhBn6Ivxy2J4ANLJgGaGhDBy7RiBoA4QPFMECijYCJUUzg/hOD
37
+ 2MRwTbE79driujTwQtppIHcqnEAZpVfBFMIBhAF4XgfWeLszujEDdPSdHT24
38
+ njACcYwdDFcLlfeuC2LwXYOswPIMWQbxMZJ7gdvAIjWgvkRSYJJ91GIRuThE
39
+ Tf5RiZ10ohhByYYFCrFnntxkuE5ZASnWDYrqIeIF8gi+DMAyi6K8wC1D6UUW
40
+ jOqXwBSA3w4QzGDKgIdy9MAuMeBKDCzzAs1MTwlJeMcLLI99F2ha8K7ZAW2u
41
+ wHK8bFyuUIcCbnLAm9aEnwbQmZ7lsXIC0bQALZnHgUpiYJ4Lg6QgVwCw3Q1Q
42
+ VTCg2hfxWEh9bsuS+HzkISO5HhCqMHfYnAAa/jsw0Q1Wc4/hSuMIHobCfb1g
43
+ gBoNGx/bONLmbSukEr0oevAZRxcisaP75EBCqcnQDcxUBQrTJcBe0LR3ksCe
44
+ Mi0oTA86R6E2tF7KOgAPUQpUSaqTAk3VgDlToLAW/hOgLVgg2CA3AFf9FJG1
45
+ e2r6wMqBqapngRk75w3LKlYJsFOqbSWBwujGw2m5QH08A1e1lJU654UVhtlc
46
+ q1MBy56rkrOLZ3slJy0gy1FWy6cbzSkFKOYCpPLQkswUrGOp5dPGfvKx75HY
47
+ 1zwQz89yNrO53CzX/FXVCRgWpSJgKRxDSNpUmna1jLWtKknZHqUeTWWIrRb5
48
+ FojaXvbPj1mFn/qS/olKvsFWAqXd7baKu63hIrc9er0ZZi3wUg1cd7K6dea7
49
+ YKC+CcQ1BWht2XbNG16dApK77YXve9kjvs+R77veHa97w/UB/KrAgNda3kBB
50
+ UN+jUc6/4p0veBWcXwajp677smKC+atM/cqXwh1AcAraJjLzKbS5fDsfBzR8
51
+ 4enu18QZtrB6Cjy0Eat4AwgmcQVkbAID2jgG6VWaHGnMXgcDgMcSALJ3qjiA
52
+ xw0AjowUcoxf3GAMv4DDJXUBiwmAAARIrodNRrGLfaxkJpsHhMCl2vO6zGUv
53
+ T1jLL5gtZwfc1xzGS7TdnbGZT1ytM9e5wj4eD0Qx0LSIBjm+ci5zarN8/ucY
54
+ sHSvM4CjhAEgupMSWn8pFrRxt+xk8ywwbwtMXnSTiGZ4AnoCxE30z2aA1m2q
55
+ DpeTVq1doflpCYQaPRXFwAlzO2jpnpbVteb0rWVwaFWtFwUsNSQP/bZpC2CR
56
+ 1qm+7apiCehLU7dazD12KzWrbGTVQHKQXYH4nrdAzHrW1ridtl+Pu9jFnbdy
57
+ ZLXAWzNgVgqsm3fnxta+mHsCvKp1XRd8dzoJWwF9E5Lf5Yl1BmYN1XTDFeBj
58
+ renBxXnteKugabDdM01jOliGv0/h7HZ4d/x9ybhGlaD4njhRgxpyGqCVzSFg
59
+ IVvLXYGP39OoLTc4yM24wlZLmwICH7hKUxpl/lnv/AV1/bAJ4mzsZ0og5z7v
60
+ +dF/bgGkj4foJS60S0u+AZdL4KZVl/kLcozy/tpcw1inpNavDvNAjvw8QEZw
61
+ u/lMbddqnOMrgHA+ZZD2Oa89sOP+t8XX2fanf33ORhd3shfM23AKdwaGJWAM
62
+ oB7oSjcetBwo9o9Z/mxI1zzXFXg1sqtLachX/n+d33UMrlxLGEge1CQ+/Z9X
63
+ iWrOw5jy5Gnar91pdvtVnFtix7jecS+D4gmN3iNQ+e09P1TbL5z3Ijd+xhFO
64
+ nmliFPnyLHvTmU52qic9ozPQWfH8jAKIm/DcYbeo0tUofZMiOj25y7ZbqX/z
65
+ zUNb1dZu/fsNDUPz/v36q7Dvd/lRn39P513X4YZr4QJ82zFA3AY88kctMxR4
66
+ /jeA1aZ+KCA0AdZ/J8BShtNtwaWADxh5fedqDCgeYJZ7ebZ01hdzJSh+NHdx
67
+ KegC86RDErh19SJsjEeCK1hwJzh9NzhB+9d8CLhvOch/uZZp5BaEPWh6VNc2
68
+ EBg0RahIp6ZYRNiBFOBsRQeF41FFNNNo88d3zKc+3OdubcWFMpA7xGJAzyUC
69
+ 4rNoWDg23fSFGkc9bMh852E5bwZHXSgBA0Q32+YBd2h+WZhmAKczSTg4ETaH
70
+ UfNXJZiHhriCiFhYJVNlV0ZvmdM5w7M5nyOJh7UCxDQqH5dQv9R1Ktg6/ghw
71
+ Khw1NZV4Om24fq1jiacYHnI3Vx+QY/0EArA4by3QigL4gbIYYpY3hHdDgLO4
72
+ hOyRhkqzaM+3NULHc3JzjHi2L9MjdyzAYgpThsgoNsoIANC4g+0UYgSIiltT
73
+ h2wnNt4oAhSzOznWAqSXMiNwjnvXZlcTjubRa/Vyf8amZquEcsIYYZ5oS1Xz
74
+ jULmAff4M2z2jzlkj/RYMPnoHfBIcYOjjqviifMyjAdpZwo5df3ojwy5ZgV0
75
+ kcT4ihoZkUNWkKuyjcUXgyrQinMHA5KljxX5ASYZMAdpktWYfCSZH741Vx6Z
76
+ XSEjklIlOe2yeMyYdSv5AdGiXe7yOTrJbjx5/pTpcQBHFkR8VSwDsCvI0ise
77
+ aWxR2SxUWQP1JUd72Hs8hADyGAJMKZXOkitXySu3IiDEZABd9ThVuQuxwpZF
78
+ ZgBvGSp2eZd4mZd6uZd82Zd++ZeAGZiCOZiEWZiGeZiImZiKuZiM2ZiO+ZiQ
79
+ GZmSOZmUWZmWeZmYmZmauZmc2Zme+ZmgGZqiOZqkWZqmeZqomZqquZqs2Zqu
80
+ +ZqwGZuyOZu0WZu2eZu4mZu6uZu82Zu++ZvAGZzCOZzEWZzGeZzImZzKuZzM
81
+ 2ZzO+ZzQGZ3SOZ3UWZ3WeZ3YmZ3auZ3c2Z3e+Z3gGZ7iOZ7kWZ7meZ7omZ7q
82
+ uZ7s2Z7u+Z7wGZ/y2jmf9Fmf9nmf+Jmf+rmf/Nmf/vmfABqgAjqgBFqgBnqg
83
+ CJqgCrqgDNqgDvqgEBqhEjqhFFqhFnqhGJqhGrqhHNqhHvqhIBqiIjqiJFqi
84
+ JnqiKJqiKrqiLNqiLvqiMBqjMjqjNFqjNnqjOJqjOrqjPNqjPvqjQBqkQjqk
85
+ RFqkRnqkSJqkSrqkTNqkTvqkUBqlUjqlVFqlVnqlWJqlWrqlXNqlXvqlYBqm
86
+ YjqmZFqmZnqmaJqmarqmbNqmbvqmcBqncjqndFqndnqneJqnerqnfNqnfvqn
87
+ gBqoYxEBADs=
88
+ headers:
89
+ user-agent:
90
+ - MediaControl/1.0
91
+ x-apple-transition:
92
+ - None
93
+ response: !ruby/struct:VCR::Response
94
+ status: !ruby/struct:VCR::ResponseStatus
95
+ code: 200
96
+ message: OK
97
+ headers:
98
+ date:
99
+ - Wed, 31 Aug 2011 14:35:23 GMT
100
+ content-length:
101
+ - '0'
102
+ body: !!null
103
+ http_version: '1.1'
104
+ ignored: false
@@ -0,0 +1,25 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :post
5
+ uri: http://10.1.0.220:7000/play
6
+ body: ! 'Content-Location: http://www.yo-yo.org/mp4/yu.mp4
7
+
8
+ Start-Position: 0
9
+
10
+ '
11
+ headers:
12
+ user-agent:
13
+ - MediaControl/1.0
14
+ response: !ruby/struct:VCR::Response
15
+ status: !ruby/struct:VCR::ResponseStatus
16
+ code: 200
17
+ message: OK
18
+ headers:
19
+ date:
20
+ - Wed, 31 Aug 2011 14:36:39 GMT
21
+ content-length:
22
+ - '0'
23
+ body: !!null
24
+ http_version: '1.1'
25
+ ignored: false
@@ -1,4 +1,12 @@
1
1
  $:.unshift(File.expand_path("../lib", File.dirname(__FILE__)))
2
2
 
3
3
  require "airplay"
4
+ require 'vcr'
5
+ require 'mocha'
4
6
  require "cutest"
7
+
8
+ VCR.config do |c|
9
+ c.cassette_library_dir = 'test/fixtures/cassettes/airplay'
10
+ c.default_cassette_options = { :record => :once }
11
+ c.stub_with :fakeweb
12
+ end
@@ -13,12 +13,18 @@ scope do
13
13
  end
14
14
 
15
15
  test "send an image to the server" do
16
- @airplay.use("Apple TV")
17
- assert @airplay.send_image("./test/fixtures/image2.gif").kind_of?(String)
16
+ VCR.use_cassette("send image to apple tv") do
17
+ @airplay.use("Apple TV")
18
+ file_path = "./test/fixtures/image2.gif"
19
+ assert @airplay.send_image(file_path).kind_of?(String)
20
+ assert @airplay.send_image(File.open(file_path)).kind_of?(String)
21
+ end
18
22
  end
19
23
 
20
24
  test "send an image to the server doing a dissolve" do
21
- @airplay.use("Apple TV")
22
- assert @airplay.send_image("./test/fixtures/image.gif", :dissolve).kind_of?(String)
25
+ VCR.use_cassette("send image to apple tv") do
26
+ @airplay.use("Apple TV")
27
+ assert @airplay.send_image("./test/fixtures/image.gif", :dissolve).kind_of?(String)
28
+ end
23
29
  end
24
30
  end
@@ -13,8 +13,10 @@ scope do
13
13
  end
14
14
 
15
15
  test "check scrub status" do
16
- @airplay.use("Apple TV")
17
- assert @airplay.scrub.has_key?("duration")
18
- assert @airplay.scrub.has_key?("position")
16
+ VCR.use_cassette("get current scrub from apple tv") do
17
+ @airplay.use("Apple TV")
18
+ assert @airplay.scrub.has_key?("duration")
19
+ assert @airplay.scrub.has_key?("position")
20
+ end
19
21
  end
20
22
  end
@@ -13,8 +13,9 @@ scope do
13
13
  end
14
14
 
15
15
  test "send a video to the server" do
16
- @airplay.use("Apple TV")
17
- assert @airplay.send_video("http://www.yo-yo.org/mp4/yu.mp4").kind_of?(String)
16
+ VCR.use_cassette("send video to apple tv") do
17
+ @airplay.use("Apple TV")
18
+ assert @airplay.send_video("http://www.yo-yo.org/mp4/yu.mp4").kind_of?(String)
19
+ end
18
20
  end
19
-
20
21
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: airplay
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,12 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-08-30 00:00:00.000000000 -03:00
12
+ date: 2011-09-13 00:00:00.000000000 -03:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: dnssd
17
- requirement: &70190462401180 !ruby/object:Gem::Requirement
17
+ requirement: &70245624906500 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,32 @@ dependencies:
22
22
  version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *70190462401180
25
+ version_requirements: *70245624906500
26
+ - !ruby/object:Gem::Dependency
27
+ name: net-http-digest_auth
28
+ requirement: &70245624906060 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *70245624906060
26
37
  - !ruby/object:Gem::Dependency
27
38
  name: cutest
28
- requirement: &70190462400740 !ruby/object:Gem::Requirement
39
+ requirement: &70245624905640 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *70245624905640
48
+ - !ruby/object:Gem::Dependency
49
+ name: mocha
50
+ requirement: &70245624905220 !ruby/object:Gem::Requirement
29
51
  none: false
30
52
  requirements:
31
53
  - - ! '>='
@@ -33,10 +55,32 @@ dependencies:
33
55
  version: '0'
34
56
  type: :development
35
57
  prerelease: false
36
- version_requirements: *70190462400740
58
+ version_requirements: *70245624905220
37
59
  - !ruby/object:Gem::Dependency
38
60
  name: capybara
39
- requirement: &70190462400320 !ruby/object:Gem::Requirement
61
+ requirement: &70245624904800 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: *70245624904800
70
+ - !ruby/object:Gem::Dependency
71
+ name: fakeweb
72
+ requirement: &70245624904380 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: *70245624904380
81
+ - !ruby/object:Gem::Dependency
82
+ name: vcr
83
+ requirement: &70245624903960 !ruby/object:Gem::Requirement
40
84
  none: false
41
85
  requirements:
42
86
  - - ! '>='
@@ -44,7 +88,7 @@ dependencies:
44
88
  version: '0'
45
89
  type: :development
46
90
  prerelease: false
47
- version_requirements: *70190462400320
91
+ version_requirements: *70245624903960
48
92
  description: Send image/video to an airplay enabled device
49
93
  email:
50
94
  - yo@brunoaguirre.com
@@ -63,7 +107,12 @@ files:
63
107
  - lib/airplay/protocol/image.rb
64
108
  - lib/airplay/protocol/scrub.rb
65
109
  - lib/airplay/protocol/video.rb
110
+ - test/authentication.rb
66
111
  - test/discovery.rb
112
+ - test/fixtures/cassettes/airplay/authenticate_all_the_things_.yml
113
+ - test/fixtures/cassettes/airplay/get_current_scrub_from_apple_tv.yml
114
+ - test/fixtures/cassettes/airplay/send_image_to_apple_tv.yml
115
+ - test/fixtures/cassettes/airplay/send_video_to_apple_tv.yml
67
116
  - test/fixtures/image.gif
68
117
  - test/fixtures/image2.gif
69
118
  - test/helper.rb