tivohmo 0.3.1 → 0.3.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.
- checksums.yaml +4 -4
- data/.travis.yml +7 -1
- data/CHANGELOG +10 -0
- data/README.md +5 -0
- data/TODO +3 -1
- data/contrib/tivohmo.yml +6 -0
- data/lib/tivohmo/adapters/plex.rb +6 -0
- data/lib/tivohmo/adapters/streamio/transcoder.rb +1 -1
- data/lib/tivohmo/cli.rb +10 -0
- data/lib/tivohmo/server.rb +29 -21
- data/lib/tivohmo/subtitles_util.rb +1 -1
- data/lib/tivohmo/version.rb +1 -1
- data/spec/cli_spec.rb +12 -1
- data/spec/server_spec.rb +19 -11
- data/spec/subtitles_util_spec.rb +2 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47cfc66b304a9e2077e46e6aa926b28f71d06b61
|
4
|
+
data.tar.gz: f3472e5e06a6167f772c4f6f6f2b78051673b4cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 526a4da9add7732b54b4579a692e1af98bd3fb7b9d8c8651ac12a461deb52def24a4a71ff2228ca3aab22cf76803b1b3584179f69affc62b0f68744425d581ce
|
7
|
+
data.tar.gz: b8fc08f4828cf93c6021a17b143328c6f5c9cff63199cf24367d0df0a71aa5073dd8bb50e56bfb06542631e99bc35ae3bc93e86934b2f26f540b2e78aa62016b
|
data/.travis.yml
CHANGED
data/CHANGELOG
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
0.3.2 (01/03/2016)
|
2
|
+
------------------
|
3
|
+
|
4
|
+
1.9.3 not supported <a2bd4bc> [Matt Conway]
|
5
|
+
TiVo Series 3 support: <486fa2e> [Scott Bailey]
|
6
|
+
add cli for setting arbitrary config <6171acb> [Matt Conway]
|
7
|
+
allow setting plex auth token <abc307a> [Matt Conway]
|
8
|
+
fix back after watching movie (anchor) <2737823> [Matt Conway]
|
9
|
+
use debug for transcode progress <4aae8d1> [Matt Conway]
|
10
|
+
|
1
11
|
0.3.1 (03/08/2015)
|
2
12
|
------------------
|
3
13
|
|
data/README.md
CHANGED
@@ -25,6 +25,11 @@ This project only supports serving of video resources (for now) as that fills my
|
|
25
25
|
|
26
26
|
## Installation
|
27
27
|
|
28
|
+
Install ffmpeg 2.x:
|
29
|
+
|
30
|
+
# On Mac OS X, use homebrew: http://brew.sh/
|
31
|
+
brew install ffmpeg
|
32
|
+
|
28
33
|
Install the gem:
|
29
34
|
|
30
35
|
$ gem install tivohmo
|
data/TODO
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
-
fix back after watching movie (anchor)
|
2
1
|
add audio track support similar to embedded subtitles
|
3
2
|
add embedded subtitles to filesystem app
|
4
3
|
figure out how to stream/transcode from plex rather than hack to use local files
|
5
4
|
figure out a way to embed subtitles in mpeg2 stream for live toggling from tivo ui (EIA-608/CEA-708/line 21)
|
5
|
+
Add push capability
|
6
|
+
Add html rendering of heirarchy for browsing/pushing
|
7
|
+
Add a plex plugin that allows one to trigger a push from plex ui (e.g. mobile plex client)
|
data/contrib/tivohmo.yml
CHANGED
@@ -35,6 +35,12 @@ applications:
|
|
35
35
|
# application: TivoHMO::Adapters::Filesystem::Application
|
36
36
|
# identifier: /My/Video
|
37
37
|
|
38
|
+
# Adapter specific configuration
|
39
|
+
# adapters:
|
40
|
+
# plex:
|
41
|
+
# # Optional, only needs to be set when plex user profiles have access control
|
42
|
+
# # https://support.plex.tv/hc/en-us/articles/204059436-Finding-your-account-token-X-Plex-Token
|
43
|
+
# auth_token: 'YOUR_TOKEN'
|
38
44
|
|
39
45
|
# BEGIN RUNTIME EDITABLE SETTINGS
|
40
46
|
#
|
@@ -1,4 +1,10 @@
|
|
1
1
|
require 'plex-ruby'
|
2
|
+
Plex.configure do |config|
|
3
|
+
# TODO: figure out a way to make this instance specific rather than global for all plex apps
|
4
|
+
token = TivoHMO::Config.instance.get(["adapters", "plex", "auth_token"])
|
5
|
+
config.auth_token = token if token.present?
|
6
|
+
end
|
7
|
+
|
2
8
|
require_relative 'plex/movie'
|
3
9
|
require_relative 'plex/episode'
|
4
10
|
require_relative 'plex/group'
|
@@ -248,7 +248,7 @@ module TivoHMO
|
|
248
248
|
begin
|
249
249
|
logger.info "Starting transcode of '#{movie.path}' to '#{output_filename}'"
|
250
250
|
transcoded_movie = movie.transcode(output_filename, opts, t_opts) do |progress|
|
251
|
-
logger.
|
251
|
+
logger.debug ("[%3i%%] Transcoding #{File.basename(movie.path)}" % (progress * 100).to_i)
|
252
252
|
raise "Halted" if Thread.current[:halt]
|
253
253
|
end
|
254
254
|
logger.info "Transcoding completed, transcoded file size: #{File.size(output_filename)}"
|
data/lib/tivohmo/cli.rb
CHANGED
@@ -70,6 +70,10 @@ module TivoHMO
|
|
70
70
|
option ["-f", "--configuration"],
|
71
71
|
"FILE", "load configuration from given filename\n"
|
72
72
|
|
73
|
+
option ["-c", "--configitem"],
|
74
|
+
"ITEM", "set configuration from given key=value item\n",
|
75
|
+
multivalued: true
|
76
|
+
|
73
77
|
option ["-s", "--settings"],
|
74
78
|
"FILE", "a writable file for storing runtime settings\n"
|
75
79
|
|
@@ -117,6 +121,12 @@ module TivoHMO
|
|
117
121
|
|
118
122
|
logger.info "TivoHMO #{TivoHMO::VERSION} starting up"
|
119
123
|
|
124
|
+
# set any config items passed in on cli
|
125
|
+
configitem_list.each do |item|
|
126
|
+
key, value = item.split('=')
|
127
|
+
Config.instance.set(key, value)
|
128
|
+
end
|
129
|
+
|
120
130
|
# allow cli option to override config file
|
121
131
|
set_if_default(:port, TivoHMO::Config.instance.get(:port).try(:to_i))
|
122
132
|
|
data/lib/tivohmo/server.rb
CHANGED
@@ -249,36 +249,41 @@ module TivoHMO
|
|
249
249
|
container = server.find(container_path)
|
250
250
|
halt 404, "No container found for #{container_path}" unless container
|
251
251
|
|
252
|
+
if anchor_item
|
253
|
+
anchor = server.find(anchor_item)
|
254
|
+
if anchor
|
255
|
+
container = anchor.parent
|
256
|
+
else
|
257
|
+
logger.warn "Anchor not found: #{anchor_item}"
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
252
261
|
children = container.children
|
253
262
|
|
254
263
|
children = select_all_items(children) if recurse
|
255
264
|
|
256
265
|
children = sort(children, sort_order) if sort_order && ! container.presorted
|
257
266
|
|
258
|
-
if
|
259
|
-
|
260
|
-
if
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
locals[:item_start] = item_start
|
269
|
-
else
|
270
|
-
logger.warn "Anchor not in container: #{container}, #{anchor_item}"
|
271
|
-
end
|
267
|
+
if anchor
|
268
|
+
idx = children.index(anchor)
|
269
|
+
if idx
|
270
|
+
# negative anchor means start N items before the anchor
|
271
|
+
# positive means start N items after the anchor
|
272
|
+
# ItemStart should be the index of the anchor with offset applied
|
273
|
+
anchor_offset = anchor_offset + 1 if anchor_offset < 0
|
274
|
+
item_start = idx + anchor_offset
|
275
|
+
item_start = 0 if item_start < 0
|
276
|
+
locals[:item_start] = item_start
|
272
277
|
else
|
273
|
-
logger.warn "Anchor not
|
274
|
-
end
|
275
|
-
else
|
276
|
-
if item_count < 0
|
277
|
-
locals[:item_start] = children.size + item_count
|
278
|
-
locals[:item_count] = - item_count
|
278
|
+
logger.warn "Anchor not in container: #{container}, #{anchor_item}"
|
279
279
|
end
|
280
280
|
end
|
281
281
|
|
282
|
+
if item_count < 0
|
283
|
+
locals[:item_start] = children.size + item_count
|
284
|
+
locals[:item_count] = - item_count
|
285
|
+
end
|
286
|
+
|
282
287
|
if container.root?
|
283
288
|
builder :server, layout: true,
|
284
289
|
locals: locals.merge(container: container, children: children)
|
@@ -313,7 +318,9 @@ module TivoHMO
|
|
313
318
|
builder :server_info, layout: true
|
314
319
|
|
315
320
|
when 'QueryItem' then
|
316
|
-
|
321
|
+
# pyTivo returns 404 when we try this (and doesn't crash the TiVo)
|
322
|
+
# builder(layout: true) {|xml| xml.QueryItem }
|
323
|
+
unsupported
|
317
324
|
|
318
325
|
when 'FlushServer' then
|
319
326
|
builder(layout: true) {|xml| xml.FlushServer }
|
@@ -337,6 +344,7 @@ module TivoHMO
|
|
337
344
|
response["Content-Type"] = format
|
338
345
|
|
339
346
|
stream do |out|
|
347
|
+
# Pulling h.264 ts fails if we include tivo_header, so it seems header is only needed for mpeg2 ts
|
340
348
|
out << tivo_header(item, format)
|
341
349
|
item.transcoder.transcode(out, format)
|
342
350
|
end
|
@@ -79,7 +79,7 @@ module TivoHMO
|
|
79
79
|
logger.debug "Setting up change listener on #{dir}"
|
80
80
|
|
81
81
|
listener = Listen.to(dir) do |modified, added, removed|
|
82
|
-
logger.debug "Detected filesystem change on #{dir}"
|
82
|
+
logger.debug "Detected filesystem change (#{added.size}/#{removed.size}) on #{dir}"
|
83
83
|
|
84
84
|
dirs = (added + removed).flatten.collect do |path|
|
85
85
|
logger.debug "Inspecting filesystem change: #{path}"
|
data/lib/tivohmo/version.rb
CHANGED
data/spec/cli_spec.rb
CHANGED
@@ -163,6 +163,17 @@ describe TivoHMO::CLI do
|
|
163
163
|
|
164
164
|
end
|
165
165
|
|
166
|
+
describe "--configitem" do
|
167
|
+
|
168
|
+
it "sets a config item" do
|
169
|
+
expect(TivoHMO::Server).to receive(:start)
|
170
|
+
cli.run(argv(minimal_args.merge(configitem: "adapters.plex.auth_token=abc123")))
|
171
|
+
expect(TivoHMO::Config.instance.get("adapters.plex.auth_token")).to eq('abc123')
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
|
166
177
|
describe "--port" do
|
167
178
|
|
168
179
|
it "has a default port" do
|
@@ -180,7 +191,7 @@ describe TivoHMO::CLI do
|
|
180
191
|
describe "--beacon" do
|
181
192
|
|
182
193
|
it "works with defaults" do
|
183
|
-
expect(TivoHMO::Beacon).to receive(:new).with(9032,
|
194
|
+
expect(TivoHMO::Beacon).to receive(:new).with(9032, {})
|
184
195
|
cli.run(argv(minimal_args))
|
185
196
|
end
|
186
197
|
|
data/spec/server_spec.rb
CHANGED
@@ -162,7 +162,8 @@ describe TivoHMO::Server do
|
|
162
162
|
|
163
163
|
it "should have a stub response for QueryItem" do
|
164
164
|
get '/TiVoConnect?Command=QueryItem'
|
165
|
-
|
165
|
+
# but make this 404 (like pyTivo) instead of 200
|
166
|
+
expect(last_response.status).to eq(404)
|
166
167
|
end
|
167
168
|
|
168
169
|
it "should have a response for QueryServer" do
|
@@ -516,17 +517,24 @@ describe TivoHMO::Server do
|
|
516
517
|
child_titles = doc.xpath("/TiVoContainer/Item/Details/Title").collect(&:content)
|
517
518
|
expect(child_titles).to match_array(["i1", "i2", "i3", "i4", "i5", "i6", "i7", "i8"])
|
518
519
|
end
|
519
|
-
|
520
|
-
# [2014-12-07 21:23:00] INFO TivoHMO::Server Request from 192.168.1.12 "GET http:
|
521
|
-
# //192.168.1.188:9033/TiVoConnect?Command=QueryContainer&Container=%2FMatts%20Lap
|
522
|
-
# top%20(Plex)&Recurse=Yes&SortOrder=Title&ItemCount=8&AnchorItem=%2FMatts%20Lapto
|
523
|
-
# p%20(Plex)%2FAdult%20TV%20Shows%2FAll%2FMarvel's%20Agents%20of%20S.H.I.E.L.D.%2F
|
524
|
-
# Season%201%2FEye%20Spy&AnchorOffset=-5&Filter=x-tivo-container%2Ftivo-videos,x-t
|
525
|
-
# ivo-container%2Ffolder,video%2Fx-tivo-mpeg,video%2F*&SerialNum=848000190292CC9"
|
526
|
-
# [2014-12-07 21:23:00] DEBUG TivoHMO::Server Headers: {"Content-Type"=>nil}
|
527
|
-
# [2014-12-07 21:23:00] WARN TivoHMO::Server Anchor not in container: <TivoHMO::Adapters::Plex::Application: Plex[localhost:32400]>, /Matts Laptop (Plex)/Adult TV Shows/All/Marvel's Agents of S.H.I.E.L.D./Season 1/Eye Spy
|
528
|
-
# [2014-12-07 21:23:00] INFO TivoHMO::Server Response to 192.168.1.12 for "GET http://192.168.1.188:9033/TiVoConnect?Command=QueryContainer&Container=%2FMatts%20Laptop%20(Plex)&Recurse=Yes&SortOrder=Title&ItemCount=8&AnchorItem=%2FMatts%20Laptop%20(Plex)%2FAdult%20TV%20Shows%2FAll%2FMarvel's%20Agents%20of%20S.H.I.E.L.D.%2FSeason%201%2FEye%20Spy&AnchorOffset=-5&Filter=x-tivo-container%2Ftivo-videos,x-tivo-container%2Ffolder,video%2Fx-tivo-mpeg,video%2F*&SerialNum=848000190292CC9" [200]
|
529
520
|
|
521
|
+
it "overrides container with the one from anchor" do
|
522
|
+
get "/TiVoConnect?Command=QueryContainer&Container=/a1&AnchorItem=/a1/c1/i8&AnchorOffset=-1"
|
523
|
+
expect(last_response.status).to eq(200)
|
524
|
+
doc = Nokogiri::XML(last_response.body)
|
525
|
+
|
526
|
+
expect(doc.at_xpath("/TiVoContainer/Details/Title").content).to eq("/a1/c1")
|
527
|
+
|
528
|
+
expect(doc.at_xpath("/TiVoContainer/ItemStart").content).to eq("7")
|
529
|
+
expect(doc.at_xpath("/TiVoContainer/ItemCount").content).to eq("8")
|
530
|
+
|
531
|
+
expect(doc.at_xpath("/TiVoContainer/Details/TotalItems").content).to eq("20")
|
532
|
+
|
533
|
+
expect(doc.xpath("/TiVoContainer/Item").size).to eq (8)
|
534
|
+
|
535
|
+
child_titles = doc.xpath("/TiVoContainer/Item/Details/Title").collect(&:content)
|
536
|
+
expect(child_titles).to match_array(["i8", "i9", "i10", "i11", "i12", "i13", "i14", "i15"])
|
537
|
+
end
|
530
538
|
|
531
539
|
end
|
532
540
|
|
data/spec/subtitles_util_spec.rb
CHANGED
@@ -41,6 +41,7 @@ describe TivoHMO::SubtitlesUtil do
|
|
41
41
|
subs = subject.subtitles_for_media_file("#{dir}/1.avi")
|
42
42
|
expect(subs.size).to eq(0)
|
43
43
|
|
44
|
+
sleep 0.1
|
44
45
|
FileUtils.touch("#{dir}/1.en.srt")
|
45
46
|
sleep 0.5
|
46
47
|
|
@@ -55,6 +56,7 @@ describe TivoHMO::SubtitlesUtil do
|
|
55
56
|
subs = subject.subtitles_for_media_file("#{dir}/1.avi")
|
56
57
|
expect(subs.size).to eq(1)
|
57
58
|
|
59
|
+
sleep 0.1
|
58
60
|
FileUtils.rm("#{dir}/1.en.srt")
|
59
61
|
sleep 0.5
|
60
62
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tivohmo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Conway
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -525,7 +525,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
525
525
|
version: '0'
|
526
526
|
requirements: []
|
527
527
|
rubyforge_project:
|
528
|
-
rubygems_version: 2.
|
528
|
+
rubygems_version: 2.5.1
|
529
529
|
signing_key:
|
530
530
|
specification_version: 4
|
531
531
|
summary: Ruby SDK for Tivo Home Media Option
|