Closed sodabrew closed 12 years ago
Running this i'm not having any issues, are you keeping the client alive?
require 'airplay'
airplay = Airplay::Client.new
airplay.send_image("http://www.prelovac.com/vladimir/wp-content/uploads/2008/03/example.jpg")
airplay.send_image("http://home.comcast.net/~urbanjost/images/globe_west_2048.jpg", :slide_left)
sleep(3) # If the client ends the connection ends
Updated above: added airplay.password call, as I have a password on my ATV.
Wiresharked the connection, and I see that every PUT of a new image is refused with a 401 Unauthorized and a new connection is established and the password sent on the first call through new connection.
I am using sleep between images in my script. Also per the wireshark protocol dump, it looks like airplay is sending a keep alive time of 30 seconds by default -- which means I should be sending a command within that window. Is there a ping command I can make sure to call every so often, in case I want to keep the same image on screen longer?
Steps:
airplay = Airplay::Client.new
airplay.use apple_tv_name
airplay.password apple_tv_password
airplay.send_image(url1)
sleep 3
# image 1 is on the screen for 3 seconds
airplay.send_image(url2)
# at this point, the ATV goes back to home screen, then switches to image 2
sleep 3
# image 2 is on the screen for 3 seconds
Oh… that's great feedback, i'll take a look at that
elCuervo http://elcuervo.co http://github.com/elcuervo
On Wednesday, March 21, 2012 at 5:59 PM, Aaron Stone wrote:
Updated above: added airplay.password call, as I have a password on my ATV.
Wiresharked the connection, and I see that every PUT of a new image is refused with a 401 Unauthorized and a new connection is established and the password sent on the first call through new connection.
Reply to this email directly or view it on GitHub: https://github.com/elcuervo/airplay/issues/10#issuecomment-4627058
First attempt, just reuse the previous authorization. This doesn't seem to work.
diff --git a/lib/airplay/protocol.rb b/lib/airplay/protocol.rb
index e20b6c3..d4cc1d7 100644
--- a/lib/airplay/protocol.rb
+++ b/lib/airplay/protocol.rb
@@ -8,6 +8,7 @@ class Airplay::Protocol
def initialize(host, port, password)
@device = { :host => host, :port => port }
@password = password || '' # Passing nil breaks Net::HTTP::DigestAuth
+ @authentication = false # after a www-authenticate challenge, keep the digest for the next query
@http = Net::HTTP::Persistent.new
@http.debug_output = $stdout if ENV.has_key?('HTTP_DEBUG')
end
@@ -17,11 +18,19 @@ class Airplay::Protocol
uri.user = "Airplay"
uri.password = @password
+ # If there was previously a www-authenticate field, use it again
+ if @authentication
+ request.add_field 'Authorization', @authentication
+ end
+
response = @http.request(uri, request) {}
+
+ # Either it's our first time authenticating with this device, so we have to reply with a digest
+ # based on the previous challenge, or we used our previous challenge and the device wants a new one.
if response['www-authenticate']
digest_auth = Net::HTTP::DigestAuth.new
- authentication = digest_auth.auth_header uri, response['www-authenticate'], request.method
- request.add_field 'Authorization', authentication
+ @authentication = digest_auth.auth_header uri, response['www-authenticate'], request.method
+ request.add_field 'Authorization', @authentication
response = @http.request(uri, request) {}
end
Ok, while I can reproduce the problem just with two send_image calls, upon code inspection I think there's a clear problem with mixed media calls.
The issue is in client.rb, where each of send_image, send_audio, send_video, and scrub create new connections:
def handler
Airplay::Protocol.new(@active_server.ip, @active_server.port, @password)
end
def send_image ...
@image_proxy ||= Airplay::Protocol::Image.new(handler)
...
def send_audio ...
@media_proxy ||= Airplay::Protocol::Image.new(handler)
...
Note that handler always returns a new connection. So you're going to get one connection in @image_proxy, one in @media_proxy, and one more in @scrub_proxy. The docs for Net::HTTP::Persistent don't indicate that it would reuse the open socket to the server. It's not clear how the ATV handles multiple connections, but I wonder if it doesn't like it.
Ok, found it. Problem is here: https://github.com/drbrain/net-http-persistent/blob/master/lib/net/http/persistent.rb#L230
Net::HTTP::Persistent is dropping and restarting connections after 5 seconds.
The code above with sleep 3 DOES work. Raise the sleep times above 5, and then it DOESN'T work!
You can cherry-pick the changes above if you don't want to pull the rest of my fork.
nil doesn't work. Submitted patch to Net::HTTP::Timeout: https://github.com/drbrain/net-http-persistent/pull/21
In the mean time, changed to 900 seconds: https://github.com/sodabrew/airplay/commit/abfbbec554e93b5fed17a331a4ebd5dd08abffa9
Fixed in 3b86cf38bcbac9c4298a697849f2c4cb79f5c18c.
My ATV 2, with latest iOS 5, returns to the home screen in between updates. I haven't started diagnosing what's up -- maybe I'm losing my connection between send_image / send_video calls? Opening this issue in case you've debugged this before.
Steps:
Expected: Apple TV displays url1, then displays url2 without interruption.
Actual: Apple TV displays url2, then home screen, then url2.