rubyVDRconvert 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.
@@ -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
+