airplay 1.0.0.beta1 → 1.0.0.beta2

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.
Files changed (47) hide show
  1. data/.gitignore +1 -0
  2. data/.travis.yml +9 -0
  3. data/Gemfile +1 -1
  4. data/Gemfile.lock +3 -7
  5. data/README.md +2 -1
  6. data/Rakefile +74 -0
  7. data/airplay-cli.gemspec +19 -0
  8. data/airplay.gemspec +5 -8
  9. data/examples/demo.rb +5 -8
  10. data/lib/airplay.rb +20 -2
  11. data/lib/airplay/cli/version.rb +5 -0
  12. data/lib/airplay/configuration.rb +8 -3
  13. data/lib/airplay/connection.rb +0 -7
  14. data/lib/airplay/devices.rb +4 -1
  15. data/lib/airplay/group.rb +33 -0
  16. data/lib/airplay/group/players.rb +31 -0
  17. data/lib/airplay/playable.rb +7 -3
  18. data/lib/airplay/{protocol/player.rb → player.rb} +37 -17
  19. data/lib/airplay/player/media.rb +22 -0
  20. data/lib/airplay/player/playback_info.rb +51 -0
  21. data/lib/airplay/player/playlist.rb +41 -0
  22. data/lib/airplay/player/timers.rb +27 -0
  23. data/lib/airplay/server.rb +56 -0
  24. data/lib/airplay/server/app.rb +17 -0
  25. data/lib/airplay/version.rb +3 -0
  26. data/lib/airplay/viewable.rb +2 -2
  27. data/lib/airplay/{protocol/viewer.rb → viewer.rb} +2 -2
  28. metadata +22 -73
  29. data/lib/airplay/protocol.rb +0 -12
  30. data/lib/airplay/protocol/app.rb +0 -52
  31. data/lib/airplay/protocol/message.rb +0 -8
  32. data/lib/airplay/protocol/playback_info.rb +0 -49
  33. data/lib/airplay/protocol/reverse.rb +0 -69
  34. data/lib/airplay/protocol/slideshow.rb +0 -66
  35. data/lib/airplay/protocol/timers.rb +0 -25
  36. data/test/fixtures/cassettes/airplay/listing_slideshow_features.yml +0 -201
  37. data/test/fixtures/cassettes/airplay/play_an_entire_video.yml +0 -100
  38. data/test/fixtures/cassettes/airplay/sending_a_video.yml +0 -71
  39. data/test/fixtures/cassettes/airplay/sending_an_image.yml +0 -26439
  40. data/test/fixtures/cassettes/airplay/stop_any_transmission.yml +0 -8851
  41. data/test/integration/discovery_test.rb +0 -13
  42. data/test/integration/features_test.rb +0 -14
  43. data/test/integration/send_media_test.rb +0 -37
  44. data/test/integration/slideshow_test.rb +0 -26
  45. data/test/test_helper.rb +0 -42
  46. data/test/unit/node_test.rb +0 -17
  47. data/test/unit/protocol_test.rb +0 -44
@@ -0,0 +1 @@
1
+ pkg
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ - "2.0.0"
5
+ - "rbx-19mode"
6
+ before_install:
7
+ - "sudo apt-get -qq update"
8
+ - "sudo apt-get -qq install rdnssd libavahi-compat-libdnssd-dev"
9
+ script: bundle exec rake spec
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gemspec
3
+ gemspec name: 'airplay'
4
4
 
5
5
  gem "rake"
6
6
 
@@ -1,17 +1,15 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- airplay (1.0.0.beta1)
4
+ airplay (1.0.0.beta2)
5
5
  CFPropertyList (~> 2.2.0)
6
6
  celluloid (~> 0.15.0)
7
- clap (~> 1.0.0)
8
7
  cuba (~> 3.1.0)
9
8
  dnssd (~> 2.0)
10
9
  log4r (~> 1.1.10)
11
10
  micromachine (~> 1.0.4)
12
11
  net-http-digest_auth (~> 1.2.1)
13
- net-ptth (~> 0.0.10)
14
- ruby-progressbar (~> 1.2.0)
12
+ net-ptth (= 0.0.12)
15
13
  uuid (~> 2.3.6)
16
14
 
17
15
  GEM
@@ -23,7 +21,6 @@ GEM
23
21
  celluloid-io (0.15.0)
24
22
  celluloid (>= 0.15.0)
25
23
  nio4r (>= 0.5.0)
26
- clap (1.0.0)
27
24
  columnize (0.3.6)
28
25
  cuba (3.1.0)
29
26
  rack
@@ -42,14 +39,13 @@ GEM
42
39
  micromachine (1.0.4)
43
40
  minitest (4.4.0)
44
41
  net-http-digest_auth (1.2.1)
45
- net-ptth (0.0.10)
42
+ net-ptth (0.0.12)
46
43
  celluloid-io (~> 0.15.0)
47
44
  http_parser.rb (~> 0.5.3)
48
45
  rack (~> 1.4.5)
49
46
  nio4r (0.5.0)
50
47
  rack (1.4.5)
51
48
  rake (10.1.0)
52
- ruby-progressbar (1.2.0)
53
49
  systemu (2.5.2)
54
50
  timers (1.1.0)
55
51
  uuid (2.3.7)
data/README.md CHANGED
@@ -8,7 +8,8 @@ to add compatibility to other servers.
8
8
 
9
9
  ## Installation
10
10
 
11
- `gem install airplay`
11
+ `gem install airplay --pre`
12
+ `gem install airplay-cli --pre`
12
13
 
13
14
  ## CLI
14
15
 
data/Rakefile CHANGED
@@ -1,9 +1,83 @@
1
+ $: << File.expand_path("../lib", __FILE__)
2
+
1
3
  require "rake/testtask"
4
+ require "fileutils"
5
+ require "airplay/version"
6
+ require "airplay/cli/version"
2
7
 
3
8
  Rake::TestTask.new("spec") do |t|
4
9
  t.libs << "test"
5
10
  t.pattern = "test/**/*_test.rb"
6
11
  end
7
12
 
13
+ class RuleBuilder
14
+ attr_reader :task, :info
15
+
16
+ TASKS = [:lib, :cli]
17
+
18
+ def initialize(options = {})
19
+ @task = options[:task]
20
+
21
+ @info = {
22
+ lib: { name: "airplay", version: Airplay::VERSION },
23
+ cli: { name: "airplay-cli", version: Airplay::CLI::VERSION }
24
+ }
25
+ end
26
+
27
+ def construct(action)
28
+ -> n {
29
+ task.call(:all) do
30
+ TASKS.each { |task| Rake::Task["#{action}:#{task}"].invoke }
31
+ end
32
+
33
+ TASKS.each do |task_name|
34
+ task.call(task_name) { action_method(action, task_name) }
35
+ end
36
+ }
37
+ end
38
+
39
+ private
40
+
41
+ def action_method(action, task_name)
42
+ method("#{action}_gem".to_sym).call(task_name)
43
+ end
44
+
45
+ def build_gem(type)
46
+ name = info[type][:name]
47
+ version = info[type][:version]
48
+
49
+ gem_name = "#{name}-#{version}.gem"
50
+
51
+ FileUtils.mkdir_p("pkg")
52
+ `gem build #{name}.gemspec`
53
+ FileUtils.mv(gem_name, "pkg")
54
+
55
+ puts "#{name} (v#{version}) builded!"
56
+
57
+ "./pkg/#{gem_name}"
58
+ end
59
+
60
+ def install_gem(type)
61
+ name = info[type][:name]
62
+ gem_path = build_gem(type)
63
+ `gem install --local #{gem_path}`
64
+
65
+ puts "#{gem_path} installed!"
66
+ end
67
+
68
+ def release_gem(type)
69
+ name = info[type][:name]
70
+ gem_path = build_gem(type)
71
+ `gem push #{gem_path}`
72
+
73
+ puts "#{gem_path} released!"
74
+ end
75
+ end
76
+
77
+ builder = RuleBuilder.new(task: method(:task))
78
+ namespace :build, &builder.construct(:build)
79
+ namespace :install, &builder.construct(:install)
80
+ namespace :release, &builder.construct(:release)
81
+
8
82
  task :default => [:test]
9
83
  task :test => [:spec]
@@ -0,0 +1,19 @@
1
+ $: << File.expand_path("../lib", __FILE__)
2
+ require "airplay/cli/version"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "airplay-cli"
6
+ s.version = Airplay::CLI::VERSION
7
+ s.summary = "Airplay client CLI"
8
+ s.description = "Send pics and videos using the terminal"
9
+ s.executables = "air"
10
+ s.licenses = ["MIT", "HUGWARE"]
11
+ s.authors = ["elcuervo"]
12
+ s.email = ["yo@brunoaguirre.com"]
13
+ s.homepage = "http://github.com/elcuervo/airplay"
14
+ s.files = %w(bin/air lib/airplay/cli.rb)
15
+
16
+ s.add_dependency("airplay", "~> 1.0.0.beta2")
17
+ s.add_dependency("clap", "~> 1.0.0")
18
+ s.add_dependency("ruby-progressbar", "~> 1.2.0")
19
+ end
@@ -1,9 +1,11 @@
1
+ $: << File.expand_path("../lib", __FILE__)
2
+ require "airplay/version"
3
+
1
4
  Gem::Specification.new do |s|
2
5
  s.name = "airplay"
3
- s.version = "1.0.0.beta1"
6
+ s.version = Airplay::VERSION
4
7
  s.summary = "Airplay client"
5
8
  s.description = "Send image/video to an airplay enabled device"
6
- s.executables = "air"
7
9
  s.licenses = ["MIT", "HUGWARE"]
8
10
  s.authors = ["elcuervo"]
9
11
  s.email = ["yo@brunoaguirre.com"]
@@ -11,7 +13,6 @@ Gem::Specification.new do |s|
11
13
  s.files = `git ls-files`.split("\n")
12
14
  s.test_files = `git ls-files test`.split("\n")
13
15
 
14
- # Lib
15
16
  s.add_dependency("dnssd", "~> 2.0")
16
17
  s.add_dependency("uuid", "~> 2.3.6")
17
18
  s.add_dependency("CFPropertyList", "~> 2.2.0")
@@ -19,13 +20,9 @@ Gem::Specification.new do |s|
19
20
  s.add_dependency("cuba", "~> 3.1.0")
20
21
  s.add_dependency("micromachine", "~> 1.0.4")
21
22
  s.add_dependency("celluloid", "~> 0.15.0")
22
- s.add_dependency("net-ptth", "~> 0.0.10")
23
+ s.add_dependency("net-ptth", "= 0.0.12")
23
24
  s.add_dependency("net-http-digest_auth", "~> 1.2.1")
24
25
 
25
- # CLI
26
- s.add_dependency("clap", "~> 1.0.0")
27
- s.add_dependency("ruby-progressbar", "~> 1.2.0")
28
-
29
26
  s.add_development_dependency("minitest", "~> 4.4.0")
30
27
  s.add_development_dependency("fakeweb", "~> 1.3.0")
31
28
  s.add_development_dependency("vcr", "~> 2.4.0")
@@ -11,21 +11,18 @@ videos = [
11
11
  ]
12
12
 
13
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
14
 
15
+ apple_tv.view("./test/fixtures/files/logo.png", transition: "SlideLeft")
16
+ sleep 2
17
+ puts apple_tv.view("./test/fixtures/files/a.png", transition: "SlideLeft")
18
+ sleep 20
21
19
  exit
22
20
 
23
21
  videos.each do |video|
24
22
  player = apple_tv.play(video)
23
+ sleep 10
25
24
  end
26
25
 
27
- apple_tv.stop
28
-
29
26
  Airplay.group["Backyard"] << Airplay["Pool TV"]
30
27
  Airplay.group["Backyard"] << Airplay.devices.add("BBQTV", "192.168.1.12")
31
28
 
@@ -1,5 +1,8 @@
1
1
  require "airplay/configuration"
2
2
  require "airplay/browser"
3
+ require "airplay/group"
4
+ require "airplay/server"
5
+ require "airplay/version"
3
6
 
4
7
  # Public: Airplay core module
5
8
  #
@@ -9,14 +12,30 @@ module Airplay
9
12
  yield(configuration) if block
10
13
  end
11
14
 
15
+ def server
16
+ @_server ||= Server.new
17
+ end
18
+
12
19
  def browse
13
20
  browser.browse
14
21
  end
15
22
 
23
+ def group
24
+ @_group ||= Hash.new { |h, k| h[k] = Group.new(k) }
25
+ end
26
+
27
+ def all
28
+ @_all ||= begin
29
+ group = Group.new(:all)
30
+ devices.each { |device| group << device }
31
+ group
32
+ end
33
+ end
34
+
16
35
  # Public: Lists found devices
17
36
  #
18
37
  def devices
19
- browse if browser.devices.empty?
38
+ browse if browser.devices.empty? && configuration.autodiscover
20
39
  browser.devices
21
40
  end
22
41
 
@@ -35,4 +54,3 @@ module Airplay
35
54
  end
36
55
  end
37
56
  end
38
-
@@ -0,0 +1,5 @@
1
+ module Airplay
2
+ class CLI
3
+ VERSION = "0.1.0.beta2"
4
+ end
5
+ end
@@ -1,15 +1,19 @@
1
- require 'log4r/config'
1
+ require "log4r/config"
2
+ require "airplay/logger"
2
3
 
3
4
  module Airplay
4
5
  # Public: Handles the Airplay configuration
5
6
  #
6
7
  class Configuration
7
- attr_accessor :log_level, :output
8
+ attr_accessor :log_level, :output, :autodiscover, :host, :port
8
9
 
9
10
  def initialize
10
11
  Log4r.define_levels(*Log4r::Log4rConfig::LogLevels)
11
12
 
12
- @log_level = Log4r::WARN
13
+ @log_level = Log4r::ERROR
14
+ @autodiscover = true
15
+ @host = "0.0.0.0"
16
+ @port = "1337"
13
17
  @output = Log4r::Outputter.stdout
14
18
  end
15
19
 
@@ -24,6 +28,7 @@ module Airplay
24
28
 
25
29
  Log4r::Logger.root.add @output
26
30
  Log4r::Logger.root.level = level
31
+ Celluloid.logger = Airplay::Logger.new("airplay::celluloid")
27
32
  end
28
33
  end
29
34
  end
@@ -8,8 +8,6 @@ module Airplay
8
8
  class Connection
9
9
  Response = Struct.new(:connection, :response)
10
10
 
11
- attr_accessor :reverse, :events, :persistent
12
-
13
11
  include Celluloid
14
12
 
15
13
  def initialize(device, options = {})
@@ -23,11 +21,6 @@ module Airplay
23
21
  @_persistent ||= Airplay::Connection::Persistent.new(address, @options)
24
22
  end
25
23
 
26
- def start_reverse_connection
27
- @reverse = Airplay::Protocol::Reverse.new(Airplay.active)
28
- @reverse.async.connect
29
- end
30
-
31
24
  def close
32
25
  persistent.close
33
26
  @_persistent = nil
@@ -28,6 +28,10 @@ module Airplay
28
28
  find_by_block { |device| device if device.ip == ip }
29
29
  end
30
30
 
31
+ def add(name, address)
32
+ self << Device.new(name: name, address: address)
33
+ end
34
+
31
35
  # Public: Adds a device to the list
32
36
  #
33
37
  # value - The Node
@@ -41,6 +45,5 @@ module Airplay
41
45
  def find_by_block(&block)
42
46
  @items.find(&block)
43
47
  end
44
-
45
48
  end
46
49
  end
@@ -0,0 +1,33 @@
1
+ require "forwardable"
2
+ require "airplay/group/players"
3
+
4
+ module Airplay
5
+ class Group
6
+ include Enumerable
7
+ extend Forwardable
8
+
9
+ def_delegators :@devices, :each, :size, :empty?
10
+
11
+ def initialize(name)
12
+ @devices = []
13
+ @players = []
14
+ @name = name
15
+ end
16
+
17
+ def <<(device)
18
+ @devices << device
19
+ end
20
+
21
+ def play(file_or_url, options = {})
22
+ @players = @devices.map { |device| device.play(file_or_url, options) }
23
+ Players.new(@players)
24
+ end
25
+
26
+ def view(media_or_io, options = {})
27
+ @devices.map do |device|
28
+ ok = device.view(media_or_io, options)
29
+ [device, ok]
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,31 @@
1
+ module Airplay
2
+ class Group
3
+ class Players
4
+ attr_reader :players
5
+
6
+ def initialize(players)
7
+ @players = players
8
+ end
9
+
10
+ def progress(callback)
11
+ players.each do |player|
12
+ player.progress -> info {
13
+ callback.call(player.device, info) if player.playing?
14
+ }
15
+ end
16
+ end
17
+
18
+ def wait
19
+ sleep 0.1 while still_playing?
20
+ players.map(&:cleanup)
21
+ end
22
+
23
+ private
24
+
25
+ def still_playing?
26
+ states = players.map { |player| !player.played? || player.stopped? }
27
+ states.uniq == [true]
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,4 +1,4 @@
1
- require "airplay/protocol/player"
1
+ require "airplay/player"
2
2
 
3
3
  module Airplay
4
4
  module Playable
@@ -10,15 +10,19 @@ module Airplay
10
10
  #
11
11
  # Returns a Player object to control the playback
12
12
  #
13
- def play(file_or_url, options = {})
13
+ def play(file_or_url = "playlist", options = {})
14
14
  player.async.play(file_or_url, options)
15
15
  player
16
16
  end
17
17
 
18
+ def playlist
19
+ player.playlist
20
+ end
21
+
18
22
  private
19
23
 
20
24
  def player
21
- @_player ||= Airplay::Protocol::Player.new(self)
25
+ @_player ||= Airplay::Player.new(self)
22
26
  end
23
27
  end
24
28
  end