apple-tv-converter 0.0.1
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/CHANGELOG +3 -0
- data/LICENSE +20 -0
- data/README.md +16 -0
- data/lib/apple_tv_converter.rb +72 -0
- data/lib/apple_tv_converter/io_patch.rb +59 -0
- data/lib/apple_tv_converter/media.rb +58 -0
- data/lib/apple_tv_converter/media_converter.rb +49 -0
- data/lib/apple_tv_converter/media_converter_adapter.rb +87 -0
- data/lib/apple_tv_converter/media_converter_mac_adapter.rb +87 -0
- data/lib/apple_tv_converter/media_converter_windows_adapter.rb +43 -0
- data/lib/apple_tv_converter/version.rb +3 -0
- metadata +137 -0
data/CHANGELOG
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2012 Pedro Rodrigues
|
|
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
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
apple-tv-converter
|
|
2
|
+
=================
|
|
3
|
+
|
|
4
|
+
Media converter for AppleTV.
|
|
5
|
+
|
|
6
|
+
## On Mac OSX
|
|
7
|
+
|
|
8
|
+
- Uses ffmpeg for encoding (http://ffmpeg.org)
|
|
9
|
+
- Uses Subler for adding the subtitles and setting the iTunes metadata tags (http://code.google.com/p/subler/)
|
|
10
|
+
- Uses MKVToolNix for extracting the embedded subtitles from MKV files (http://www.bunkus.org/videotools/mkvtoolnix/)
|
|
11
|
+
|
|
12
|
+
# TODO
|
|
13
|
+
|
|
14
|
+
- Windows implementation
|
|
15
|
+
- Tests!
|
|
16
|
+
- Create a Mac OSX executable for running the script
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)
|
|
2
|
+
|
|
3
|
+
require 'logger'
|
|
4
|
+
require 'stringio'
|
|
5
|
+
require 'shellwords'
|
|
6
|
+
require 'open3'
|
|
7
|
+
require 'streamio-ffmpeg'
|
|
8
|
+
require 'mkv'
|
|
9
|
+
require 'awesome_print'
|
|
10
|
+
require 'fileutils'
|
|
11
|
+
require 'language_list'
|
|
12
|
+
|
|
13
|
+
require 'apple_tv_converter/version'
|
|
14
|
+
require 'apple_tv_converter/io_patch'
|
|
15
|
+
require 'apple_tv_converter/media_converter'
|
|
16
|
+
require 'apple_tv_converter/media'
|
|
17
|
+
require 'apple_tv_converter/media_converter_adapter'
|
|
18
|
+
require 'apple_tv_converter/media_converter_windows_adapter' if RUBY_PLATFORM =~ /(win|w)(32|64)$/
|
|
19
|
+
require 'apple_tv_converter/media_converter_mac_adapter' if RUBY_PLATFORM =~ /(darwin)/
|
|
20
|
+
|
|
21
|
+
module AppleTvConverter
|
|
22
|
+
# AppleTvConverter logs information about its progress when it's transcoding.
|
|
23
|
+
# Jack in your own logger through this method if you wish to.
|
|
24
|
+
#
|
|
25
|
+
# @param [Logger] log your own logger
|
|
26
|
+
# @return [Logger] the logger you set
|
|
27
|
+
def self.logger=(log)
|
|
28
|
+
@logger = log
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Get AppleTvConverter logger.
|
|
32
|
+
#
|
|
33
|
+
# @return [Logger]
|
|
34
|
+
def self.logger
|
|
35
|
+
return @logger if @logger
|
|
36
|
+
logger = Logger.new(STDOUT)
|
|
37
|
+
logger.level = Logger::INFO
|
|
38
|
+
@logger = logger
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Set the path of the mp4box binary.
|
|
42
|
+
# Can be useful if you need to specify a path such as /usr/local/bin/mp4box
|
|
43
|
+
#
|
|
44
|
+
# @param [String] path to the mp4box binary
|
|
45
|
+
# @return [String] the path you set
|
|
46
|
+
def self.mp4box_binary=(bin)
|
|
47
|
+
@mp4box_binary = bin
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Get the path to the mp4box binary, defaulting to 'MP4Box'
|
|
51
|
+
#
|
|
52
|
+
# @return [String] the path to the mp4box binary
|
|
53
|
+
def self.mp4box_binary
|
|
54
|
+
@mp4box_binary.nil? ? 'MP4Box' : @mp4box_binary
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Set the path of the atomic parsley binary.
|
|
58
|
+
# Can be useful if you need to specify a path such as /usr/local/bin/atomic_parsley
|
|
59
|
+
#
|
|
60
|
+
# @param [String] path to the atomic parsley binary
|
|
61
|
+
# @return [String] the path you set
|
|
62
|
+
def self.atomic_parsley_binary=(bin)
|
|
63
|
+
@atomic_parsley_binary = bin
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Get the path to the atomic_parsley binary, defaulting to 'AtomicParsley'
|
|
67
|
+
#
|
|
68
|
+
# @return [String] the path to the atomic_parsley binary
|
|
69
|
+
def self.atomic_parsley_binary
|
|
70
|
+
@atomic_parsley_binary.nil? ? 'AtomicParsley' : @atomic_parsley_binary
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
if RUBY_VERSION =~ /1\.8/
|
|
2
|
+
# Useful when `timeout.rb`, which, on M.R.I 1.8, relies on green threads, does not work consistently.
|
|
3
|
+
begin
|
|
4
|
+
require 'system_timer'
|
|
5
|
+
AppleTvConverter::Timer = SystemTimer
|
|
6
|
+
rescue LoadError
|
|
7
|
+
require 'timeout'
|
|
8
|
+
AppleTvConverter::Timer = Timeout
|
|
9
|
+
end
|
|
10
|
+
else
|
|
11
|
+
require 'timeout'
|
|
12
|
+
AppleTvConverter::Timer = Timeout
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
require 'win32/process' if RUBY_PLATFORM =~ /(win|w)(32|64)$/
|
|
16
|
+
|
|
17
|
+
#
|
|
18
|
+
# Monkey Patch timeout support into the IO class
|
|
19
|
+
#
|
|
20
|
+
class IO
|
|
21
|
+
def each_with_timeout(pid, seconds, sep_string=$/)
|
|
22
|
+
sleeping_queue = Queue.new
|
|
23
|
+
thread = nil
|
|
24
|
+
|
|
25
|
+
timer_set = lambda do
|
|
26
|
+
thread = new_thread(pid) { AppleTvConverter::Timer.timeout(seconds) { sleeping_queue.pop } }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
timer_cancel = lambda do
|
|
30
|
+
thread.kill if thread rescue nil
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
timer_set.call
|
|
34
|
+
each(sep_string) do |buffer|
|
|
35
|
+
timer_cancel.call
|
|
36
|
+
yield buffer
|
|
37
|
+
timer_set.call
|
|
38
|
+
end
|
|
39
|
+
ensure
|
|
40
|
+
timer_cancel.call
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
def new_thread(pid, &block)
|
|
45
|
+
current_thread = Thread.current
|
|
46
|
+
Thread.new do
|
|
47
|
+
begin
|
|
48
|
+
block.call
|
|
49
|
+
rescue Exception => e
|
|
50
|
+
current_thread.raise e
|
|
51
|
+
if RUBY_PLATFORM =~ /(win|w)(32|64)$/
|
|
52
|
+
Process.kill(1, pid)
|
|
53
|
+
else
|
|
54
|
+
Process.kill('SIGKILL', pid)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
module AppleTvConverter
|
|
2
|
+
class Media
|
|
3
|
+
attr_accessor :show, :season, :number, :genre
|
|
4
|
+
attr_reader :original_filename, :quality
|
|
5
|
+
|
|
6
|
+
def original_filename=(value)
|
|
7
|
+
@original_filename = value
|
|
8
|
+
|
|
9
|
+
if @original_filename =~ /.*?\.m4v$/
|
|
10
|
+
if File.exists?(@original_filename.gsub(/\.m4v/, '.avi'))
|
|
11
|
+
@original_filename = @original_filename.gsub(/\.m4v/, '.avi')
|
|
12
|
+
elsif File.exists?(@original_filename.gsub(/\.m4v/, '.mkv'))
|
|
13
|
+
@original_filename = @original_filename.gsub(/\.m4v/, '.mkv')
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def subtitle_filename
|
|
19
|
+
@subtitle_filename ||= self.original_filename.gsub(/\.(mkv|avi|mp4)/, '.srt')
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def converted_filename
|
|
23
|
+
@converted_filename ||= self.original_filename.gsub(/\.(mkv|avi)/, '.m4v')
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def converted_filename_with_subtitles
|
|
27
|
+
@converted_filename_with_subtitles ||= self.original_filename.gsub(/\.(mkv|avi|mp4)/, '_subtitled.m4v')
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def ffmpeg_data
|
|
31
|
+
@ffmpeg_data ||= FFMPEG::Movie.new(original_filename)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def mkv_data
|
|
35
|
+
@mkv_data ||= MKV::Movie.new(original_filename)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def is_tv_show_episode?
|
|
39
|
+
!season.nil? && !number.nil?
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def is_movie?
|
|
43
|
+
!is_tv_show_episode?
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def is_mkv?
|
|
47
|
+
ffmpeg_data.container =~ /matroska/i rescue File.extname(original_filename).downcase == '.mkv'
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def is_mp4?
|
|
51
|
+
ffmpeg_data.container =~ /mp4/ rescue File.extname(original_filename) =~ /\.(mp4|m4v)$/
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def is_valid?
|
|
55
|
+
ffmpeg_data.valid?
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module AppleTvConverter
|
|
2
|
+
class MediaConverter
|
|
3
|
+
@@timeout = 200
|
|
4
|
+
|
|
5
|
+
def is_windows? ; RUBY_PLATFORM =~/.*?mingw.*?/i ; end
|
|
6
|
+
def is_macosx? ; RUBY_PLATFORM =~/.*?darwin.*?/i ; end
|
|
7
|
+
|
|
8
|
+
def initialize
|
|
9
|
+
@adapter = is_windows? ? AppleTvConverter::MediaConverterWindowsAdapter.new : AppleTvConverter::MediaConverterMacAdapter.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def process_media(media)
|
|
13
|
+
AppleTvConverter.logger.debug "**** #{File.basename(media.original_filename)}"
|
|
14
|
+
AppleTvConverter.logger.debug "* Video codec: #{media.ffmpeg_data.video_codec}"
|
|
15
|
+
AppleTvConverter.logger.debug "* Audio codec: #{media.ffmpeg_data.audio_codec}"
|
|
16
|
+
AppleTvConverter.logger.debug "* Container: #{media.ffmpeg_data.container}" rescue nil
|
|
17
|
+
|
|
18
|
+
extract_subtitles(media) if media.is_mkv?
|
|
19
|
+
|
|
20
|
+
if @adapter.transcode(media)
|
|
21
|
+
@adapter.add_subtitles media
|
|
22
|
+
@adapter.tag media
|
|
23
|
+
|
|
24
|
+
# add_to_itunes media
|
|
25
|
+
@adapter.clean_up media
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
# HELPERS
|
|
32
|
+
def process_all_medias(medias)
|
|
33
|
+
medias.each_with_index do |media, index|
|
|
34
|
+
puts '*' * 80
|
|
35
|
+
puts "* [#{(index + 1).to_s.rjust(medias.length.to_s.length, ' ')}/#{medias.length}] #{File.basename(media.original_filename)}"
|
|
36
|
+
|
|
37
|
+
process_media media
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def process_file(file)
|
|
42
|
+
puts '*' * 80
|
|
43
|
+
puts "* #{file}"
|
|
44
|
+
|
|
45
|
+
media = parse_filename(file)
|
|
46
|
+
process_media media
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
module AppleTvConverter
|
|
2
|
+
class MediaConverterAdapter
|
|
3
|
+
def extract_subtitles(media)
|
|
4
|
+
printf "*** Extracting subtitles"
|
|
5
|
+
media.mkv_data.extract_subtitles(File.dirname(media.original_filename)) do |progress|
|
|
6
|
+
printf "\r* Progress: #{progress}%%"
|
|
7
|
+
end
|
|
8
|
+
puts "\r* Progress: [DONE]"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def transcode(media)
|
|
12
|
+
if convert?(media)
|
|
13
|
+
puts "*** Encoding"
|
|
14
|
+
|
|
15
|
+
options = {
|
|
16
|
+
:video_codec => convert_video?(media) ? 'mpeg4' : 'copy',
|
|
17
|
+
:audio_codec => convert_audio?(media) ? 'libfaac' : 'copy'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
options[:custom] = "-qscale 1" if convert_video?(media)
|
|
21
|
+
|
|
22
|
+
transcoded = media.ffmpeg_data.transcode(media.converted_filename, options) do |progress|
|
|
23
|
+
printf %Q[\r* Progress: #{(progress * 100).round(2)}%%]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
status transcoded.valid?
|
|
27
|
+
|
|
28
|
+
if status
|
|
29
|
+
puts "\r* Encoding: [DONE]#{' ' * 20}"
|
|
30
|
+
else
|
|
31
|
+
puts "\r* Encoding: [ERROR]#{' ' * 20}"
|
|
32
|
+
end
|
|
33
|
+
else
|
|
34
|
+
puts "*** Encoding: [UNNECESSARY]"
|
|
35
|
+
status = true
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
return status
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def add_subtitles(media)
|
|
42
|
+
raise NotImplementedYetException
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def tag(media)
|
|
46
|
+
raise NotImplementedYetException
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def add_to_itunes(media)
|
|
50
|
+
raise NotImplementedYetException
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def clean_up(media)
|
|
54
|
+
printf "*** Cleaning up"
|
|
55
|
+
begin
|
|
56
|
+
FileUtils.rm(media.original_filename) unless media.original_filename == media.converted_filename
|
|
57
|
+
FileUtils.rm_r list_files(File.join(File.dirname(media.original_filename), '*.srt'))
|
|
58
|
+
puts " [DONE]"
|
|
59
|
+
rescue
|
|
60
|
+
puts " [ERROR]"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
protected
|
|
65
|
+
|
|
66
|
+
def list_files(ls)
|
|
67
|
+
raise NotImplementedYetException
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def convert_audio?(media)
|
|
71
|
+
return media.ffmpeg_data.audio_codec !~ /(?:ac3|aac)/i
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def convert_video?(media)
|
|
75
|
+
return media.ffmpeg_data.video_codec !~ /.*(?:mpeg4).*/i
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def convert?(media)
|
|
79
|
+
!(media.is_valid? && media.is_mp4?)# && !convert_video?(media) && !convert_audio?(media))
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def has_subtitles?(media)
|
|
83
|
+
list_files(File.join(File.dirname(media.original_filename), '*.srt')).any?
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
module AppleTvConverter
|
|
2
|
+
class MediaConverterMacAdapter < MediaConverterAdapter
|
|
3
|
+
def add_subtitles(media)
|
|
4
|
+
puts "*** Adding subtitles"
|
|
5
|
+
|
|
6
|
+
printf "* Removing any previous subtitles"
|
|
7
|
+
|
|
8
|
+
command_line = %Q[./SublerCLI -remove -dest "#{media.converted_filename}"]
|
|
9
|
+
|
|
10
|
+
AppleTvConverter.logger.debug "Executing:"
|
|
11
|
+
AppleTvConverter.logger.debug command_line
|
|
12
|
+
|
|
13
|
+
output = Open3.popen3(command_line) { |stdin, stdout, stderr, wait_thr| stdout.read }
|
|
14
|
+
|
|
15
|
+
puts output.strip.empty? ? " [DONE]" : (output.strip == 'Error: (null)' ? " [NONE FOUND]" : " [ERROR]")
|
|
16
|
+
|
|
17
|
+
if has_subtitles?(media)
|
|
18
|
+
list_files(File.join(File.dirname(media.original_filename), '*.srt')).map do |subtitle_filename|
|
|
19
|
+
subtitle_filename =~ /(\w{3})\.srt$/
|
|
20
|
+
language_code = $1 || 'eng'
|
|
21
|
+
|
|
22
|
+
language = ::LanguageList::LanguageInfo.find_by_iso_639_3(language_code)
|
|
23
|
+
language ||= ::LanguageList::LanguageInfo.find_by_iso_639_3('eng')
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
command_line = "./SublerCLI "
|
|
27
|
+
command_line << %Q[-source "#{subtitle_filename}" ]
|
|
28
|
+
command_line << %Q[-language "#{language.name}" ]
|
|
29
|
+
command_line << %Q[-dest "#{media.converted_filename}"]
|
|
30
|
+
|
|
31
|
+
AppleTvConverter.logger.debug "Executing:"
|
|
32
|
+
AppleTvConverter.logger.debug command_line
|
|
33
|
+
|
|
34
|
+
printf "* Adding #{language.name} subtitles"
|
|
35
|
+
output = Open3.popen3(command_line) { |stdin, stdout, stderr, wait_thr| stdout.read }
|
|
36
|
+
|
|
37
|
+
puts output.strip.empty? ? " [DONE]" : " [ERROR]"
|
|
38
|
+
end
|
|
39
|
+
else
|
|
40
|
+
puts "* No new subtitles found"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def tag(media)
|
|
45
|
+
metadata = ''
|
|
46
|
+
metadata << %Q[{Name: #{media.show} S#{media.season.to_s.rjust(2, '0')}E#{media.number.to_s.rjust(2, '0')}}] if media.is_tv_show_episode?
|
|
47
|
+
metadata << %Q[{Name: #{media.show}}] if media.is_movie?
|
|
48
|
+
metadata << %Q[{Genre: #{media.show}}{TV Show: #{media.show}}{TV Season: #{media.season}}{TV Episode #: #{media.number}}] if media.is_tv_show_episode?
|
|
49
|
+
metadata << %Q[{Genre: #{media.quality} Movie}] if media.is_movie?
|
|
50
|
+
|
|
51
|
+
command_line = %Q[./SublerCLI -metadata "#{metadata}" -dest "#{media.converted_filename}"]
|
|
52
|
+
|
|
53
|
+
AppleTvConverter.logger.debug "Executing:"
|
|
54
|
+
AppleTvConverter.logger.debug command_line
|
|
55
|
+
|
|
56
|
+
printf "*** Tagging"
|
|
57
|
+
|
|
58
|
+
output = Open3.popen3(command_line) { |stdin, stdout, stderr, wait_thr| stdout.read }
|
|
59
|
+
|
|
60
|
+
puts output.strip.empty? ? " [DONE]" : " [ERROR]"
|
|
61
|
+
|
|
62
|
+
return output.strip.empty?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def add_to_itunes(media)
|
|
66
|
+
printf "*** Adding to iTunes"
|
|
67
|
+
|
|
68
|
+
command_line = [
|
|
69
|
+
"ln -s",
|
|
70
|
+
"#{media.converted_filename}".gsub(/\s/, '\ ').gsub(/\[/, '\[').gsub(/\]/, '\]'),
|
|
71
|
+
"#{File.expand_path(File.join('~', 'Music', 'iTunes', 'iTunes Media', 'Automatically Add to iTunes.localized'))}".gsub(/\s/, '\ ').gsub(/\[/, '\[').gsub(/\]/, '\]')
|
|
72
|
+
].join(' ')
|
|
73
|
+
|
|
74
|
+
AppleTvConverter.logger.debug "Executing:"
|
|
75
|
+
AppleTvConverter.logger.debug command_line
|
|
76
|
+
|
|
77
|
+
`#{command_line}`
|
|
78
|
+
|
|
79
|
+
puts ' [DONE]'
|
|
80
|
+
return true
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def list_files(ls)
|
|
84
|
+
`ls -1 #{ls.gsub(/\s/, '\ ').gsub(/\[/, '\[').gsub(/\]/, '\]')} 2>/dev/null`.split("\n")
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module AppleTvConverter
|
|
2
|
+
class MediaConverterWindowsAdapter < MediaConverterAdapter
|
|
3
|
+
require 'win32ole'
|
|
4
|
+
|
|
5
|
+
def handbrake_location
|
|
6
|
+
return File.expand_path("./HandBrakeCLI#{'_x64' if is_windows_64bit?}.exe")
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def atomic_parsley_location
|
|
10
|
+
return File.expand_path('./AtomicParsley.exe')
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def clean_up_command_line(command_line)
|
|
14
|
+
return command_line.gsub(/\//, '\\')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def add_to_itunes(episode)
|
|
18
|
+
printf "* Adding to iTunes"
|
|
19
|
+
@itunes ||= WIN32OLE.new("iTunes.Application")
|
|
20
|
+
@itunes.PlayFile(episode.converted_filename)
|
|
21
|
+
@itunes.Stop
|
|
22
|
+
|
|
23
|
+
puts " [DONE]"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def line_ending
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def execute_command(command_line, &block)
|
|
30
|
+
`#{command_line}`
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def is_windows_32bit?
|
|
36
|
+
!is_windows_64bit?
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def is_windows_64bit?
|
|
40
|
+
ENV.has_key?('ProgramFiles(x86)')
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: apple-tv-converter
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Pedro Rodrigues
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2012-11-15 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: rspec
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
none: false
|
|
18
|
+
requirements:
|
|
19
|
+
- - ~>
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '2.7'
|
|
22
|
+
type: :development
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ~>
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '2.7'
|
|
30
|
+
- !ruby/object:Gem::Dependency
|
|
31
|
+
name: rake
|
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
|
33
|
+
none: false
|
|
34
|
+
requirements:
|
|
35
|
+
- - ~>
|
|
36
|
+
- !ruby/object:Gem::Version
|
|
37
|
+
version: 0.9.2
|
|
38
|
+
type: :development
|
|
39
|
+
prerelease: false
|
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
41
|
+
none: false
|
|
42
|
+
requirements:
|
|
43
|
+
- - ~>
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: 0.9.2
|
|
46
|
+
- !ruby/object:Gem::Dependency
|
|
47
|
+
name: mkv
|
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
|
49
|
+
none: false
|
|
50
|
+
requirements:
|
|
51
|
+
- - ~>
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: 0.0.1
|
|
54
|
+
type: :runtime
|
|
55
|
+
prerelease: false
|
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
57
|
+
none: false
|
|
58
|
+
requirements:
|
|
59
|
+
- - ~>
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 0.0.1
|
|
62
|
+
- !ruby/object:Gem::Dependency
|
|
63
|
+
name: streamio-ffmpeg
|
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
|
65
|
+
none: false
|
|
66
|
+
requirements:
|
|
67
|
+
- - ~>
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: 0.9.0
|
|
70
|
+
type: :runtime
|
|
71
|
+
prerelease: false
|
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
73
|
+
none: false
|
|
74
|
+
requirements:
|
|
75
|
+
- - ~>
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: 0.9.0
|
|
78
|
+
- !ruby/object:Gem::Dependency
|
|
79
|
+
name: language_list
|
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
|
81
|
+
none: false
|
|
82
|
+
requirements:
|
|
83
|
+
- - ~>
|
|
84
|
+
- !ruby/object:Gem::Version
|
|
85
|
+
version: 0.0.3
|
|
86
|
+
type: :runtime
|
|
87
|
+
prerelease: false
|
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
89
|
+
none: false
|
|
90
|
+
requirements:
|
|
91
|
+
- - ~>
|
|
92
|
+
- !ruby/object:Gem::Version
|
|
93
|
+
version: 0.0.3
|
|
94
|
+
description: Converts movies to a format playable on Apple TV. Supporting multiple
|
|
95
|
+
subtitles.
|
|
96
|
+
email:
|
|
97
|
+
- pedro@bbde.org
|
|
98
|
+
executables: []
|
|
99
|
+
extensions: []
|
|
100
|
+
extra_rdoc_files: []
|
|
101
|
+
files:
|
|
102
|
+
- lib/apple_tv_converter/io_patch.rb
|
|
103
|
+
- lib/apple_tv_converter/media.rb
|
|
104
|
+
- lib/apple_tv_converter/media_converter.rb
|
|
105
|
+
- lib/apple_tv_converter/media_converter_adapter.rb
|
|
106
|
+
- lib/apple_tv_converter/media_converter_mac_adapter.rb
|
|
107
|
+
- lib/apple_tv_converter/media_converter_windows_adapter.rb
|
|
108
|
+
- lib/apple_tv_converter/version.rb
|
|
109
|
+
- lib/apple_tv_converter.rb
|
|
110
|
+
- README.md
|
|
111
|
+
- LICENSE
|
|
112
|
+
- CHANGELOG
|
|
113
|
+
homepage: http://github.com/gokuu/apple-tv-converter
|
|
114
|
+
licenses: []
|
|
115
|
+
post_install_message:
|
|
116
|
+
rdoc_options: []
|
|
117
|
+
require_paths:
|
|
118
|
+
- lib
|
|
119
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
120
|
+
none: false
|
|
121
|
+
requirements:
|
|
122
|
+
- - ! '>='
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '0'
|
|
125
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
126
|
+
none: false
|
|
127
|
+
requirements:
|
|
128
|
+
- - ! '>='
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: '0'
|
|
131
|
+
requirements: []
|
|
132
|
+
rubyforge_project:
|
|
133
|
+
rubygems_version: 1.8.24
|
|
134
|
+
signing_key:
|
|
135
|
+
specification_version: 3
|
|
136
|
+
summary: Converts movies to a format playable on Apple TV.
|
|
137
|
+
test_files: []
|