airplay 0.1.6 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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