Class: Videoreg::Registrar

Inherits:
Base
  • Object
show all
Defined in:
lib/videoreg/registrar.rb

Constant Summary collapse

DELEGATE_TO_CONFIG =
[:command, :outfile, :resolution, :fps, :duration, :device, :storage, :base_cmd, :store_max]

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#logger, logger, #logger=, logger=, #proc_alive?, #tpl, #which

Constructor Details

#initialize(&block) ⇒ Registrar

Returns a new instance of Registrar.



14
15
16
17
18
19
20
# File 'lib/videoreg/registrar.rb', line 14

def initialize(&block)
  @config = Videoreg::Config.new
  @pid = nil
  @halted_mutex = nil
  @terminated = false
  configure(&block) if block_given?
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(m) ⇒ Object



27
28
29
# File 'lib/videoreg/registrar.rb', line 27

def method_missing(m)
  DELEGATE_TO_CONFIG.include?(m.to_sym) ? config.send(m) : super
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



9
10
11
# File 'lib/videoreg/registrar.rb', line 9

def config
  @config
end

Instance Method Details

#clean_old_files!Object



78
79
80
81
82
83
84
85
86
87
88
# File 'lib/videoreg/registrar.rb', line 78

def clean_old_files!
  all_saved_files = Dir[Pathname.new(storage).join("*#{File.extname(config.filename)}").to_s].sort_by { |c|
    File.stat(c).ctime
  }.reverse
  if all_saved_files.length > config.store_max.to_i
    all_saved_files[config.store_max.to_i..-1].each do |saved_file|
      logger.info "Removing saved file #{saved_file}..."
      File.unlink(saved_file) if File.exists?(saved_file)
    end
  end
end

#configure {|@config| ... } ⇒ Object

Yields:



22
23
24
25
# File 'lib/videoreg/registrar.rb', line 22

def configure
  @thread = nil
  yield @config
end

#continuousObject



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/videoreg/registrar.rb', line 31

def continuous
  logger.info "Starting the continuous capture..."
  @terminated = false
  @thread = Thread.new do
    while true do
      unless @halted_mutex.nil?
        logger.info "Registrar (#{device}) HALTED. Waiting for the restore message..."
        @halted_mutex.lock
      end
      unless device_exists?
        logger.error "Capture failed! Device #{device} does not exist!"
        terminate!
      end
      begin
        logger.info "Cleaning old files from storage (#{storage})... (MAX: #{config.store_max})"
        clean_old_files!
        logger.info "Waiting for registrar (#{device}) to finish the part (#{outfile})..."
        run # perform one registration
        logger.info "Registrar (#{device}) has finished to capture the part (#{outfile})..."
      rescue RuntimeError => e
        logger.error(e.message)
        logger.info "Registrar (#{device}) has failed to capture the part (#{outfile})..."
        terminate!
      end
    end
  end
end

#device_exists?Boolean

Returns:

  • (Boolean)


149
150
151
# File 'lib/videoreg/registrar.rb', line 149

def device_exists?
  File.exists?(device)
end

#force_release_lock!Object



144
145
146
147
# File 'lib/videoreg/registrar.rb', line 144

def force_release_lock!
  logger.info("Forced to release lockfile #{config.lockfile}...")
  File.unlink(config.lockfile) if File.exists?(config.lockfile)
end

#halt!Object



90
91
92
93
94
95
# File 'lib/videoreg/registrar.rb', line 90

def halt!
  logger.info "Registrar #{device} HALTED! Killing process..."
  @halted_mutex = Mutex.new
  @halted_mutex.lock
  kill_process!
end

#kill!Object

Kill completely



125
126
127
128
129
130
# File 'lib/videoreg/registrar.rb', line 125

def kill!
  terminate!
  kill_process! if process_alive?
ensure
  safe_release!
end

#kill_process!Object

Kill just the underlying process



114
115
116
117
118
119
120
121
122
# File 'lib/videoreg/registrar.rb', line 114

def kill_process!
  begin
    logger.info("Killing the process for #{device} : #{pid}")
    Process.kill("KILL", pid) if process_alive?
    Process.getpgid
  rescue => e
    logger.warn("An attempt to kill already killed process (#{pid}): #{e.message}")
  end
end

#pause!Object



97
98
99
100
# File 'lib/videoreg/registrar.rb', line 97

def pause!
  logger.info "Registrar #{device} pausing process with pid #{pid}..."
  Process.kill("STOP", pid) if process_alive?
end

#paused?Boolean

Returns:

  • (Boolean)


165
166
167
# File 'lib/videoreg/registrar.rb', line 165

def paused?
  process_alive? && (`ps -p #{pid} -o stat=`.chomp == "T")
end

#pidObject



74
75
76
# File 'lib/videoreg/registrar.rb', line 74

def pid
  @pid || ((rpid = lockfile.lockcode) ? rpid.to_i : nil)
end

#process_alive?Boolean

Returns:

  • (Boolean)


157
158
159
# File 'lib/videoreg/registrar.rb', line 157

def process_alive?
  !pid.to_s.empty? && pid.to_i != 0 && proc_alive?(pid)
end

#recover!Object



102
103
104
105
106
# File 'lib/videoreg/registrar.rb', line 102

def recover!
  logger.info "Registrar #{device} UNHALTED! Recovering process..."
  @halted_mutex.unlock if @halted_mutex && @halted_mutex.locked?
  @halted_mutex = nil
end

#resume!Object



108
109
110
111
# File 'lib/videoreg/registrar.rb', line 108

def resume!
  logger.info "Registrar #{device} resuming process with pid #{pid}..."
  Process.kill("CONT", pid) if process_alive?
end

#runObject



59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/videoreg/registrar.rb', line 59

def run
  logger.info "Spawning a new process to capture video from device '#{device}'..."
  raise "Lockfile already exists '#{config.lockfile}'..." if File.exist?(config.lockfile)
  logger.info "Running the command: '#{command}'..."
  raise "#{base_cmd} not found on your system. Please install it or add it to your PATH" if which(base_cmd).nil?&& !File.exists?(base_cmd)
  Open4::popen4(command) do |pid, stdin, stdout, stderr|
    @pid = pid
    raise "Cannot lock the lock-file '#{config.lockfile}'..." unless lock(pid)
    output = stdout.read + stderr.read
    raise "FATAL ERROR: Cannot capture video: \n #{output}" if error?(output)
  end
ensure
  release
end

#safe_release!Object



140
141
142
# File 'lib/videoreg/registrar.rb', line 140

def safe_release!
  release if File.exists?(config.lockfile)
end

#self_alive?Boolean

Returns:

  • (Boolean)


153
154
155
# File 'lib/videoreg/registrar.rb', line 153

def self_alive?
  process_alive? && lockfile.readlock
end

#terminate!Object

Terminate the main thread



133
134
135
136
137
138
# File 'lib/videoreg/registrar.rb', line 133

def terminate!
  @terminated = true
  @thread.kill if @thread
ensure
  safe_release!
end

#terminated?Boolean

Returns:

  • (Boolean)


161
162
163
# File 'lib/videoreg/registrar.rb', line 161

def terminated?
  @terminated
end