rubyVDRconvert 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # TODO: Lower my own process priority to idle class
4
+ # TODO: Write the daemon
data/lib/file_dir.rb ADDED
@@ -0,0 +1,31 @@
1
+ require 'find'
2
+
3
+ class FileDir
4
+ def self.delete!(filedir)
5
+ case Dir.exist?(filedir)
6
+ when true
7
+ begin
8
+ Dir.rmdir(filedir)
9
+ rescue
10
+ Dir.foreach(filedir) { | entry |
11
+ delete!(entry) unless (entry == ".") or (entry == "..")
12
+ }
13
+ retry
14
+ end
15
+ else
16
+ File.delete(filedir)
17
+ end
18
+ end
19
+ def self.mkdirtree(directory)
20
+ begin
21
+ Dir.mkdir(directory)
22
+ rescue SystemCallError => ex
23
+ parent = File.dirname(directory)
24
+ # Prevent an endless loop
25
+ return true if Dir.exist?(directory)
26
+ raise ex if parent.length == '/'
27
+ self.mkdirtree(parent)
28
+ retry
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,8 @@
1
+ class Processing_thread
2
+ def start
3
+ # TODO: Run the processing thread
4
+ end
5
+ def stop
6
+ # TODO: Stop the processing thread
7
+ end
8
+ end
data/lib/recording.rb ADDED
@@ -0,0 +1,76 @@
1
+ require 'rubygems'
2
+
3
+ require 'recording_ts'
4
+ require 'recording_vdr'
5
+ require 'file_dir'
6
+
7
+ class Recording
8
+ attr_reader :directory, :target_dir, :processed, :friendly_name
9
+ def initialize(directory)
10
+ @mutex = Mutex.new
11
+ @directory = directory
12
+ @recording = nil
13
+ @title = nil
14
+ @subtitle = nil
15
+ @friendly_name = nil
16
+ @target_dir = nil
17
+ @processed = false
18
+ @timestamp = File.mtime(@directory + '/index')
19
+ load_info
20
+ update_target_dir
21
+ determine_stream_type
22
+ end
23
+ def delete!()
24
+ @mutex.synchronize {
25
+ @recording = nil
26
+ GC.start
27
+ FileDir.delete!(@target_dir)
28
+ }
29
+ end
30
+ def load_info()
31
+ #begin
32
+ info = File.read(@directory + '/info')
33
+ info.force_encoding('BINARY')
34
+ cd = CharDet.detect(info)
35
+ encoding = cd['encoding']
36
+ info.each_line { | line |
37
+ case line[0..1]
38
+ when 'T '
39
+ @title = line[2..256].chomp
40
+ @title.force_encoding(encoding)
41
+ p "Found title: #{@title}"
42
+ when 'S '
43
+ @subtitle = line[2..256].chomp
44
+ @subtitle.force_encoding(encoding)
45
+ p "Found subtitle: #{@subtitle}"
46
+ end
47
+ }
48
+ #rescue
49
+ #end
50
+ @title = 'Unknown' if not @title
51
+ @subtitle = 'Unknown' if not @subtitle
52
+ end
53
+ def determine_stream_type()
54
+ case
55
+ when File.file?(@directory + '/00001.ts')
56
+ @recording = RecordingTS.new(self)
57
+ when File.file?(@directory + '/00001.vdr')
58
+ @recording = RecordingVDR.new(self)
59
+ else
60
+ raise 'Unknown recording'
61
+ end
62
+ end
63
+ def update_target_dir()
64
+ title = @title
65
+ subtitle = @subtitle
66
+ title.gsub!('/', '!')
67
+ subtitle.gsub!('/', '!')
68
+ @target_dir = "/video/#{title}/#{subtitle}"
69
+ @friendly_name = "#{title} - #{subtitle}"
70
+ end
71
+ def process!()
72
+ @mutex.synchronize{
73
+ @processed = true if @recording.process!
74
+ }
75
+ end
76
+ end
@@ -0,0 +1,22 @@
1
+ require 'file_dir'
2
+
3
+ class RecordingTS
4
+ def initialize(recording)
5
+ @parent = recording
6
+ end
7
+ def process!()
8
+ target_file = @parent.target_dir + "/#{@parent.friendly_name}.ts"
9
+ FileDir.mkdirtree(@parent.target_dir)
10
+ tf = File.new(target_file, 'wb:ascii-8bit')
11
+ source_files = Dir.glob("#{@parent.directory}/*.ts")
12
+ source_files.sort!
13
+ source_files.each { | source_file |
14
+ sf = File.new(source_file, 'rb:ascii-8bit')
15
+ while not sf.eof?
16
+ tf.write(sf.read(1*(2**20))) # Only read some bytes at once
17
+ sleep(0.01) # Be friendly to other processes
18
+ end
19
+ sf.close
20
+ }
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ class RecordingVDR
2
+ def initialize(recording)
3
+ @parent = recording
4
+ end
5
+ def process!()
6
+ return false
7
+ target_file = @parent.target_dir + "/#{@parent.friendly_name}.ts"
8
+ FileDir.mkdirtree(@parent.target_dir)
9
+ tf = File.new(target_file, 'wb:ascii-8bit')
10
+ source_files = Dir.glob("#{@parent.directory}/*.ts")
11
+ source_files.sort!
12
+ source_files.each { | source_file |
13
+ sf = File.new(source_file, 'rb:ascii-8bit')
14
+ while not sf.eof?
15
+ tf.write(sf.read(1*(2**20))) # Only read some bytes at once
16
+ sleep(0.01) # Be friendly to other processes
17
+ end
18
+ sf.close
19
+ }
20
+ end
21
+ end
data/lib/recordings.rb ADDED
@@ -0,0 +1,59 @@
1
+ require 'rubygems'
2
+ require 'rchardet'
3
+ require 'find'
4
+
5
+ require 'recording'
6
+
7
+ class Recordings
8
+ def initialize()
9
+ @recordings_db = Hash.new
10
+ end
11
+ def scan()
12
+ basedir = '/var/vdr/video'
13
+ found_directories = Array.new
14
+ Find.find(basedir) { | entry |
15
+ entry.force_encoding('BINARY')
16
+ # Guess encoding of filename
17
+ cd = CharDet.detect(entry)
18
+ encoding = cd['encoding']
19
+ #p encoding
20
+ entry.force_encoding(encoding)
21
+ # Look for the index file created by VDR
22
+ if File.basename(entry) == "index" then
23
+ directory = File.dirname(entry)
24
+ found_directories << directory
25
+ if @recordings_db[directory] == nil then
26
+ # Found a new entry
27
+ p directory
28
+ add(directory)
29
+ end
30
+ end
31
+ }
32
+ @recordings_db.each { | recording |
33
+ recording.delete! unless found_directories.include?(recording.directory)
34
+ }
35
+ end
36
+ def dump()
37
+ File.new('/var/vdr/video/rubyVDRconvert.recordings.marshal', 'wb:ascii-8bit') { | f |
38
+ f.write(Marshal.dump(@recordings_db))
39
+ }
40
+ end
41
+ def load()
42
+ begin
43
+ @recordings_db = Marshal.load(File.read('/var/vdr/video/rubyVDRconvert.recordings.marshal'))
44
+ rescue
45
+ @recordings_db = Hash.new
46
+ end
47
+ end
48
+ def add(directory)
49
+ # TODO: Add a new recording that was found in the specified directory
50
+ # Ensure that VDR has finished writing the recording by checking the mtime of the index file
51
+ # Wait at least 30 seconds after VDR has finished
52
+ return false if (Time.now - File.mtime(directory + '/index')) > 30
53
+ @recordings_db[directory] = Recording.new(directory)
54
+ @recordings_db[directory].process!
55
+ end
56
+ def delete(recording)
57
+ # TODO: Delete the recording
58
+ end
59
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubyVDRconvert
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Daniel Frank
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-11-07 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rchardet
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 3
30
+ - 0
31
+ version: 1.3.0
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ description:
35
+ email: scripts@danielfrank.net
36
+ executables:
37
+ - rubyVDRconvert
38
+ extensions: []
39
+
40
+ extra_rdoc_files: []
41
+
42
+ files:
43
+ - lib/file_dir.rb
44
+ - lib/processing_thread.rb
45
+ - lib/recording.rb
46
+ - lib/recording_ts.rb
47
+ - lib/recording_vdr.rb
48
+ - lib/recordings.rb
49
+ has_rdoc: true
50
+ homepage:
51
+ licenses: []
52
+
53
+ post_install_message:
54
+ rdoc_options: []
55
+
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ segments:
63
+ - 1
64
+ - 9
65
+ - 2
66
+ version: 1.9.2
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ requirements: []
75
+
76
+ rubyforge_project:
77
+ rubygems_version: 1.3.6
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: background maintenance script for VDR
81
+ test_files: []
82
+