airplay 0.2.9 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/Gemfile +5 -0
  2. data/Gemfile.lock +68 -0
  3. data/HUGS +15 -0
  4. data/LICENSE +20 -0
  5. data/README.md +50 -72
  6. data/Rakefile +6 -9
  7. data/SPEC.md +34 -0
  8. data/airplay.gemspec +28 -16
  9. data/bin/air +27 -0
  10. data/examples/demo.rb +35 -0
  11. data/examples/image.rb +9 -0
  12. data/examples/video.rb +24 -0
  13. data/lib/airplay.rb +38 -17
  14. data/lib/airplay/browser.rb +68 -0
  15. data/lib/airplay/cli.rb +104 -0
  16. data/lib/airplay/configuration.rb +29 -0
  17. data/lib/airplay/connection.rb +114 -0
  18. data/lib/airplay/connection/authentication.rb +37 -0
  19. data/lib/airplay/connection/persistent.rb +44 -0
  20. data/lib/airplay/device.rb +81 -0
  21. data/lib/airplay/device/features.rb +43 -0
  22. data/lib/airplay/device/info.rb +22 -0
  23. data/lib/airplay/devices.rb +46 -0
  24. data/lib/airplay/logger.rb +20 -0
  25. data/lib/airplay/playable.rb +24 -0
  26. data/lib/airplay/protocol.rb +9 -72
  27. data/lib/airplay/protocol/app.rb +52 -0
  28. data/lib/airplay/protocol/message.rb +8 -0
  29. data/lib/airplay/protocol/playback_info.rb +49 -0
  30. data/lib/airplay/protocol/player.rb +170 -0
  31. data/lib/airplay/protocol/reverse.rb +69 -0
  32. data/lib/airplay/protocol/slideshow.rb +66 -0
  33. data/lib/airplay/protocol/timers.rb +25 -0
  34. data/lib/airplay/protocol/viewer.rb +56 -0
  35. data/lib/airplay/structure.rb +7 -0
  36. data/lib/airplay/viewable.rb +16 -0
  37. data/test/fixtures/cassettes/airplay/listing_slideshow_features.yml +201 -0
  38. data/test/fixtures/cassettes/airplay/play_an_entire_video.yml +100 -0
  39. data/test/fixtures/cassettes/airplay/sending_a_video.yml +71 -0
  40. data/test/fixtures/cassettes/airplay/sending_an_image.yml +26439 -0
  41. data/test/fixtures/cassettes/airplay/stop_any_transmission.yml +8851 -0
  42. data/test/fixtures/files/logo.png +0 -0
  43. data/test/fixtures/files/transition_0.png +0 -0
  44. data/test/fixtures/files/transition_1.png +0 -0
  45. data/test/fixtures/files/transition_2.png +0 -0
  46. data/test/fixtures/files/transition_3.png +0 -0
  47. data/test/integration/discovery_test.rb +13 -0
  48. data/test/integration/features_test.rb +14 -0
  49. data/test/integration/send_media_test.rb +37 -0
  50. data/test/integration/slideshow_test.rb +26 -0
  51. data/test/test_helper.rb +42 -0
  52. data/test/unit/node_test.rb +17 -0
  53. data/test/unit/protocol_test.rb +44 -0
  54. metadata +247 -77
  55. data/.gitignore +0 -2
  56. data/.travis.yml +0 -6
  57. data/examples/jobs.jpg +0 -0
  58. data/examples/send_image.rb +0 -5
  59. data/examples/send_video.rb +0 -7
  60. data/lib/airplay/client.rb +0 -60
  61. data/lib/airplay/protocol/image.rb +0 -41
  62. data/lib/airplay/protocol/media.rb +0 -64
  63. data/lib/airplay/protocol/scrub.rb +0 -37
  64. data/lib/airplay/server.rb +0 -2
  65. data/lib/airplay/server/browser.rb +0 -35
  66. data/lib/airplay/server/node.rb +0 -7
  67. data/test/authentication.rb +0 -13
  68. data/test/discovery.rb +0 -27
  69. data/test/fixtures/cassettes/airplay/authenticate_all_the_things_.yml +0 -139
  70. data/test/fixtures/cassettes/airplay/control_a_video_being_played_in_apple_tv.yml +0 -242
  71. data/test/fixtures/cassettes/airplay/get_current_scrub_from_apple_tv.yml +0 -69
  72. data/test/fixtures/cassettes/airplay/go_to_a_given_position_in_the_video.yml +0 -157
  73. data/test/fixtures/cassettes/airplay/send_audio_to_apple_tv.yml +0 -33
  74. data/test/fixtures/cassettes/airplay/send_image_to_apple_tv.yml +0 -661
  75. data/test/fixtures/cassettes/airplay/send_image_to_apple_tv_with_effects.yml +0 -591
  76. data/test/fixtures/cassettes/airplay/send_video_to_apple_tv.yml +0 -33
  77. data/test/fixtures/image.gif +0 -0
  78. data/test/fixtures/image2.gif +0 -0
  79. data/test/helper.rb +0 -31
  80. data/test/images.rb +0 -31
  81. data/test/media.rb +0 -47
  82. data/test/scrub.rb +0 -31
data/Gemfile CHANGED
@@ -1,4 +1,9 @@
1
1
  source "http://rubygems.org"
2
2
 
3
3
  gemspec
4
+
4
5
  gem "rake"
6
+
7
+ group :development do
8
+ gem "debugger"
9
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,68 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ airplay (1.0.0.beta1)
5
+ CFPropertyList (~> 2.2.0)
6
+ celluloid (~> 0.15.0)
7
+ clap (~> 1.0.0)
8
+ cuba (~> 3.1.0)
9
+ dnssd (~> 2.0)
10
+ log4r (~> 1.1.10)
11
+ micromachine (~> 1.0.4)
12
+ net-http-digest_auth (~> 1.2.1)
13
+ net-ptth (~> 0.0.10)
14
+ ruby-progressbar (~> 1.2.0)
15
+ uuid (~> 2.3.6)
16
+
17
+ GEM
18
+ remote: http://rubygems.org/
19
+ specs:
20
+ CFPropertyList (2.2.3)
21
+ celluloid (0.15.1)
22
+ timers (~> 1.1.0)
23
+ celluloid-io (0.15.0)
24
+ celluloid (>= 0.15.0)
25
+ nio4r (>= 0.5.0)
26
+ clap (1.0.0)
27
+ columnize (0.3.6)
28
+ cuba (3.1.0)
29
+ rack
30
+ debugger (1.6.2)
31
+ columnize (>= 0.3.1)
32
+ debugger-linecache (~> 1.2.0)
33
+ debugger-ruby_core_source (~> 1.2.3)
34
+ debugger-linecache (1.2.0)
35
+ debugger-ruby_core_source (1.2.3)
36
+ dnssd (2.0)
37
+ fakeweb (1.3.0)
38
+ http_parser.rb (0.5.3)
39
+ log4r (1.1.10)
40
+ macaddr (1.6.1)
41
+ systemu (~> 2.5.0)
42
+ micromachine (1.0.4)
43
+ minitest (4.4.0)
44
+ net-http-digest_auth (1.2.1)
45
+ net-ptth (0.0.10)
46
+ celluloid-io (~> 0.15.0)
47
+ http_parser.rb (~> 0.5.3)
48
+ rack (~> 1.4.5)
49
+ nio4r (0.5.0)
50
+ rack (1.4.5)
51
+ rake (10.1.0)
52
+ ruby-progressbar (1.2.0)
53
+ systemu (2.5.2)
54
+ timers (1.1.0)
55
+ uuid (2.3.7)
56
+ macaddr (~> 1.0)
57
+ vcr (2.4.0)
58
+
59
+ PLATFORMS
60
+ ruby
61
+
62
+ DEPENDENCIES
63
+ airplay!
64
+ debugger
65
+ fakeweb (~> 1.3.0)
66
+ minitest (~> 4.4.0)
67
+ rake
68
+ vcr (~> 2.4.0)
data/HUGS ADDED
@@ -0,0 +1,15 @@
1
+ THE HUGWARE LICENSE
2
+
3
+ LICENSE
4
+
5
+ If there is no other license you can do whatever you want with this while you
6
+ retain the attribution to the author.
7
+
8
+ HUGS
9
+
10
+ The author spent time to make this software so please show some gratitude,
11
+ in any
12
+ form. A hug, a tweet, a beer on a conference or just a plain old email. Your
13
+ choice.
14
+
15
+ Less hate, more hugs.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Bruno Aguirre
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,111 +1,89 @@
1
1
  # Airplay
2
+ [![Code Climate](https://codeclimate.com/github/elcuervo/airplay.png)](https://codeclimate.com/github/elcuervo/airplay)
2
3
 
3
- ![Travis](https://secure.travis-ci.org/elcuervo/airplay.png)
4
+ ![Airplay](test/fixtures/files/logo.png)
4
5
 
5
- ![Ruby Airplay](http://elcuervo.co/images/posts/airplay/ruby_airplay.png?1)
6
+ Airplay attempts to be compatible with the latest AppleTV firmware but I'd like
7
+ to add compatibility to other servers.
6
8
 
7
- A client (and someday a server) of the superfancy http content stream technique
8
- that Apple uses in its products.
9
+ ## Installation
9
10
 
10
- Now supports any Airplay-compatible device, like [Airserver](http://www.airserverapp.com/)
11
+ `gem install airplay`
11
12
 
12
- You can try this in an AppleTV for instance.
13
+ ## CLI
13
14
 
14
- ## IMPORTANT!
15
+ ### View devices
15
16
 
16
- Since iOS 5 there are some changes in the API so to keep playing something (like
17
- a video) you must keep the client alive!
18
-
19
- ## Basic Usage
20
-
21
- ```ruby
22
- require 'airplay'
17
+ `air list`
18
+ ```text
19
+ * Apple TV (AppleTV2,1 running 11A502)
20
+ ip: 192.168.1.12
21
+ resolution: 1280x720
22
+ ```
23
23
 
24
- airplay = Airplay::Client.new
25
- # To send an image
26
- airplay.send_image("fancy_pants.jpg")
24
+ ### Play a video
27
25
 
28
- # To stream a video
29
- airplay.send_video("http://www.yo-yo.org/mp4/yu2.mp4")
26
+ `air play [url to video]`
27
+ ```text
28
+ Playing http://movietrailers.apple.com/movies/universal/rush/rush-tlr3_480p.mov?width=848&height=352
29
+ Time: 00:00:13 [===== ] 7% Apple TV
30
30
  ```
31
31
 
32
- ## Sending images
33
-
34
- ```ruby
35
- require 'airplay'
32
+ ### Show images
36
33
 
37
- airplay = Airplay::Client.new
34
+ `air view [url to image or image folder]`
38
35
 
39
- airplay.send_image("fancy_pants.jpg")
40
- airplay.send_image(File.open("/home/userman/Pictures/fancy_pants.jpg"))
41
- airplay.send_image("http://mine.icanhascheezburger.com/completestore/Wezinyercupz128401525895963750.jpg")
42
- ```
36
+ ## Library
43
37
 
44
- ### Transitions
38
+ ### Finding devices
45
39
 
46
40
  ```ruby
47
- require 'airplay'
48
-
49
- airplay = Airplay::Client.new
41
+ require "airplay"
50
42
 
51
- airplay.send_image("fancy_pants.jpg", :dissolve)
52
- airplay.send_image("fancy_pants.jpg", :slide_left)
53
- airplay.send_image("fancy_pants.jpg", :slide_right)
43
+ Airplay.devices.each do |device|
44
+ puts device.name
45
+ end
54
46
  ```
55
47
 
56
- ## Scrub
48
+ ### Sending images
57
49
 
58
50
  ```ruby
59
- require 'airplay'
51
+ require "airplay"
60
52
 
61
- airplay = Airplay::Client.new
62
- airplay.scrub
63
- # {:duration => 189, :position => 50}
64
- airplay.scrub(30) # Media goes to 30s
65
- airplay.scrub("10%") # Media goes to the 10% of its duration
53
+ apple_tv = Airplay["Apple TV"]
54
+ apple_tv.view("my_image.png")
55
+ apple_tv.view("url_to_the_image", transition: "Dissolve")
56
+
57
+ # View all transitions
58
+ apple_tv.transitions
66
59
  ```
67
60
 
68
- ## Password Authentication
61
+ ### Playing video
69
62
 
70
63
  ```ruby
71
- require 'airplay'
64
+ require "airplay"
72
65
 
73
- airplay = Airplay::Client.new
74
- airplay.use "Apple TV"
75
- airplay.password "password"
66
+ apple_tv = Airplay["Apple TV"]
67
+ trailer = "http://movietrailers.apple.com/movies/dreamworks/needforspeed/needforspeed-tlr1xxzzs2_480p.mov"
76
68
 
77
- airplay.send_image("lolcatz.jpg")
78
- ```
69
+ player = apple_tv.play(trailer)
79
70
 
80
- ## Player
71
+ # Wait until the video is finished
72
+ player.wait
81
73
 
82
- ```ruby
83
- require 'airplay'
84
-
85
- airplay = Airplay::Client.new
86
- player = airplay.send_video("http://www.yo-yo.org/mp4/yu2.mp4")
74
+ # Actions
87
75
  player.pause
88
76
  player.resume
89
- player.scrub
90
- # {:duration => 189, :position => 50}
91
- player.scrub("50%") # Go to the half of the media
92
77
  player.stop
93
- ```
94
-
95
- ## Useful methods
96
-
97
- ```ruby
98
- require 'airplay'
78
+ player.scrub
99
79
 
100
- airplay = Airplay::Client.new
101
- airplay.browse
102
- #=> [#<Airplay::Node:0x007fbb5a83eb28 @name="elCuervo", @domain="local.", @ip="10.1.0.63">, #<Airplay::Node:0x007fbb5a83b0b8 @name="Apple TV", @domain="local.", @ip="10.1.0.220">]
103
- airplay.use "elCuervo"
104
- airplay.use "Apple TV"
80
+ # Access the playback time per second
81
+ player.progress -> progress {
82
+ puts "I'm viewing #{progress["position"]} of #{progress["duration"]}"
83
+ }
105
84
  ```
106
85
 
107
86
  ## Contributors
108
87
 
109
- Thanks to all the contributors:
110
-
111
- * File handler support when sending an image. By [pote](http://github.com/pote)
88
+ * [sodabrew](http://github.com/sodabrew)
89
+ * [pote](http://github.com/pote)
data/Rakefile CHANGED
@@ -1,12 +1,9 @@
1
- task :test do
2
- require "cutest"
3
- require "capybara/dsl"
1
+ require "rake/testtask"
4
2
 
5
- Cutest.run(Dir["test/*.rb"])
6
-
7
- class Cutest::Scope
8
- include Capybara::DSL
9
- end
3
+ Rake::TestTask.new("spec") do |t|
4
+ t.libs << "test"
5
+ t.pattern = "test/**/*_test.rb"
10
6
  end
11
7
 
12
- task :default => :test
8
+ task :default => [:test]
9
+ task :test => [:spec]
data/SPEC.md ADDED
@@ -0,0 +1,34 @@
1
+ # Airplay Spec
2
+
3
+ ## CLI
4
+
5
+ ### Commands
6
+
7
+ **play**
8
+ **stop**
9
+ **pause**
10
+
11
+ ```bash
12
+ airplay image.jpg
13
+ airplay image.jpg --transition slide_left
14
+
15
+ airplay video.mp4
16
+ airplay> pause
17
+ ```
18
+
19
+ ## Library
20
+
21
+ ```ruby
22
+ Airplay.send("image.png", transition: :slide_left)
23
+
24
+ player = Airplay.send("video.mp4")
25
+ player.pause
26
+ player.rewind("10s")
27
+
28
+ Airplay.player
29
+ ```
30
+
31
+ ## Documentation
32
+
33
+ * http://nto.github.com/AirPlay.html
34
+ * http://elcuervo.co/protocol/airplay/apple/2012/01/05/airplay-protocol.html
data/airplay.gemspec CHANGED
@@ -1,20 +1,32 @@
1
1
  Gem::Specification.new do |s|
2
- s.name = "airplay"
3
- s.version = "0.2.9"
4
- s.summary = "Airplay client"
5
- s.description = "Send image/video to an airplay enabled device"
6
- s.authors = ["elcuervo"]
7
- s.email = ["yo@brunoaguirre.com"]
8
- s.homepage = "http://github.com/elcuervo/airplay"
9
- s.files = `git ls-files`.split("\n")
10
- s.test_files = `git ls-files test`.split("\n")
2
+ s.name = "airplay"
3
+ s.version = "1.0.0.beta1"
4
+ s.summary = "Airplay client"
5
+ s.description = "Send image/video to an airplay enabled device"
6
+ s.executables = "air"
7
+ s.licenses = ["MIT", "HUGWARE"]
8
+ s.authors = ["elcuervo"]
9
+ s.email = ["yo@brunoaguirre.com"]
10
+ s.homepage = "http://github.com/elcuervo/airplay"
11
+ s.files = `git ls-files`.split("\n")
12
+ s.test_files = `git ls-files test`.split("\n")
11
13
 
12
- s.add_dependency("dnssd", "~> 2.0")
13
- s.add_dependency("net-http-persistent", ">= 2.6")
14
- s.add_dependency("net-http-digest_auth", "~> 1.2")
14
+ # Lib
15
+ s.add_dependency("dnssd", "~> 2.0")
16
+ s.add_dependency("uuid", "~> 2.3.6")
17
+ s.add_dependency("CFPropertyList", "~> 2.2.0")
18
+ s.add_dependency("log4r", "~> 1.1.10")
19
+ s.add_dependency("cuba", "~> 3.1.0")
20
+ s.add_dependency("micromachine", "~> 1.0.4")
21
+ s.add_dependency("celluloid", "~> 0.15.0")
22
+ s.add_dependency("net-ptth", "~> 0.0.10")
23
+ s.add_dependency("net-http-digest_auth", "~> 1.2.1")
15
24
 
16
- s.add_development_dependency("cutest", "~> 1.1")
17
- s.add_development_dependency("capybara", "~> 1.0")
18
- s.add_development_dependency("fakeweb", "~> 1.3")
19
- s.add_development_dependency("vcr", "~> 2.0")
25
+ # CLI
26
+ s.add_dependency("clap", "~> 1.0.0")
27
+ s.add_dependency("ruby-progressbar", "~> 1.2.0")
28
+
29
+ s.add_development_dependency("minitest", "~> 4.4.0")
30
+ s.add_development_dependency("fakeweb", "~> 1.3.0")
31
+ s.add_development_dependency("vcr", "~> 2.4.0")
20
32
  end
data/bin/air ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "clap"
4
+ require "airplay/cli"
5
+
6
+ Clap.run ARGV,
7
+ "--device" => lambda { |device_name| @device = Airplay[device_name] },
8
+ "--wait" => lambda { |sec| @wait = sec.to_i },
9
+ "--interactive" => lambda { @interactive = true },
10
+
11
+ "list" => Airplay::CLI.method(:list),
12
+
13
+ "play" => lambda { |video|
14
+ options = { device: @device || Airplay.devices.first }
15
+ Airplay::CLI.play(video, options)
16
+ },
17
+
18
+ "view" => lambda { |file|
19
+ options = {
20
+ device: @device || Airplay.devices.first,
21
+ interactive: @interactive || false,
22
+ wait: @wait || 3
23
+ }
24
+ Airplay::CLI.view(file, options)
25
+ }
26
+
27
+ # vim: ft=ruby
data/examples/demo.rb ADDED
@@ -0,0 +1,35 @@
1
+ require "airplay"
2
+
3
+ puts Airplay.devices.count
4
+ Airplay.devices.each do |device|
5
+ puts device.name
6
+ end
7
+
8
+ videos = [
9
+ "http://trailers.apple.com/movies/marvel/ironman3/ironman3-tlr1-m4mb0_h1080p.mov",
10
+ "http://movietrailers.apple.com/movies/dreamworks/needforspeed/needforspeed-tlr1xxzzs2_480p.mov"
11
+ ]
12
+
13
+ apple_tv = Airplay["Apple TV"]
14
+ player = apple_tv.play(videos.last)
15
+ sleep 4
16
+ player.stop
17
+ sleep 5
18
+
19
+
20
+
21
+ exit
22
+
23
+ videos.each do |video|
24
+ player = apple_tv.play(video)
25
+ end
26
+
27
+ apple_tv.stop
28
+
29
+ Airplay.group["Backyard"] << Airplay["Pool TV"]
30
+ Airplay.group["Backyard"] << Airplay.devices.add("BBQTV", "192.168.1.12")
31
+
32
+ player = Airplay.group["Backyard"].play("video")
33
+ player.wait
34
+
35
+ Airplay.all # => Alias for a global group of all the available devices