openplay 0.0.2
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 +38 -0
- data/bin/openplay +35 -0
- data/lib/openplay.rb +2 -0
- data/lib/openplay/client.rb +52 -0
- data/lib/openplay/determines_resolution.rb +6 -0
- data/lib/openplay/discovers_servers.rb +9 -0
- data/lib/openplay/server.rb +21 -0
- metadata +189 -0
data/README.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
## OpenPlay
|
2
|
+
Screenshare to another machine painlessly, with basic glue for ffmpeg and vlc.
|
3
|
+
|
4
|
+
### Prerequisites
|
5
|
+
On ubuntu:
|
6
|
+
|
7
|
+
sudo apt-get install libavahi-compat-libdnssd-dev
|
8
|
+
|
9
|
+
To throw:
|
10
|
+
|
11
|
+
sudo apt-get install ffmpeg libavcodec-extra-53
|
12
|
+
|
13
|
+
To catch:
|
14
|
+
|
15
|
+
sudo apt-get install vlc
|
16
|
+
|
17
|
+
### Development
|
18
|
+
Run the tests with:
|
19
|
+
|
20
|
+
rake
|
21
|
+
|
22
|
+
### For help
|
23
|
+
./bin/openplay help
|
24
|
+
|
25
|
+
### To receive
|
26
|
+
./bin/openplay receive
|
27
|
+
|
28
|
+
### To list available servers
|
29
|
+
./bin/openplay list
|
30
|
+
|
31
|
+
### To throw
|
32
|
+
#### by Hostname
|
33
|
+
./bin/openplay --hostname=some-host
|
34
|
+
|
35
|
+
#### by IP
|
36
|
+
This needs a real ip, rather than just localhost
|
37
|
+
|
38
|
+
./bin/openplay throw --host=127.0.0.1
|
data/bin/openplay
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'thor'
|
3
|
+
require './lib/openplay/client'
|
4
|
+
require './lib/openplay/server'
|
5
|
+
|
6
|
+
module Openplay
|
7
|
+
class CLI < Thor
|
8
|
+
desc "throw", "Throw video"
|
9
|
+
method_option :host, default: "127.0.0.1", banner: "Host IP"
|
10
|
+
method_option :hostname, banner: "Hostname returned from 'list'"
|
11
|
+
method_option :port, default: 5003, banner: "Port the host is receiving on."
|
12
|
+
method_option :resolution, default: nil
|
13
|
+
def throw
|
14
|
+
@client = ::Openplay::Client.new(options)
|
15
|
+
@client.throw
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "list", "List available servers"
|
19
|
+
def list
|
20
|
+
@client = ::Openplay::Client.new
|
21
|
+
# Just list IPv4 records for now
|
22
|
+
@client.list.each do |server|
|
23
|
+
puts "#{server.hosttxt} on port #{server.port}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "receive", "Receive video"
|
28
|
+
def receive
|
29
|
+
@server = ::Openplay::Server.new
|
30
|
+
@server.receive
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
Openplay::CLI.start
|
data/lib/openplay.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative 'determines_resolution'
|
2
|
+
require_relative 'discovers_servers'
|
3
|
+
|
4
|
+
module Openplay
|
5
|
+
class Client
|
6
|
+
attr_reader :host, :port
|
7
|
+
|
8
|
+
def initialize(options={})
|
9
|
+
if options[:hostname]
|
10
|
+
server = get_server_by_hostname(options[:hostname])
|
11
|
+
raise "No server found with hostname #{options[:hostname]}" unless server
|
12
|
+
@host = server.ip
|
13
|
+
@port = server.port
|
14
|
+
else
|
15
|
+
@host = options[:host]
|
16
|
+
@port = options[:port]
|
17
|
+
end
|
18
|
+
@resolution = options[:resolution] || screen_resolution
|
19
|
+
end
|
20
|
+
|
21
|
+
# Throw video to a particular server
|
22
|
+
def throw
|
23
|
+
options = []
|
24
|
+
options << "-framerate ntsc"
|
25
|
+
options << "-video_size #{@resolution}"
|
26
|
+
options << "-f x11grab -i #{ENV['DISPLAY']}"
|
27
|
+
options << "-f alsa -i pulse"
|
28
|
+
options << "-vcodec libx264 -tune zerolatency -crf 26 -preset ultrafast"
|
29
|
+
options << "-f mpegts udp://#{host}:#{port}?pkt_size=#{packet_size}"
|
30
|
+
`ffmpeg #{options.join(' ')}`
|
31
|
+
end
|
32
|
+
|
33
|
+
# List available servers
|
34
|
+
def list
|
35
|
+
DiscoversServers.find_servers
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
def get_server_by_hostname(hostname)
|
40
|
+
list.detect{|s| s.hosttxt == hostname }
|
41
|
+
end
|
42
|
+
|
43
|
+
def screen_resolution
|
44
|
+
DeterminesResolution.new.get
|
45
|
+
end
|
46
|
+
|
47
|
+
def packet_size
|
48
|
+
# This is tuned for getting mpegts frames into udp packets nicely
|
49
|
+
1316
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'findme'
|
2
|
+
class DiscoversServers
|
3
|
+
def self.find_servers
|
4
|
+
servers = Findme.discover.select{|s| s.service == "_openplay._tcp"}
|
5
|
+
# Only return IPv4 servers for now, there were issues with IPv6
|
6
|
+
# (unacceptable, but whatev)
|
7
|
+
servers.select{|s| s.ipv4 == "IPv4"}
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'dnssd'
|
2
|
+
|
3
|
+
module Openplay
|
4
|
+
class Server
|
5
|
+
attr_reader :port
|
6
|
+
|
7
|
+
def initialize(port=5003)
|
8
|
+
@port = port
|
9
|
+
announce_availability
|
10
|
+
end
|
11
|
+
|
12
|
+
def receive
|
13
|
+
`cvlc udp://@:#{port} --network-caching=250`
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def announce_availability
|
18
|
+
DNSSD.register `hostname`.chomp, "_openplay._tcp", nil, port
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: openplay
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Josh Adams
|
9
|
+
- Adam Gamble
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2013-01-09 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: dnssd
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '2.0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ~>
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '2.0'
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: findme
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ! '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
type: :runtime
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: thor
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: minitest
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
type: :development
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
- !ruby/object:Gem::Dependency
|
80
|
+
name: minitest-matchers
|
81
|
+
requirement: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
type: :development
|
88
|
+
prerelease: false
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ! '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: turn
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ! '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
none: false
|
107
|
+
requirements:
|
108
|
+
- - ! '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: pry
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
115
|
+
requirements:
|
116
|
+
- - ! '>='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
none: false
|
123
|
+
requirements:
|
124
|
+
- - ! '>='
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
- !ruby/object:Gem::Dependency
|
128
|
+
name: mocha
|
129
|
+
requirement: !ruby/object:Gem::Requirement
|
130
|
+
none: false
|
131
|
+
requirements:
|
132
|
+
- - ! '>='
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '0'
|
135
|
+
type: :development
|
136
|
+
prerelease: false
|
137
|
+
version_requirements: !ruby/object:Gem::Requirement
|
138
|
+
none: false
|
139
|
+
requirements:
|
140
|
+
- - ! '>='
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
description: Open source air play
|
144
|
+
email:
|
145
|
+
- josh@isotope11.com
|
146
|
+
- agamble@isotope11.com
|
147
|
+
executables:
|
148
|
+
- openplay
|
149
|
+
extensions: []
|
150
|
+
extra_rdoc_files: []
|
151
|
+
files:
|
152
|
+
- bin/openplay
|
153
|
+
- lib/openplay.rb
|
154
|
+
- lib/openplay/server.rb
|
155
|
+
- lib/openplay/client.rb
|
156
|
+
- lib/openplay/determines_resolution.rb
|
157
|
+
- lib/openplay/discovers_servers.rb
|
158
|
+
- README.md
|
159
|
+
homepage: http://www.isotope11.com
|
160
|
+
licenses: []
|
161
|
+
post_install_message:
|
162
|
+
rdoc_options: []
|
163
|
+
require_paths:
|
164
|
+
- lib
|
165
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
166
|
+
none: false
|
167
|
+
requirements:
|
168
|
+
- - ! '>='
|
169
|
+
- !ruby/object:Gem::Version
|
170
|
+
version: '0'
|
171
|
+
segments:
|
172
|
+
- 0
|
173
|
+
hash: 56586988126532875
|
174
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
175
|
+
none: false
|
176
|
+
requirements:
|
177
|
+
- - ! '>='
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
version: '0'
|
180
|
+
segments:
|
181
|
+
- 0
|
182
|
+
hash: 56586988126532875
|
183
|
+
requirements: []
|
184
|
+
rubyforge_project:
|
185
|
+
rubygems_version: 1.8.24
|
186
|
+
signing_key:
|
187
|
+
specification_version: 3
|
188
|
+
summary: Open source air play
|
189
|
+
test_files: []
|