tracksperanto 1.7.4 → 1.7.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,7 @@
1
+ === 1.7.5 / 2010-02-17
2
+
3
+ * Use a special IO so that we can display progress when parsing/reading a file (based on the IO offset)
4
+
1
5
  === 1.7.4 / 2010-02-02
2
6
 
3
7
  * Introduce an intentional gap in the reference exports to test trackers with gaps
@@ -46,6 +46,7 @@ lib/tracksperanto/const_name.rb
46
46
  lib/tracksperanto/ext_io.rb
47
47
  lib/tracksperanto/format_detector.rb
48
48
  lib/tracksperanto/keyframe.rb
49
+ lib/tracksperanto/progressive_io.rb
49
50
  lib/tracksperanto/safety.rb
50
51
  lib/tracksperanto/simple_export.rb
51
52
  lib/tracksperanto/tracker.rb
@@ -129,6 +130,7 @@ test/test_const_name.rb
129
130
  test/test_extio.rb
130
131
  test/test_format_detector.rb
131
132
  test/test_keyframe.rb
133
+ test/test_progressive_io.rb
132
134
  test/test_simple_export.rb
133
135
  test/test_tracker.rb
134
136
  test/test_tracksperanto.rb
@@ -92,7 +92,6 @@ end
92
92
  input_file = ARGV.pop
93
93
  if !input_file
94
94
  STDERR.puts "No input file provided - should be the last argument"
95
- puts parser
96
95
  exit(-1)
97
96
  end
98
97
 
@@ -100,20 +99,26 @@ class Spinner
100
99
  RING = ['|', '/', '-', '\\', '|', '/', '-', '\\']
101
100
 
102
101
  def initialize
103
- @counter = 0
104
- @last_message_length = 0
102
+ @counter, @last_len = 0, 0
105
103
  end
106
104
 
107
105
  def spin(percent, msg)
108
106
  current = RING[(@counter += 1) % RING.length]
109
107
  output = " [%s %d%%]" % [current, percent]
110
- STDOUT.write(output + "\r" * output.length)
108
+ STDOUT.write(output + ("\r" * output.length))
111
109
  STDOUT.flush
110
+ @last_len = output.length
111
+ end
112
+
113
+ def finish(with_message = '')
114
+ STDOUT.write("\r" * @last_len.to_i)
115
+ STDOUT.flush
116
+ STDOUT.puts(with_message)
112
117
  end
113
118
  end
114
119
 
115
- pipe = Tracksperanto::Pipeline::Base.new
116
- pipe.progress_block = Spinner.new.method(:spin).to_proc
120
+ spinner = Spinner.new
121
+ pipe = Tracksperanto::Pipeline::Base.new(:progress_block => spinner.method(:spin).to_proc)
117
122
 
118
123
  if sole_format
119
124
  begin
@@ -137,4 +142,5 @@ pipe.run(input_file, :pix_w => width, :pix_h => height, :parser => reader_klass)
137
142
  lerpm.enabled = lerp
138
143
  len.min_length = length_gate
139
144
  end
140
- STDOUT.puts("\rConverted #{pipe.converted_points} trackers with #{pipe.converted_keyframes} keys")
145
+
146
+ spinner.finish("Converted #{pipe.converted_points} trackers with #{pipe.converted_keyframes} keys")
@@ -25,7 +25,7 @@ class Tracksperanto::Export::SynthEyes < Tracksperanto::Export::Base
25
25
  end
26
26
 
27
27
  def start_tracker_segment(tracker_name)
28
- @last_f, @tracker_name = nil, tracker_name
28
+ @last_registered_frame, @tracker_name = nil, tracker_name
29
29
  end
30
30
 
31
31
  def export_point(frame, abs_float_x, abs_float_y, float_residual)
@@ -38,14 +38,14 @@ class Tracksperanto::Export::SynthEyes < Tracksperanto::Export::Base
38
38
  # It's very important that we provide an outcome code for Syntheyes. Regular keyframes get
39
39
  # STATUS_STD, and after a gap we have to signal STATUS_REENABLE, otherwise this might bust solves
40
40
  def get_outcome_code(frame)
41
- outcome = if @last_f.nil?
41
+ outcome = if @last_registered_frame.nil?
42
42
  STATUS_KF
43
- elsif @last_f && (@last_f != frame -1)
43
+ elsif @last_registered_frame != (frame - 1)
44
44
  STATUS_REENABLE
45
45
  else
46
46
  STATUS_STD
47
47
  end
48
- @last_f = frame
48
+ @last_registered_frame = frame
49
49
  outcome
50
50
  end
51
51
  end
@@ -12,6 +12,8 @@ module Tracksperanto::ShakeGrammar
12
12
  attr_reader :sentinel
13
13
 
14
14
  STOP_TOKEN = :__stop #:nodoc:
15
+ MAX_BUFFER_SIZE = 32000
16
+ MAX_STACK_DEPTH = 127
15
17
 
16
18
  # The first argument is the IO handle to the data of the Shake script.
17
19
  # The second argument is a "sentinel" that is going to be passed
@@ -42,11 +44,11 @@ module Tracksperanto::ShakeGrammar
42
44
 
43
45
  c = @io.read(1)
44
46
 
45
- if @buf.length > 32000 # Wrong format and the buffer is filled up, bail
47
+ if @buf.length > MAX_BUFFER_SIZE # Wrong format and the buffer is filled up, bail
46
48
  raise WrongInput, "Buffer overflow at 32K, this is definitely not a Shake script"
47
49
  end
48
50
 
49
- if @stack_depth > 127 # Wrong format - parentheses overload
51
+ if @stack_depth > MAX_STACK_DEPTH # Wrong format - parentheses overload
50
52
  raise WrongInput, "Stack overflow at level 128, this is probably a LISP program uploaded by accident"
51
53
  end
52
54
 
@@ -13,6 +13,8 @@
13
13
  # and setup outputs for all supported export formats.
14
14
  class Tracksperanto::Pipeline::Base
15
15
 
16
+ include Tracksperanto::BlockInit
17
+
16
18
  # How many points have been converted. In general, the pipeline does not preserve the parsed tracker objects
17
19
  # after they have been exported
18
20
  attr_reader :converted_points
@@ -83,16 +85,27 @@ class Tracksperanto::Pipeline::Base
83
85
  # If a block is passed, the block will receive the percent complete and the last
84
86
  # status message that you can pass back to the UI
85
87
  def run_export(tracker_data_io, parser, processor)
86
- @ios << tracker_data_io
87
-
88
88
  points, keyframes, percent_complete = 0, 0, 0.0
89
89
 
90
90
  yield(percent_complete, "Starting the parser") if block_given?
91
+
92
+ # Report progress from the parser
91
93
  parser.progress_block = lambda do | message |
92
94
  yield(percent_complete, message) if block_given?
93
95
  end
94
96
 
95
- trackers = parser.parse(tracker_data_io)
97
+ # Wrap the input in a progressive IO
98
+ io_with_progress = Tracksperanto::ProgressiveIO.new(tracker_data_io)
99
+ @ios << io_with_progress
100
+
101
+ # Setup a lambda that will spy on the reader and update the percentage.
102
+ # We will only broadcast messages that come from the parser though (complementing it
103
+ # with a percentage)
104
+ io_with_progress.progress_block = lambda do | offset, of_total |
105
+ percent_complete = (50.0 / of_total) * offset
106
+ end
107
+
108
+ trackers = parser.parse(io_with_progress)
96
109
 
97
110
  validate_trackers!(trackers)
98
111
 
@@ -4,7 +4,7 @@ require 'tempfile'
4
4
 
5
5
  module Tracksperanto
6
6
  PATH = File.expand_path(File.dirname(__FILE__))
7
- VERSION = '1.7.4'
7
+ VERSION = '1.7.5'
8
8
 
9
9
  module Import; end
10
10
  module Export; end
@@ -42,8 +42,7 @@ module Tracksperanto
42
42
  # Case-insensitive search for an export module by name
43
43
  def self.get_exporter(name)
44
44
  exporters.each do | x |
45
- normalized_name = x.to_s.split("::")[-1].downcase
46
- return x if normalized_name == name.downcase
45
+ return x if x.const_name.downcase == name.downcase
47
46
  end
48
47
 
49
48
  raise NameError, "Unknown exporter #{name}"
@@ -52,8 +51,7 @@ module Tracksperanto
52
51
  # Case-insensitive search for an export module by name
53
52
  def self.get_importer(name)
54
53
  importers.each do | x |
55
- normalized_name = x.to_s.split("::")[-1].downcase
56
- return x if normalized_name == name.downcase
54
+ return x if x.const_name.downcase == name.downcase
57
55
  end
58
56
 
59
57
  raise NameError, "Unknown importer #{name}"
@@ -70,6 +68,7 @@ end
70
68
  tracker
71
69
  format_detector
72
70
  ext_io
71
+ progressive_io
73
72
  simple_export
74
73
  uv_coordinates
75
74
  ).each do | submodule |
@@ -1,17 +1,17 @@
1
1
  # Many importers use this as a standard. This works like a wrapper for any
2
- # IO object with a couple extra methods added
2
+ # IO object with a couple extra methods added.
3
3
  class Tracksperanto::ExtIO < DelegateClass(IO)
4
4
  def initialize(with)
5
5
  __setobj__ with
6
6
  end
7
7
 
8
8
  def gets_and_strip
9
- s = __getobj__.gets
9
+ s = gets
10
10
  s ? s.strip : nil
11
11
  end
12
12
 
13
13
  def gets_non_empty
14
- line = __getobj__.gets
14
+ line = gets
15
15
  return nil if line.nil?
16
16
  s = line.strip
17
17
  return gets_non_empty if s.empty?
@@ -0,0 +1,79 @@
1
+ # Used for IO objects that need to report the current offset at each operation that changes the said offset
2
+ # (useful for building progress bars that report on a file read operation)
3
+ class Tracksperanto::ProgressiveIO < DelegateClass(IO)
4
+
5
+ # Should contain a block that accepts the current offset in bytes and the total size
6
+ attr_accessor :progress_block
7
+
8
+ # Get or set the total size of the contained IO. If the passed IO is a File object
9
+ # the size will be preset automatically
10
+ attr_accessor :total_size
11
+
12
+ def initialize(with_file)
13
+ __setobj__(with_file)
14
+ @total_size = with_file.stat.size if with_file.respond_to?(:stat)
15
+ end
16
+
17
+ def each(sep_string = $/, &blk)
18
+ # Report offset at each call of the iterator
19
+ result = super(sep_string) do | line |
20
+ yield(line)
21
+ notify_read
22
+ end
23
+ end
24
+ alias_method :each_line, :each
25
+
26
+ def each_byte(&blk)
27
+ # Report offset at each call of the iterator
28
+ super { |b| yield(b); notify_read }
29
+ end
30
+
31
+ def getc
32
+ returning(super) { notify_read }
33
+ end
34
+
35
+ def gets
36
+ returning(super) { notify_read }
37
+ end
38
+
39
+ def read(*a)
40
+ returning(super) { notify_read }
41
+ end
42
+
43
+ def readbytes(*a)
44
+ returning(super) { notify_read }
45
+ end
46
+
47
+ def readchar
48
+ returning(super) { notify_read }
49
+ end
50
+
51
+ def readline(*a)
52
+ returning(super) { notify_read }
53
+ end
54
+
55
+ def readlines(*a)
56
+ returning(super) { notify_read }
57
+ end
58
+
59
+ def seek(*a)
60
+ returning(super) { notify_read }
61
+ end
62
+
63
+ def ungetc(*a)
64
+ returning(super) { notify_read }
65
+ end
66
+
67
+ def pos=(p)
68
+ returning(super) { notify_read }
69
+ end
70
+
71
+ private
72
+ def returning(r)
73
+ yield; r
74
+ end
75
+
76
+ def notify_read
77
+ @progress_block.call(pos, @total_size) if @progress_block
78
+ end
79
+ end
@@ -0,0 +1,119 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestProgressiveIO < Test::Unit::TestCase
4
+
5
+ def e(s)
6
+
7
+ # Make a mock File object from a string
8
+ io = StringIO.new(s)
9
+ mock_stat = flexmock(:size => s.length)
10
+ flexmock(io).should_receive(:stat).and_return(mock_stat)
11
+
12
+ Tracksperanto::ProgressiveIO.new(io)
13
+ end
14
+
15
+ def test_each
16
+ io, messages = e("Mary\nHad\nA little\nLamb"), []
17
+
18
+ io.progress_block = lambda do | offset, total |
19
+ messages.push([offset, total])
20
+ end
21
+
22
+ lines = []
23
+ io.each {|line| lines.push(line) }
24
+ assert_equal ["Mary\n", "Had\n", "A little\n", "Lamb"], lines
25
+ assert_equal [[5, 22], [9, 22], [18, 22], [22, 22]], messages
26
+ end
27
+
28
+ def test_each_byte
29
+ io, messages = e("123"), []
30
+
31
+ io.progress_block = lambda do | offset, total |
32
+ messages.push([offset, total])
33
+ end
34
+
35
+ bytes = []
36
+ io.each_byte{|s| bytes << s }
37
+ assert_equal [49, 50, 51], bytes
38
+ assert_equal [[1, 3], [2, 3], [3, 3]], messages
39
+ end
40
+
41
+ def test_getc
42
+ io = e("123")
43
+ io.progress_block = lambda do | offset, total |
44
+ assert_equal [1, 3], [offset, total]
45
+ end
46
+ assert_equal 49, io.getc
47
+ end
48
+
49
+ def test_gets
50
+ io = e("Mary\nHad\nA little\nLamb")
51
+ io.progress_block = lambda do | offset, total |
52
+ assert_equal [5, 22], [offset, total]
53
+ end
54
+ assert_equal "Mary\n", io.gets
55
+ end
56
+
57
+ def test_read
58
+ io = e("Mary\nHad\nA little\nLamb")
59
+ io.progress_block = lambda do | offset, total |
60
+ assert_equal [15, 22], [offset, total]
61
+ end
62
+ assert_equal "Mary\nHad\nA litt", io.read(15)
63
+ end
64
+
65
+ def test_readchar
66
+ io = e("123")
67
+ io.progress_block = lambda do | offset, total |
68
+ assert_equal [1, 3], [offset, total]
69
+ end
70
+ assert_equal 49, io.readchar
71
+ end
72
+
73
+ def test_readline
74
+ io = e("Mary\nHad\nA little\nLamb")
75
+ io.progress_block = lambda do | offset, total |
76
+ assert_equal [5, 22], [offset, total]
77
+ end
78
+ assert_equal "Mary\n", io.readline
79
+ end
80
+
81
+ def test_readlines
82
+ io = e("Mary\nHad\nA little\nLamb")
83
+ m = []
84
+ io.progress_block = lambda do | offset, total |
85
+ m.push([offset, total])
86
+ end
87
+
88
+ assert_equal ["Mary\n", "Had\n", "A little\n", "Lamb"], io.readlines
89
+ assert_equal [[22, 22]], m
90
+ end
91
+
92
+ def test_seek
93
+ io = e("Mary\nHad\nA little\nLamb")
94
+ io.progress_block = lambda do | offset, total |
95
+ assert_equal [6, 22], [offset, total]
96
+ end
97
+ io.seek(6)
98
+ end
99
+
100
+ def test_ungetc
101
+ io = e("Mary\nHad\nA little\nLamb")
102
+ m = []
103
+ io.progress_block = lambda do | offset, total |
104
+ m.push([offset, total])
105
+ end
106
+
107
+ io.getc
108
+ io.ungetc(2)
109
+ assert_equal [[1, 22], [0, 22]], m
110
+ end
111
+
112
+ def test_poseq
113
+ io = e("Mary\nHad\nA little\nLamb")
114
+ io.progress_block = lambda do | offset, total |
115
+ assert_equal [2, 22], [offset, total]
116
+ end
117
+ io.pos = 2
118
+ end
119
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tracksperanto
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.4
4
+ version: 1.7.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julik Tarkhanov
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-02-09 00:00:00 +01:00
12
+ date: 2010-02-17 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -93,6 +93,7 @@ files:
93
93
  - lib/tracksperanto/ext_io.rb
94
94
  - lib/tracksperanto/format_detector.rb
95
95
  - lib/tracksperanto/keyframe.rb
96
+ - lib/tracksperanto/progressive_io.rb
96
97
  - lib/tracksperanto/safety.rb
97
98
  - lib/tracksperanto/simple_export.rb
98
99
  - lib/tracksperanto/tracker.rb
@@ -176,6 +177,7 @@ files:
176
177
  - test/test_extio.rb
177
178
  - test/test_format_detector.rb
178
179
  - test/test_keyframe.rb
180
+ - test/test_progressive_io.rb
179
181
  - test/test_simple_export.rb
180
182
  - test/test_tracker.rb
181
183
  - test/test_tracksperanto.rb
@@ -244,6 +246,7 @@ test_files:
244
246
  - test/test_extio.rb
245
247
  - test/test_format_detector.rb
246
248
  - test/test_keyframe.rb
249
+ - test/test_progressive_io.rb
247
250
  - test/test_simple_export.rb
248
251
  - test/test_tracker.rb
249
252
  - test/test_tracksperanto.rb