lolcommits 0.13.1 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +1 -0
  3. data/.rubocop_todo.yml +3 -3
  4. data/CHANGELOG.md +18 -7
  5. data/Gemfile +2 -0
  6. data/README.md +101 -76
  7. data/Rakefile +3 -1
  8. data/bin/console +1 -0
  9. data/bin/lolcommits +37 -32
  10. data/config/cucumber.yml +1 -1
  11. data/features/bugs.feature +2 -2
  12. data/features/lolcommits.feature +42 -17
  13. data/features/step_definitions/lolcommits_steps.rb +7 -3
  14. data/lib/lolcommits/animated_gif.rb +77 -0
  15. data/lib/lolcommits/backends/git_info.rb +15 -11
  16. data/lib/lolcommits/backends/installation_git.rb +4 -3
  17. data/lib/lolcommits/backends/installation_mercurial.rb +1 -1
  18. data/lib/lolcommits/backends/mercurial_info.rb +13 -9
  19. data/lib/lolcommits/capturer.rb +14 -6
  20. data/lib/lolcommits/capturer/capture_cygwin.rb +3 -14
  21. data/lib/lolcommits/capturer/capture_fake.rb +8 -2
  22. data/lib/lolcommits/capturer/capture_linux.rb +11 -10
  23. data/lib/lolcommits/capturer/capture_linux_video.rb +15 -0
  24. data/lib/lolcommits/capturer/capture_mac.rb +6 -11
  25. data/lib/lolcommits/capturer/capture_mac_video.rb +23 -0
  26. data/lib/lolcommits/capturer/capture_windows.rb +14 -9
  27. data/lib/lolcommits/capturer/capture_windows_video.rb +46 -0
  28. data/lib/lolcommits/cli/fatals.rb +1 -1
  29. data/lib/lolcommits/cli/launcher.rb +1 -1
  30. data/lib/lolcommits/cli/timelapse_gif.rb +28 -12
  31. data/lib/lolcommits/configuration.rb +4 -26
  32. data/lib/lolcommits/platform.rb +4 -4
  33. data/lib/lolcommits/plugin/base.rb +2 -2
  34. data/lib/lolcommits/plugin/configuration_helper.rb +1 -1
  35. data/lib/lolcommits/runner.rb +138 -69
  36. data/lib/lolcommits/version.rb +2 -2
  37. data/lolcommits.gemspec +4 -2
  38. data/test/assets/test_image.jpg +0 -0
  39. data/test/assets/test_video.mp4 +0 -0
  40. metadata +12 -9
  41. data/lib/lolcommits/capturer/capture_linux_animated.rb +0 -74
  42. data/lib/lolcommits/capturer/capture_mac_animated.rb +0 -75
  43. data/lib/lolcommits/capturer/capture_windows_animated.rb +0 -110
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lolcommits
4
+ class CaptureLinuxVideo < Capturer
5
+ def capture
6
+ system_call "ffmpeg -nostats -v quiet -y -f video4linux2 -video_size 640x480 -i #{capture_device_string} -t #{capture_duration} \"#{capture_path}\" > /dev/null"
7
+ end
8
+
9
+ private
10
+
11
+ def capture_device_string
12
+ capture_device || Dir.glob('/dev/video*').first
13
+ end
14
+ end
15
+ end
@@ -2,19 +2,14 @@
2
2
 
3
3
  module Lolcommits
4
4
  class CaptureMac < Capturer
5
- def capture_device_string
6
- @capture_device.nil? ? nil : "-d \"#{@capture_device}\""
5
+ def capture
6
+ system_call "#{executable_path} -q \"#{capture_path}\" -w #{capture_delay} #{capture_device_string}"
7
7
  end
8
8
 
9
- def capture
10
- # TODO: check we have a webcam we can capture from first. See issue #219
11
- # operating laptop in clamshell (lid closed) from 2nd desktop screen,
12
- # needs to better handle the capturer (imagesnap, videosnap
13
- # CommandCam, mplayer) return code or check with an option before
14
- # attempting capture. Alt solution is puttin in prompt mode option :(
15
- call_str = "#{executable_path} -q \"#{snapshot_location}\" -w #{capture_delay} #{capture_device_string}"
16
- debug "Capturer: making system call for #{call_str}"
17
- system(call_str)
9
+ private
10
+
11
+ def capture_device_string
12
+ capture_device.nil? ? '' : "-d \"#{capture_device}\""
18
13
  end
19
14
 
20
15
  def executable_path
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lolcommits
4
+ class CaptureMacVideo < Capturer
5
+ def capture
6
+ system_call "#{executable_path} -p 640x480 #{capture_device_string}#{capture_delay_string}-t #{capture_duration} --no-audio \"#{capture_path}\" > /dev/null"
7
+ end
8
+
9
+ private
10
+
11
+ def capture_device_string
12
+ "-d \"#{capture_device}\" " if capture_device
13
+ end
14
+
15
+ def capture_delay_string
16
+ "-w \"#{capture_delay}\" " if capture_delay.positive?
17
+ end
18
+
19
+ def executable_path
20
+ File.join(Configuration::LOLCOMMITS_ROOT, 'vendor', 'ext', 'videosnap', 'videosnap')
21
+ end
22
+ end
23
+ end
@@ -3,19 +3,24 @@
3
3
  module Lolcommits
4
4
  class CaptureWindows < Capturer
5
5
  def capture
6
- # DirectShow takes a while to show... at least for me anyway
7
- delaycmd = ' /delay 3000'
8
- if capture_delay > 0
9
- # CommandCam delay is in milliseconds
10
- delaycmd = " /delay #{capture_delay * 1000}"
11
- end
12
-
13
- _stdin, stdout, _stderr = Open3.popen3("#{executable_path} /filename #{snapshot_location}#{delaycmd}")
6
+ _stdin, stdout, _stderr = Open3.popen3("#{executable_path} /filename #{capture_path}#{delay_arg}")
14
7
 
15
- # looks like we still need to read the output for something to happen
8
+ # need to read the output for something to happen
16
9
  stdout.read
17
10
  end
18
11
 
12
+ private
13
+
14
+ def delay_arg
15
+ # CommandCam delay is in milliseconds
16
+ if capture_delay.positive?
17
+ " /delay #{capture_delay * 1000}"
18
+ else
19
+ # DirectShow takes a while to show, default to 3 sec delay
20
+ ' /delay 3000'
21
+ end
22
+ end
23
+
19
24
  def executable_path
20
25
  File.join(Configuration::LOLCOMMITS_ROOT, 'vendor', 'ext', 'CommandCam', 'CommandCam.exe')
21
26
  end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lolcommits
4
+ class CaptureWindowsVideo < Capturer
5
+ def capture
6
+ return unless capture_device_string
7
+
8
+ system_call "ffmpeg -v quiet -y -f dshow -i video=\"#{capture_device_string}\" -video_size 640x480 -t #{capture_duration} \"#{capture_path}\" > NUL"
9
+ end
10
+
11
+ private
12
+
13
+ def capture_device_string
14
+ capture_device || device_names.first
15
+ end
16
+
17
+ def ffpmeg_list_devices_cmd
18
+ 'ffmpeg -list_devices true -f dshow -i dummy 2>&1'
19
+ end
20
+
21
+ # inspired by this code from @rdp http://tinyurl.com/y7t276bh
22
+ def device_names
23
+ @device_names ||= begin
24
+ names = []
25
+ cmd_output = ''
26
+ count = 0
27
+ while cmd_output.empty? || !cmd_output.split('DirectShow')[2]
28
+ cmd_output = system_call(ffpmeg_list_devices_cmd, true)
29
+ count += 1
30
+ raise 'failed to find a video capture device with ffmpeg -list_devices' if count == 5
31
+
32
+ sleep 0.1
33
+ end
34
+ cmd_output.gsub!("\r\n", "\n")
35
+ video = cmd_output.split('DirectShow')[1]
36
+
37
+ video.lines.map do |line|
38
+ names << Regexp.last_match(1) if line =~ /"(.+)"\n/
39
+ end
40
+
41
+ debug "found #{names.length} video devices: #{names.join(', ')}"
42
+ names
43
+ end
44
+ end
45
+ end
46
+ end
@@ -59,7 +59,7 @@ module Lolcommits
59
59
  # If we are not in a git repo, we can't do git related things!
60
60
  # Die with an informative error message in that case.
61
61
  def self.die_if_not_vcs_repo!
62
- debug 'Checking for valid vcs repo'
62
+ debug 'Checking for valid VCS repo'
63
63
  current = File.expand_path('.')
64
64
  parent = File.dirname(current)
65
65
  while current != parent
@@ -10,7 +10,7 @@ module Lolcommits
10
10
  # Right now this is mostly just a wrapper for Launchy, in case we want
11
11
  # to factor out it's dependency later or swap it out.
12
12
  class Launcher
13
- def self.open_image(path)
13
+ def self.open_file(path)
14
14
  open_with_launchy(path)
15
15
  end
16
16
 
@@ -7,9 +7,9 @@ module Lolcommits
7
7
  module CLI
8
8
  # Creates an animated timeline GIF of lolcommits history.
9
9
  class TimelapseGif
10
- # param config [Lolcommits::Configuration]
11
- def initialize(config)
12
- @configuration = config
10
+ # param loldir [String] path to loldir
11
+ def initialize(loldir)
12
+ self.loldir = loldir
13
13
  end
14
14
 
15
15
  # Runs the history timeline animator task thingy
@@ -17,11 +17,11 @@ module Lolcommits
17
17
  def run(args = nil)
18
18
  case args
19
19
  when 'today'
20
- lolimages = @configuration.jpg_images_today
21
- filename = "#{Date.today}.gif"
20
+ lolimages = jpg_images_today
21
+ filename = Date.today.to_s
22
22
  else
23
- lolimages = @configuration.jpg_images
24
- filename = 'archive.gif'
23
+ lolimages = jpg_images
24
+ filename = "all-until-#{Time.now.strftime('%d-%b-%Y--%Hh%Mm%Ss')}"
25
25
  end
26
26
 
27
27
  if lolimages.empty?
@@ -29,14 +29,30 @@ module Lolcommits
29
29
  exit 1
30
30
  end
31
31
 
32
- puts '*** Generating animated gif.'
32
+ puts '*** Generating animated timelapse gif.'
33
33
 
34
- gif = MiniMagick::Image.new File.join @configuration.archivedir, filename
34
+ gif = MiniMagick::Image.new(File.join(timelapses_dir_path, "#{filename}.gif"))
35
+ gif.run_command('convert', *['-delay', '50', '-loop', '0', lolimages, gif.path].flatten)
35
36
 
36
- # This is for ruby 1.8.7, *lolimages just doesn't work with ruby 187
37
- gif.run_command('convert', *['-delay', '50', '-loop', '0', lolimages, gif.path.to_s].flatten)
37
+ puts "*** Done, generated at #{gif.path}"
38
+ end
39
+
40
+ private
41
+
42
+ attr_accessor :loldir
43
+
44
+ def jpg_images
45
+ Dir.glob(File.join(loldir, '*.jpg')).sort_by { |f| File.mtime(f) }
46
+ end
47
+
48
+ def jpg_images_today
49
+ jpg_images.select { |f| Date.parse(File.mtime(f).to_s) == Date.today }
50
+ end
38
51
 
39
- puts "*** #{gif.path} generated."
52
+ def timelapses_dir_path
53
+ dir = File.join(loldir, 'timelapses')
54
+ FileUtils.mkdir_p(dir)
55
+ dir
40
56
  end
41
57
  end
42
58
  end
@@ -38,34 +38,12 @@ module Lolcommits
38
38
  @loldir = Configuration.loldir_for(basename)
39
39
  end
40
40
 
41
- def archivedir
42
- dir = File.join(loldir, 'archive')
43
- FileUtils.mkdir_p dir unless File.directory? dir
44
- dir
41
+ def sha_path(sha, ext)
42
+ File.join loldir, "#{sha}.#{ext}"
45
43
  end
46
44
 
47
- def jpg_images
48
- Dir.glob(File.join(loldir, '*.jpg')).sort_by { |f| File.mtime(f) }
49
- end
50
-
51
- def jpg_images_today
52
- jpg_images.select { |f| Date.parse(File.mtime(f).to_s) == Date.today }
53
- end
54
-
55
- def raw_image(image_file_type = 'jpg')
56
- File.join loldir, "tmp_snapshot.#{image_file_type}"
57
- end
58
-
59
- def main_image(commit_sha, image_file_type = 'jpg')
60
- File.join loldir, "#{commit_sha}.#{image_file_type}"
61
- end
62
-
63
- def video_loc
64
- File.join(loldir, 'tmp_video.mov')
65
- end
66
-
67
- def frames_loc
68
- File.join(loldir, 'tmp_frames')
45
+ def capture_path(ext = 'jpg')
46
+ File.join loldir, "raw_capture.#{ext}"
69
47
  end
70
48
 
71
49
  def list_plugins
@@ -11,11 +11,11 @@ module Lolcommits
11
11
  if ENV['LOLCOMMITS_CAPTURER']
12
12
  const_get(ENV['LOLCOMMITS_CAPTURER'])
13
13
  elsif platform_mac?
14
- animate ? CaptureMacAnimated : CaptureMac
14
+ animate ? CaptureMacVideo : CaptureMac
15
15
  elsif platform_linux?
16
- animate ? CaptureLinuxAnimated : CaptureLinux
16
+ animate ? CaptureLinuxVideo : CaptureLinux
17
17
  elsif platform_windows?
18
- animate ? CaptureWindowsAnimated : CaptureWindows
18
+ animate ? CaptureWindowsVideo : CaptureWindows
19
19
  elsif platform_cygwin?
20
20
  CaptureCygwin
21
21
  else
@@ -123,7 +123,7 @@ module Lolcommits
123
123
  # TODO: handle other platforms here (linux/windows) e.g with ffmpeg -list_devices
124
124
  return unless Platform.platform_mac?
125
125
 
126
- capturer = Lolcommits::CaptureMacAnimated.new
126
+ capturer = Lolcommits::CaptureMacVideo.new
127
127
  `#{capturer.executable_path} -l`
128
128
  end
129
129
  end
@@ -76,13 +76,13 @@ module Lolcommits
76
76
  # uniform puts and print for plugins
77
77
  # dont puts or print if the runner wants to be silent (stealth mode)
78
78
  def puts(*args)
79
- return if runner && runner.capture_stealth
79
+ return if runner&.capture_stealth
80
80
 
81
81
  super(*args)
82
82
  end
83
83
 
84
84
  def print(*args)
85
- return if runner && runner.capture_stealth
85
+ return if runner&.capture_stealth
86
86
 
87
87
  super(*args)
88
88
  end
@@ -31,7 +31,7 @@ module Lolcommits
31
31
  # value is returned.
32
32
  def prompt_autocomplete_hash(prompt, items, name: 'name', value: 'value', suggest_words: 5)
33
33
  words = items.map { |item| item[name] }.sort
34
- puts "e.g. #{words.take(suggest_words).join(', ')}" if suggest_words > 0
34
+ puts "e.g. #{words.take(suggest_words).join(', ')}" if suggest_words.positive?
35
35
  completed_input = gets_autocomplete(prompt, words)
36
36
  items.find { |item| item[name] == completed_input }[value]
37
37
  end
@@ -1,126 +1,195 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'lolcommits/platform'
4
+ require 'lolcommits/animated_gif'
4
5
 
5
6
  module Lolcommits
6
7
  class Runner
7
- attr_accessor :capture_delay, :capture_stealth, :capture_device, :message,
8
- :sha, :snapshot_loc, :main_image, :config, :vcs_info,
9
- :capture_animate
8
+ attr_accessor :capture_delay, :capture_stealth, :capture_device,
9
+ :capture_duration, :capture_path, :capture_video,
10
+ :capture_gif, :sha, :message, :config, :vcs_info,
11
+ :lolcommit_path, :lolcommit_gif_path
10
12
 
11
13
  def initialize(attributes = {})
12
14
  attributes.each do |attr, val|
13
15
  send("#{attr}=", val)
14
16
  end
15
17
 
16
- return unless sha.nil? || message.nil?
17
-
18
18
  if GitInfo.repo_root?
19
19
  self.vcs_info = GitInfo.new
20
20
  elsif MercurialInfo.repo_root?
21
21
  self.vcs_info = MercurialInfo.new
22
- else
23
- raise('Unknown VCS')
24
22
  end
25
23
 
26
- self.sha = vcs_info.sha if sha.nil?
27
- self.message = vcs_info.message if message.nil?
28
- end
24
+ self.sha = sha || vcs_info.sha
25
+ self.message = message || vcs_info.message
29
26
 
30
- def execute_plugins_for(hook)
31
- debug "#{self.class}: running all enabled plugin hooks for #{hook}"
32
- enabled_plugins.each do |plugin|
33
- if plugin.valid_configuration?
34
- plugin.send("run_#{hook}")
35
- else
36
- puts "Warning: skipping plugin #{plugin.name} (invalid configuration, fix with: lolcommits --config -p #{plugin.name})"
37
- end
38
- end
27
+ self.capture_path = config.capture_path(lolcommit_ext)
28
+ self.lolcommit_path = config.sha_path(sha, lolcommit_ext)
29
+ self.lolcommit_gif_path = config.sha_path(sha, 'gif') if capture_gif
39
30
  end
40
31
 
41
- # wrap run to handle things that should happen before and after
42
- # this used to be handled with ActiveSupport::Callbacks, but
43
- # now we're just using a simple procedural list
44
32
  def run
45
- # do plugins that need to happen before capture
46
33
  execute_plugins_for(:pre_capture)
47
34
 
48
- # do main capture to snapshot_loc
35
+ # main capture
49
36
  run_capture
50
37
 
51
- # check capture succeded, file must exist
52
- if File.exist?(snapshot_loc)
53
- ## resize snapshot first
54
- resize_snapshot!
38
+ # capture must exist to run post capture methods
39
+ unless File.exist?(capture_path)
40
+ raise 'failed to capture any image or video!'
41
+ end
42
+
43
+ run_post_capture
44
+ run_capture_ready
45
+ rescue StandardError => e
46
+ debug("#{e.class}: #{e.message}")
47
+ exit 1
48
+ ensure
49
+ debug 'running cleanup'
50
+ FileUtils.rm_f(capture_path)
51
+ end
55
52
 
56
- # execute post_capture plugins, use to alter the capture
57
- execute_plugins_for(:post_capture)
53
+ # return MiniMagick overlay png for manipulation (or create one)
54
+ def overlay
55
+ @overlay ||= begin
56
+ source_path = capture_image? ? lolcommit_path : capture_path
57
+ unless File.exist?(source_path)
58
+ raise "too early to overlay, capture doesn't exist yet"
59
+ end
58
60
 
59
- # execute capture_ready plugins, capture is ready for export/sharing
60
- execute_plugins_for(:capture_ready)
61
+ base = MiniMagick::Image.open(source_path)
62
+ png_tempfile = MiniMagick::Utilities.tempfile('.png')
63
+ debug("creating a new empty overlay png for lolcommit (#{base.dimensions.join('x')})")
61
64
 
62
- # clean away any tmp files
63
- cleanup!
64
- else
65
- debug 'Runner: failed to capture a snapshot'
66
- exit 1
65
+ MiniMagick::Tool::Convert.new do |i|
66
+ i.size "#{base.width}x#{base.height}"
67
+ i.xc 'transparent'
68
+ i << png_tempfile.path
69
+ end
70
+
71
+ MiniMagick::Image.open(png_tempfile.path)
72
+ end
73
+ end
74
+
75
+ # backward compatibility with earlier plugin releases
76
+ # remove this when all plugins target 0.14+
77
+ def main_image
78
+ capture_gif ? lolcommit_gif_path : lolcommit_path
79
+ end
80
+
81
+ private
82
+
83
+ def execute_plugins_for(hook)
84
+ debug "running all enabled #{hook} plugin hooks"
85
+ enabled_plugins.each do |plugin|
86
+ if plugin.valid_configuration?
87
+ plugin.send("run_#{hook}")
88
+ else
89
+ puts "Warning: skipping plugin #{plugin.name} (invalid configuration, fix with: lolcommits --config -p #{plugin.name})"
90
+ end
67
91
  end
68
92
  end
69
93
 
70
- # the main capture
94
+ def capture_image?
95
+ capture_duration.zero?
96
+ end
97
+
71
98
  def run_capture
72
99
  puts '*** Preserving this moment in history.' unless capture_stealth
73
- self.snapshot_loc = config.raw_image(image_file_type)
74
- self.main_image = config.main_image(sha, image_file_type)
75
-
76
- capturer = Platform.capturer_class(capture_animated?).new(
100
+ capturer = Platform.capturer_class(!capture_image?).new(
101
+ capture_path: capture_path,
77
102
  capture_device: capture_device,
78
103
  capture_delay: capture_delay,
79
- snapshot_location: snapshot_loc,
80
- video_location: config.video_loc,
81
- frames_location: config.frames_loc,
82
- animated_duration: capture_animate
104
+ capture_duration: capture_duration
83
105
  )
84
106
  capturer.capture
85
107
  end
86
108
 
87
- def capture_animated?
88
- capture_animate > 0
89
- end
109
+ def run_post_capture
110
+ resize_captured_image if capture_image?
90
111
 
91
- private
112
+ execute_plugins_for(:post_capture)
92
113
 
93
- def enabled_plugins
94
- @enabled_plugins ||= config.plugin_manager.enabled_plugins_for(self)
114
+ # apply overlay if present, or cp video to lolcommit_path
115
+ if @overlay
116
+ apply_overlay
117
+ elsif !capture_image?
118
+ FileUtils.cp(capture_path, lolcommit_path)
119
+ end
120
+
121
+ # optionally create animated gif
122
+ return unless capture_gif
123
+
124
+ AnimatedGif.new.create(
125
+ video_path: lolcommit_path,
126
+ output_path: lolcommit_gif_path
127
+ )
128
+
129
+ # done if we are capturing both video and gif
130
+ return if capture_video
131
+
132
+ # remove video and assign var (if only capturing gif)
133
+ FileUtils.rm_f(lolcommit_path)
134
+ self.lolcommit_path = lolcommit_gif_path
95
135
  end
96
136
 
97
- def image_file_type
98
- capture_animated? ? 'gif' : 'jpg'
137
+ def run_capture_ready
138
+ debug "lolcommit_path: #{lolcommit_path}"
139
+ debug "lolcommit_gif_path: #{lolcommit_gif_path}"
140
+ execute_plugins_for(:capture_ready)
99
141
  end
100
142
 
101
- def resize_snapshot!
102
- debug 'Runner: resizing snapshot'
103
- image = MiniMagick::Image.open(snapshot_loc)
104
- if image[:width] > 640 || image[:height] > 480
105
- # this is hacky resize-to-fill
143
+ def resize_captured_image
144
+ image = MiniMagick::Image.open(capture_path)
145
+
146
+ if image.width > 640 || image.height > 480
147
+ debug "resizing raw image (#{image.dimensions.join('x')}) to #{lolcommit_path} (640x480)"
148
+ # hacky resize to fill bounds
106
149
  image.combine_options do |c|
107
150
  c.resize '640x480^'
108
151
  c.gravity 'center'
109
152
  c.extent '640x480'
110
153
  end
111
- debug "Runner: writing resized image to #{snapshot_loc}"
112
- image.write snapshot_loc
154
+ image.write(lolcommit_path)
155
+ else
156
+ debug "no resize needed, copying raw image to #{lolcommit_path} (640x480)"
157
+ FileUtils.cp(capture_path, lolcommit_path)
113
158
  end
114
- debug "Runner: copying resized image to #{main_image}"
115
- FileUtils.cp(snapshot_loc, main_image)
116
159
  end
117
160
 
118
- def cleanup!
119
- debug 'Runner: running cleanup'
120
- # clean up the captured image and any other raw assets
121
- FileUtils.rm(snapshot_loc)
122
- FileUtils.rm_f(config.video_loc)
123
- FileUtils.rm_rf(config.frames_loc)
161
+ def apply_overlay
162
+ debug 'applying overlay to lolcommit'
163
+ if capture_image?
164
+ MiniMagick::Image.open(lolcommit_path).composite(overlay) do |c|
165
+ c.gravity 'center'
166
+ end.write(lolcommit_path)
167
+ else
168
+ system_call "ffmpeg -v quiet -nostats -i #{capture_path} -i #{overlay.path} \
169
+ -filter_complex overlay=0:0 \
170
+ -y #{lolcommit_path}"
171
+ end
172
+ end
173
+
174
+ def lolcommit_ext
175
+ if capture_image?
176
+ 'jpg'
177
+ else
178
+ 'mp4'
179
+ end
180
+ end
181
+
182
+ def enabled_plugins
183
+ @enabled_plugins ||= config.plugin_manager.enabled_plugins_for(self)
184
+ end
185
+
186
+ def system_call(call_str, capture_output = false)
187
+ debug "making system call for \n #{call_str}"
188
+ capture_output ? `#{call_str}` : system(call_str)
189
+ end
190
+
191
+ def debug(message)
192
+ super("#{self.class}: #{message}")
124
193
  end
125
194
  end
126
195
  end