Class: EdlParser

Inherits:
Object
  • Object
show all
Defined in:
lib/edl_parser.rb

Constant Summary collapse

TimeStamp =
/(^\d+:\d\d[\d:\.]*$|\d+)/

Class Method Summary collapse

Class Method Details

.convert_incoming_to_split_sectors(incoming, add_this_to_mutes_end = 0, add_this_to_mutes_beginning = 0, splits = []) ⇒ Object

divides up mutes and blanks so that they don’t overlap, preferring blanks over mutes returns it like [[start,end,type], [s,e,t]…] type like :blank and :mute



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/edl_parser.rb', line 111

def self.convert_incoming_to_split_sectors incoming, add_this_to_mutes_end = 0, add_this_to_mutes_beginning = 0, splits = []
  if splits != []
    # allow it to do all the double checks we later skip, just in case :)
    self.convert_incoming_to_split_sectors incoming
  end
  mutes = incoming["mutes"] || {}
  blanks = incoming["blank_outs"] || {}
  p 'incoming', incoming, splits
  mutes = mutes.map{|k, v| get_secs(k, v, -add_this_to_mutes_beginning, add_this_to_mutes_end, splits) + [:mute]}
  blanks = blanks.map{|k, v| get_secs(k, v, -add_this_to_mutes_beginning, add_this_to_mutes_end, splits) + [:blank]}
  combined = (mutes+blanks).sort
  
  previous = nil
  combined.each_with_index{|current, idx|
    s,e,t = current
    if e < s
     raise SyntaxError.new("detected an end before a start: #{e} < #{s}") if e < s unless splits.length > 0
    end
    if previous
      ps, pe, pt = previous
      if (s < pe)
        raise SyntaxError.new("detected an overlap #{[s,e,t].join(' ')} #{previous.join(' ')}") unless splits.length > 0
        # our start might be within the previous' in which case its their start, with (greater of our, their endig)
        preferred_end = [e,pe].max
        preferred_type = [t,pt].detect{|t| t == :blank} || :mute # prefer blank to mute
        combined[idx-1] = [ps, preferred_end, preferred_type]
        combined[idx] = nil # allow it to be culled later
      end
      
    end
    previous = current
  }
  combined.compact
end

.convert_to_timestamp_arrays(array, ok_categories_array) ⇒ Object

converts “blanks” => [“00:00:00”, “00”, “reason”, “01”, “01”, “02”, “02”] into sane arrays, also filters based on category, though disabled



51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/edl_parser.rb', line 51

def self.convert_to_timestamp_arrays array, ok_categories_array
  out = []
  while(single_element = extract_entry!(array))
    # assume that it's always start_time, end_time, category, number
    category = single_element[-2]
    category_number = single_element[-1]
    unless ok_categories_array.index([category, category_number])
      out << single_element
    end
  end
  out
end

.extract_entry!(from_this) ⇒ Object

starts with a digit, has at least one colon followed by two digits,then some combo of digits and colons and periods… or just like 5057 s



68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/edl_parser.rb', line 68

def self.extract_entry! from_this
  return nil if from_this.length == 0
  # two digits, then whatever else you see, that's not a digit...
  out = from_this.shift(2)
  out.each{|d|
    unless d =~ TimeStamp
      raise SyntaxError.new('non timestamp? ' + d) 
    end
  }
  while(from_this[0] && from_this[0] !~ TimeStamp)
    out << from_this.shift
  end
  out
end

.get_secs(timestamp_string_begin, timestamp_string_end, add_begin, add_end, splits) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/edl_parser.rb', line 83

def self.get_secs timestamp_string_begin, timestamp_string_end, add_begin, add_end, splits
  answers = []
  unless timestamp_string_begin
  p 'BAD'
    raise 'non begin' 
  end
  unless timestamp_string_end
  p 'BAD2', '', ''
    raise 'non end' 
  end
  for type, offset, multiplier in [[timestamp_string_begin, add_begin, -1], [timestamp_string_end, add_end, 1]]
    original_secs = translate_string_to_seconds(type) + offset
    # now if splits is 900 and we'are at 909, then we're just 9
    closest_split_idx = splits.reverse.index{|t| t < original_secs}
    p 'got idx', closest_split_idx
    if closest_split_idx
      closest_split = splits.reverse[closest_split_idx]
      # add some extra seconds onto these if they're "past" a split, too
      original_secs = original_secs - closest_split + multiplier * (splits.length - closest_split_idx)
      original_secs = [0, original_secs].max # no negatives allowed :)
    end
    answers << original_secs
  end
  answers
end

.parse_file(filename, ignore_settings = false) ⇒ Object



23
24
25
# File 'lib/edl_parser.rb', line 23

def self.parse_file filename, ignore_settings = false
  parse_string File.read(filename), filename, [], ignore_settings
end

.parse_string(string, filename, ok_categories_array = [], ignore_settings = false) ⇒ Object

better eye-ball these before letting people run them, eh? XXXX but I couldn’t think of any other way to parse the files tho

Raises:

  • (SyntaxError)


29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/edl_parser.rb', line 29

def self.parse_string string, filename, ok_categories_array = [], ignore_settings = false
  string = '{' + string + "\n}"
  if filename
   raw = eval(string, binding, filename)
  else
   raw = eval string
  end
  
  raise SyntaxError.new("maybe missing quotation marks?" + string) if raw.keys.contain?(nil)
  
  # mutes and blank_outs need to be special parsed into arrays...
  mutes = raw["mutes"] || []
  blanks = raw["blank_outs"] || []
  if ignore_settings
    mutes = blanks = []
  end
  raw["mutes"] = convert_to_timestamp_arrays(mutes, ok_categories_array)
  raw["blank_outs"] = convert_to_timestamp_arrays(blanks, ok_categories_array)
  raw
end

.translate_string_to_seconds(s) ⇒ Object



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/edl_parser.rb', line 146

def self.translate_string_to_seconds s
  # might actually already be a float, or int, depending on the yaml
  # int for 8 => 9 and also for 1:09 => 1:10
  if s.is_a? Numeric
    return s.to_f
  end
  
  # s is like 1:01:02.0
  total = 0.0
  seconds = nil
  begin
    seconds = s.split(":")[-1]
  rescue Exception => e
   p 'failed!', s
   raise e
  end
  total += seconds.to_f
  minutes = s.split(":")[-2] || "0"
  total += 60 * minutes.to_i
  hours = s.split(":")[-3] || "0"
  total += 60* 60 * hours.to_i
  total
end

.translate_time_to_human_readable(seconds) ⇒ Object



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/edl_parser.rb', line 170

def self.translate_time_to_human_readable seconds
  # 3600 => "1:00:00"
  out = ''
  hours = seconds.to_i / 3600
  if hours > 0
    out << "%d" % hours
    out << ":"
  end
  seconds = seconds - hours*3600
  minutes = seconds.to_i / 60
  out << "%02d" % minutes
  seconds = seconds - minutes * 60
  out << ":"
  # avoid .0 at the end
  if seconds != seconds.to_i
    out << "%04.1f" % seconds
  else
    out << "%02d" % seconds
  end
end