xmltv2html 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/ChangeLog +128 -0
  2. data/bin/xmltv2html.rb +402 -323
  3. data/xmltv2htmlrc +31 -33
  4. metadata +3 -3
data/bin/xmltv2html.rb CHANGED
@@ -1,9 +1,10 @@
1
+ #!/usr/bin/ruby -w
2
+ # With Ruby 1.8.3, yaml gives a lot of warnings... :-(( Fixed with 1.8.4
1
3
  #!/usr/bin/env ruby
2
- #!/usr/bin/ruby -w # With Ruby 1.8.3, yaml gives a lot of warnings... :-((
3
4
  #
4
5
  # xmltv2html.rb - A Ruby script to transform the XMLTV output into HTML.
5
6
  #
6
- # Version : 0.6.1
7
+ # Version : 0.7.0
7
8
  # Author : Kurt V. Hindenburg <public@kurt.hindenburg.name>
8
9
  #
9
10
  # Copyright (C) 2003, 2004, 2005 Kurt V. Hindenburg
@@ -38,8 +39,6 @@ file and a CSS file.
38
39
  = OPTIONS
39
40
  : -c, --configfile=FILE
40
41
  Configuration file to use.
41
- : --noconfigfile
42
- Do not use any configuration file.
43
42
  : --urlprev=URL
44
43
  URL for previous link.
45
44
  : --urlnext=URL
@@ -63,7 +62,6 @@ Written by Kurt V. Hindenburg <public@kurt.hindenburg.name>
63
62
  = SEE ALSO
64
63
  * ((<"xmltv2html.rb home page - http://xmltv2html.rubyforge.org/"|URL:http://xmltv2html.rubyforge.org/>))
65
64
  * ((<"xmltv home page - http://sourceforge.net/projects/xmltv"|URL:http://sourceforge.net/projects/xmltv>))
66
- * ((<"REXML home page - http://www.germane-software.com/software/rexml"|URL:http://www.germane-software.com/software/rexml>))
67
65
  = BUGS
68
66
  * Please process the xmltv.xml file through tv_sort ((*before*)) using xmltv2html.rb
69
67
 
@@ -75,10 +73,10 @@ require 'rexml/document'
75
73
  require 'singleton'
76
74
  require 'time'
77
75
  require 'set'
76
+ require 'ostruct'
78
77
 
79
-
80
- XMLTV2HTML_VERSION="0.6.1"
81
- XMLTV2HTML_DATE="Dec 21, 2005"
78
+ XMLTV2HTML_VERSION="0.7.0"
79
+ XMLTV2HTML_DATE="Feb 13, 2006"
82
80
 
83
81
  class Time
84
82
  class << self
@@ -95,9 +93,8 @@ class Time
95
93
  end
96
94
 
97
95
  ### object.<method>
98
-
99
96
  def round_to_interval
100
- self - (self.min % @@options['time_divisor']) * 60
97
+ self - (self.min % @@options[:time_divisor]) * 60
101
98
  end
102
99
 
103
100
  end
@@ -113,79 +110,55 @@ module XMLTV2HTML
113
110
  exit(1)
114
111
  end
115
112
 
116
- def test
117
- # info "The West Wing=", @@options['favorites'].include?('The West Wing')
118
- # info "EXTRA=", @@options['favorites'].include?('EXTRA')
119
- # info "Lay & Order=", @@options['favorites'].include?("Law & Order")
120
- # info "Categories=", @@options['categories'].class
121
- # info "Categories=", @@options['categories']
122
- # info "start_time=",@@options['start_time']
123
- # info "stop_time=",@@options['stop_time']
124
- end
125
-
126
113
  class ConfReader
127
114
  def initialize
128
115
  @@options = self # set Module variable
129
116
  @cmd_line_options = nil
130
117
  clear
131
118
  set_defaults
132
- # info "default config_file=",@@options['config_file']
133
119
  parse_command_line_options_for_config_file
134
- # info "cmd_line config_file=",@@options['config_file']
135
- # info "cmd_line start_time=",@@options['start_time']
136
- # info "cmd_line stop_time=",@@options['stop_time']
137
-
138
120
 
139
- read_conf if @@options['use_config_file']
140
- # info "start_time=",@@options['start_time']
141
- # info "stop_time=",@@options['stop_time']
121
+ read_conf if @@options[:use_config_file]
142
122
  parse_command_line_options
143
- # info "start_time=",@@options['start_time']
144
- # info "stop_time=",@@options['stop_time']
145
- # info "config_file=",@@options['config_file']
146
123
 
147
124
  # convert favorites_list to Set for faster lookup
148
- @@options['favorites'] = Set.new @@options['favorites_list' ]
149
-
150
- test
125
+ @@options[:favorites] = Set.new @@options[:favorites_list]
151
126
  end
152
127
 
153
128
  # Don't edit these, use an external xmltv2htmlrc file.
154
129
  def set_defaults
155
130
  @tree = {
156
- 'verbose' => false,
157
- 'times_interval' => 4,
158
- 'channels_interval' => 4,
159
- 'time_format_12' => true,
160
- 'use_favorites' => false,
161
- 'output_favorites' => false,
162
- 'favorites_list' => [],
163
- 'css_filename' => 'xmltv2html.css',
164
- 'categories' => {},
165
- 'output_date_in_time' => false,
166
- 'date_format' => '%a %d',
167
- 'use_programme_popup' => true,
168
- 'programme_popup_method' => "DHTML",
169
- 'popup_title_format' => "%T",
170
- 'popup_body_format' => "%S %P<br />%D<br />Rating: %R",
171
- 'popup_title_color' => "#FFFFFF",
172
- 'popup_title_font' => "",
173
- 'popup_title_font_size' => "2",
174
- 'popup_title_background_color' => "#000099",
175
- 'popup_body_color' => "#000000",
176
- 'popup_body_font' => "",
177
- 'popup_body_font_size' => "1",
178
- 'popup_body_background_color' => "#E8E8FF",
179
- 'popup_body_width' => "200",
180
- 'output_links' => false,
181
- 'start_time' => "",
182
- 'stop_time' => "",
183
- 'start_date' => "",
184
- 'stop_date' => "",
185
- 'time_divisor' => 10, # Divide programmes' times in X minute slots
186
- 'total_hours' => 0,
187
- 'config_file' => "",
188
- 'use_config_file' => true,
131
+ :verbose => false,
132
+ :times_interval => 4,
133
+ :channels_interval => 4,
134
+ :time_format_12 => true,
135
+ :use_favorites => false,
136
+ :output_favorites => false,
137
+ :favorites_list => [],
138
+ :css_filename => 'xmltv2html.css',
139
+ :categories => {},
140
+ :output_date_in_time => false,
141
+ :date_format => '%a %d',
142
+ :use_programme_popup => true,
143
+ :programme_popup_method => "DHTML",
144
+ :popup_title_format => "%T",
145
+ :popup_body_format => "%S %P<br />%D<br />Rating: %R",
146
+ :popup_title_color => "#FFFFFF",
147
+ :popup_title_font => "",
148
+ :popup_title_font_size => "2",
149
+ :popup_title_background_color => "#000099",
150
+ :popup_body_color => "#000000",
151
+ :popup_body_font => "",
152
+ :popup_body_font_size => "1",
153
+ :popup_body_background_color => "#E8E8FF",
154
+ :popup_body_width => "200",
155
+ :output_links => false,
156
+ :start_time => "",
157
+ :stop_time => "",
158
+ :time_divisor => 10, # Divide programmes' times in X minute slots
159
+ :total_hours => 0,
160
+ :config_file => "",
161
+ :use_config_file => true,
189
162
  }
190
163
  end
191
164
 
@@ -202,8 +175,8 @@ module XMLTV2HTML
202
175
  end
203
176
 
204
177
  def read_conf
205
- return if @@options['config_file'].empty?
206
- f=File.expand_path(@@options['config_file'])
178
+ return if @@options[:config_file].empty?
179
+ f=File.expand_path(@@options[:config_file])
207
180
  if not File.exists?(f) or not File.stat(f).readable_real?
208
181
  info "* Unable to read #{f}\n"
209
182
  return
@@ -211,12 +184,12 @@ module XMLTV2HTML
211
184
  new_xmltv2htmlrc_format = false
212
185
  File.open(f, "r") do |aFile|
213
186
  first_line = aFile.gets
214
- new_xmltv2htmlrc_format = true if first_line =~ /^#config_version: 1/
187
+ new_xmltv2htmlrc_format = true if first_line =~ /^#config_version: 2/
215
188
  end
216
189
  if new_xmltv2htmlrc_format == false
217
- info "\nWhoa! You are using an old xmltv2htmlrc format file (v0.5.x)."
190
+ info "\nWhoa! You are using an old xmltv2htmlrc format file (< v0.7.x)."
218
191
  info "Please update your xmltv2htmlrc using the sample file provided"
219
- info "with xmltv2html-0.6.0+."
192
+ info "with xmltv2html-0.7.0+."
220
193
  die "\n"
221
194
  end
222
195
  info "^ Reading #{f}\n"
@@ -229,12 +202,11 @@ module XMLTV2HTML
229
202
  ARGV.each do
230
203
  |opts|
231
204
  if opts =~ /--configfile=/
232
- @@options['config_file'] = opts.split(/=/)[1]
205
+ @@options[:config_file] = opts.split(/=/)[1]
233
206
  end
234
207
  end
235
208
  end
236
209
 
237
- # TODO: This has to be a better way to do this...
238
210
  def parse_command_line_options
239
211
  ARGV.options do
240
212
  |opts|
@@ -245,17 +217,17 @@ module XMLTV2HTML
245
217
  opts.on_tail("common options:")
246
218
 
247
219
  opts.on("--configfile=FILE", String, "config file to use") {
248
- |@@options['config_file']|}
220
+ |@@options[:config_file]|}
249
221
 
250
222
  opts.on("--starttime=YYYYMMDDHHMM", String, "Start time") {
251
- |@@options['start_time']|}
223
+ |@@options[:start_time]|}
252
224
  opts.on("--stoptime=YYYYMMDDHHMM", String, "Stop time") {
253
- |@@options['stop_time']|}
225
+ |@@options[:stop_time]|}
254
226
 
255
227
  opts.on("--urlprev=URL", String, "URL for previous link") {
256
- |@@options['url_prev']|}
228
+ |@@options[:url_prev]|}
257
229
  opts.on("--urlnext=URL", String, "URL for next link") {
258
- |@@options['url_next']|}
230
+ |@@options[:url_next]|}
259
231
 
260
232
  # no argument, shows at tail
261
233
  opts.on_tail("-h", "--help", "show this message") {puts opts; exit}
@@ -282,86 +254,103 @@ EOF
282
254
 
283
255
  end
284
256
 
285
- class ProgrammeTime
286
- attr_reader(:fullStartTime, :fullStopTime)
287
-
288
- def initialize(start, stop)
289
- @fullStartTime = Time.parse_xmltv_time(start)
290
- @fullStopTime = Time.parse_xmltv_time(stop)
291
-
292
- #$stderr.print "#{@fullStartTime}; "
293
- @fullStartTime = @fullStartTime.round_to_interval
294
- #$stderr.print "after #{@fullStartTime} \n"
295
- @fullStopTime = @fullStopTime.round_to_interval
296
-
297
- @start_date = nil
298
- @stop_date = nil
299
- end
300
-
301
- def returnParsedTime(t)
302
- begin
303
- pt = Time.parse(t)
304
- rescue ArgumentError
305
- die "Unable to parse #{t}\n\n"
306
- end
307
- pt
308
- end
309
-
310
- def calculateStartSlot
311
- return if @@options['start_date'] == nil # 1st pass
312
- @start_date = returnParsedTime(@@options['start_date']) if not @start_date
313
-
314
- start_diff_min = ((@fullStartTime - @start_date) / 60).to_i
315
- # $stderr.print ", diff #{start_diff_min}"
316
- start_slot = start_diff_min / @@options['time_divisor']
317
- # $stderr.print "starting slot #{start_slot}\n"
318
- start_slot
319
- end
320
- def calculateStopSlot
321
- return if @@options['stop_date'] == nil # 1st pass
322
-
323
- @start_date = returnParsedTime(@@options['start_date']) if not @start_date
324
- stop_diff_min = ((@fullStopTime - @start_date) / 60).to_i
325
- stop_slot = stop_diff_min / @@options['time_divisor']
326
- # $stderr.print " stoping slot #{stop_slot}\n"
327
-
328
- # (@fullStopTime.hour * 60 / $timeDivisor) + (@fullStopTime.min / $timeDivisor)
329
- stop_slot
330
- end
331
-
332
- end
333
-
334
257
  class Programme
335
258
  attr_reader :title, :subtitle, :span, :times, :desc, :rating, :category
336
259
  attr_reader :previouslyShown, :spanSlots, :startSlot
337
- attr_accessor :popupIndex
260
+ attr_accessor :startTimeStr, :stopTimeStr
261
+ attr_accessor :startTime, :stopTime, :popupIndex
338
262
 
339
263
  def initialize(title, subtitle, channel, start, stop, desc, rating, cats, rerun)
340
264
  @title = title
341
265
  @subtitle = subtitle
342
266
  @channelid = channel
267
+ @startTimeStr = start
268
+ @stopTimeStr = stop
343
269
  @desc = desc
344
270
  @rating = rating
345
271
  @category = cats
346
272
  @previouslyShown = rerun
347
273
  @popupIndex = -1
274
+ @startTime = nil
275
+ @stopTime = nil
276
+ @startSlot = 0
277
+ @stopSlot = -1
278
+
279
+ @title.gsub!(/[\"\'\`]/,'') # Remove "'`
280
+ @title = @title.unpack("U*").pack("C*")
281
+
282
+ @subtitle = "" if not @subtitle
283
+ @subtitle.gsub!(/[\"\'\`]/,'') # Remove "'`
284
+
285
+ @desc = "" if not @desc
286
+ @desc.gsub!(/[\"\'\`]/,'') # Remove "'`
287
+ @desc = @desc.unpack("U*").pack("C*")
348
288
 
349
- @times = ProgrammeTime.new(start, stop)
289
+ @rating = "" if not @rating
290
+ @rating.gsub!(/[\"\'\`]/,'') # Remove "'`
291
+
292
+ # @times = ProgrammeTime.new(start, stop)
293
+ setStartTime(start) if start
294
+ setStopTime(stop) if stop
350
295
  end
351
296
 
352
- # Slot interval = 12 (60 minutes / 5 minutes)
353
- def calculateSlots
354
- @startSlot = @times.calculateStartSlot
355
- @stopSlot = @times.calculateStopSlot
297
+ # Change start time
298
+ def setStartTime(start)
299
+ #$stderr.print "setStartTime=#{start}\n"
300
+ case start
301
+ when String
302
+ begin
303
+ @startTimeStr = start
304
+ @startTime = Time.parse_xmltv_time(@startTimeStr)
305
+ end
306
+ when Time
307
+ begin
308
+ @startTime = start
309
+ @startTimeStr = start.strftime("%Y%m%d%H%M%S")
310
+ end
311
+ end
312
+ end
356
313
 
357
- return if not @startSlot
358
- return if not @stopSlot
314
+ # Change stop time
315
+ def setStopTime(stop)
316
+ case stop
317
+ when String
318
+ begin
319
+ @stopTimeStr = stop
320
+ @stopTime = Time.parse_xmltv_time(@stopTimeStr)
321
+ end
322
+ when Time
323
+ begin
324
+ @stopTime = stop
325
+ @stopTimeStr = stop.strftime("%Y%m%d%H%M%S")
326
+ end
327
+ end
328
+ end
329
+
330
+ def calculateProgrammeSlots
331
+
332
+ listing_start_time = Time.parse_xmltv_time(@@options[:start_time])
333
+
334
+ start_diff_min = ((@startTime - listing_start_time) / 60).to_i
335
+ @startSlot = start_diff_min / @@options[:time_divisor]
336
+
337
+ stop_diff_min = ((@stopTime - listing_start_time) / 60).to_i
338
+ @stopSlot = stop_diff_min / @@options[:time_divisor]
359
339
 
360
340
  @spanSlots = @stopSlot - @startSlot
341
+
342
+ #$stderr.print "startSlot=#{@startSlot}, stopSlot=#{@stopSlot}, spanSlots=#{@spanSlots}\n"
343
+
361
344
  end
362
345
 
363
- def to_s
364
- @title
346
+ def calculateTimeData
347
+
348
+ @startTime = Time.parse_xmltv_time(@startTimeStr)
349
+ @stopTime = Time.parse_xmltv_time(@stopTimeStr)
350
+
351
+ setStartTime @startTime.round_to_interval
352
+ setStopTime @stopTime.round_to_interval
353
+
365
354
  end
366
355
 
367
356
  end
@@ -395,7 +384,8 @@ end
395
384
 
396
385
  class Channel
397
386
  attr_reader(:name, :id, :fullname)
398
- attr_reader(:programmes)
387
+ attr_accessor(:programmes)
388
+ # attr_reader(:programmes)
399
389
  attr_accessor(:totalSpan)
400
390
 
401
391
  def initialize(id, fn)
@@ -417,39 +407,69 @@ class Channel
417
407
  end
418
408
 
419
409
  def number_of_programmes
420
- @programmes[@id].size
410
+ return @programmes[@id].size if @programmes[@id]
411
+ 0
421
412
  end
422
413
 
423
414
  def programme_at(i)
424
- @programmes[@id][i]
415
+ @programmes[@id][i] if @programmes[@id]
416
+ end
417
+
418
+ def addDummyProgramme(index, start, stop)
419
+ info "\n * Adding dummy programme: #{start}, #{stop}\n" +
420
+ " This could indicate a problem with your xmltv grabber.\n\n"
421
+
422
+ @programmes[@id][index,0] = Programme.new("No Data", "", @id,
423
+ start, stop, "", "",
424
+ "", false)
425
+ @programmes[@id][index].calculateTimeData
426
+ @programmes[@id][index].calculateProgrammeSlots
425
427
  end
426
428
 
427
429
  # Verify that each show's STOP date is the next show's START date
428
- # Should not be needed if tv_sort was used.
429
- # TODO: remove this once we can verify tv_sort was used on input data
430
+ # tv_sort doesn't fix all the start/stop issues...
430
431
  def verifyStopDate
431
- # @programmeList.each_index { |si|
432
- # s = @programmeList[si]
433
- # next_show = @programmeList[si.succ]
434
- # next if next_show == nil
435
- # next if s.times.fullStopTime == next_show.times.fullStartTime
436
- #
437
- # die "\n * A programme's stop time does not match the next \n" +
438
- # " * programme's start time. \n" +
439
- # " * Use tv_sort from the xmltv distribution to correct!\n" +
440
- # " * Exiting...\n\n" if !stop
441
- # }
442
- end
432
+ dummy_record = OpenStruct.new
433
+ dummy_progs = []
434
+
435
+ @programmes[@id].each_index { |si|
436
+ s = @programmes[@id][si]
437
+ next_show = @programmes[@id][si.succ]
438
+ next if next_show == nil
439
+ next if s.stopTime == next_show.startTime
440
+
441
+ if s.stopTime > next_show.startTime
442
+ die "\n * Whoa...this is bad!\n" +
443
+ " * Previous programme's stop time #{s.stopTime}, next\n" +
444
+ " * programme's start time #{next_show.startTime}\n\n"
445
+ end
443
446
 
444
- def calc_programme_slots
447
+ dummy_record.index = si + 1
448
+ dummy_record.start = s.stopTime
449
+ dummy_record.stop = next_show.startTime
450
+ dummy_progs << dummy_record
445
451
 
446
- @programmes[@id].each { |p|
447
- p.calculateSlots
452
+ addDummyProgramme(si + 1, s.stopTime, next_show.startTime)
453
+
454
+ # info " * Using tv_sort from the xmltv may correct this!\n" +
455
+ # " * Currently xmltv2html is unable to continue...\n\n" +
456
+ # " * Previous programme's stop time #{s.stopTime}, next\n" +
457
+ # " * programme's start time #{next_show.startTime}\n\n" +
458
+ # " * Previous programme's stop time #{s.stopTimeStr}, next\n" +
459
+ # " * programme's start time #{next_show.startTimeStr}\n\n"
448
460
  }
449
461
  end
450
462
 
463
+
464
+ def calc_programme_slots
465
+ # $stderr.print "\n# programmes=#{number_of_programmes}\n\n"
466
+ # @programmes[@id].each { |p|
467
+ # p.calculateSlots
468
+ # }
469
+ end
470
+
451
471
  def calculateSlots(slist)
452
- tinterval = @@options['channels_interval'] * 60 / @@options['time_divisor']
472
+ tinterval = @@options[:channels_interval] * 60 / @@options[:time_divisor]
453
473
  left = []
454
474
  right = slist.dup
455
475
  index = 0
@@ -503,8 +523,8 @@ class Channel
503
523
  times_counter = 1
504
524
  sindex = 0
505
525
  total = 0
506
- if @@options['channels_interval'] > 0
507
- tinterval = @@options['channels_interval'] * 60 / @@options['time_divisor']
526
+ if @@options[:channels_interval] > 0
527
+ tinterval = @@options[:channels_interval] * 60 / @@options[:time_divisor]
508
528
  else
509
529
  tinterval = 9999
510
530
  end
@@ -512,19 +532,40 @@ class Channel
512
532
 
513
533
  slist = Array.new
514
534
 
515
-
516
535
  s = @programmes[@id].first # 1st programme for this channel
536
+ # $stderr.print "### programmes=#{@programmes[@id].size}\n"
517
537
 
518
- if s.startSlot() > 0 # Missing programme at start
519
- dummy_span = s.startSlot() - span_counter
538
+ # $stderr.print "#{s.class}, startSlot=#{s.startSlot}\n"
539
+ # $stderr.print "startSlot=#{s.startTime},#{s.startTimeStr}\n"
540
+ if s.startSlot > 0 # Missing programme at start
541
+ dummy_span = s.startSlot - span_counter
520
542
  slist.push "D"+dummy_span.to_s
521
543
  end
522
544
 
523
545
  @programmes[@id].each { |s|
524
- slist.push "P"+s.spanSlots.to_s
546
+ # if s.title == "No Data" # Where we had to add dummy in middle
547
+ # slist.push "D"+s.spanSlots.to_s
548
+ # $stderr.print "push dummy...slots=#{s.spanSlots.to_s}\n"
549
+ # else
550
+ slist.push "P"+s.spanSlots.to_s # if s.spanSlots
551
+ # end
525
552
  }
526
553
 
527
- if @@options['channels_interval'] > 0
554
+ slist.each { |entry|
555
+ span = entry.slice(1..-1).to_i
556
+ total += span
557
+ }
558
+
559
+ dinterval = @@options[:total_hours] * 60 / @@options[:time_divisor]
560
+ #$stderr.print "totalhours=#{@@options[:total_hours]}\n"
561
+ #$stderr.print "total=#{total}, dinterval=#{dinterval}\n"
562
+ if total < dinterval # Not enough programmes' data at end
563
+ slist.push("D"+(dinterval - total).to_s)
564
+ end
565
+ #$stderr.print slist,"\n"
566
+
567
+ total = 0
568
+ if @@options[:channels_interval] > 0
528
569
  sl = calculateSlots(slist)
529
570
  while sl != slist
530
571
  slist = sl.dup
@@ -536,23 +577,11 @@ class Channel
536
577
  span = entry.slice(1..-1).to_i
537
578
  l.push entry
538
579
  total += span
539
- l.push("C0") if (total % tinterval) == 0 and @@options['channels_interval'] > 0
580
+ l.push("C0") if (total % tinterval) == 0 and @@options[:channels_interval] > 0
540
581
  }
541
582
 
542
583
  slist = l.unshift("C0") # Add left-most channel
543
- # Add left-most channel if not already there
544
- # slist = l
545
- # slist = l.unshift("C0") if l[0] != "C0"
546
- # slist = l.unshift("C0") if l[0, 1] != "C0"
547
- # $stderr.print slist[0, 3],"\n"
548
- # $stderr.print l[0, 3],"\n"
549
-
550
- dinterval = @@options['total_hours'] * 60 / @@options['time_divisor']
551
- if total < dinterval # Not enough programmes' data at end
552
- slist.push("D"+(dinterval - total).to_s)
553
- slist.push("C0") if dinterval % tinterval == 0
554
- end
555
-
584
+ #$stderr.print slist,"\n"
556
585
  slist
557
586
  end
558
587
 
@@ -572,7 +601,6 @@ class Channels < Hash
572
601
  end
573
602
 
574
603
  def calc_programmes_slots
575
-
576
604
  each { |id, c|
577
605
  c.calc_programme_slots
578
606
  }
@@ -608,8 +636,9 @@ class XmlTV
608
636
  @top_title = ""
609
637
  @HTML_title = ""
610
638
  @top_title += @srcInfoName + " :: " if @srcInfoName
611
- t1 = Time.parse(@firstShowStartDate)
612
- t2 = Time.parse(@lastShowStopDate)
639
+ t1 = Time.parse(@@options[:start_time])
640
+ t2 = Time.parse(@@options[:stop_time])
641
+ # t2 = Time.parse(@lastShowStopDate)
613
642
 
614
643
  @time_first = t1.strftime("%a %b %d %I:%M %p")
615
644
  @time_last = t2.strftime("%a %b %d %I:%M %p %Z")
@@ -642,6 +671,9 @@ class XmlTV
642
671
  }
643
672
  channels[id] = Channel.new(id, fn)
644
673
  }
674
+ if channels.size < 1
675
+ die "No channels in the input file!"
676
+ end
645
677
  end
646
678
 
647
679
  def parseProgrammes
@@ -653,60 +685,13 @@ class XmlTV
653
685
  rating=""
654
686
  cats = nil
655
687
  rerun = false
656
- ndesc = ""
657
688
  start = element.attributes["start"]
658
689
  stop = element.attributes["stop"]
659
- die "\n * No stop attribute in this programme...\n" +
660
- " * Use tv_sort from the xmltv distribution to correct!\n" +
661
- " * Exiting...\n\n" if !stop
690
+ dstart = ""
691
+ dstop= ""
662
692
 
663
693
  dstart = start[0..13]
664
- dstop = stop[0..13]
665
- ext = start[14..-1]
666
-
667
- # info "start_time=",@@options['start_time']
668
- # info "stop_time=",@@options['stop_time']
669
- # info "empty?" ,@@options['start_time'].empty?
670
- if not @@options['start_time'].empty?
671
- nstart = @@options['start_time'].clone
672
- nstart[10..11] = @@options['time_divisor'].to_s
673
-
674
- # If programme ends before the desired start time...
675
- # Adjust for the time_divisor (round_to_interval)
676
- if dstop < nstart
677
- # info "Delete programme - Desired start : #{@@options['start_time']}, "
678
- # $stderr.print "Delete programme - Desired start : #{$params.start_time}, "
679
- # $stderr.print "programme stop : #{dstop}\n"
680
- # $stderr.print "Old start time = #{$params.start_time}, new=#{nstart}\n"
681
- next
682
- end
683
- end
684
- # If programme starts after the desired stop time...
685
- if (not @@options['stop_time'].empty?) and (dstart >= @@options['stop_time'])
686
- # $stderr.print "Delete programme - Desired stop : #{$params.stop_time}, "
687
- # $stderr.print "programme start : #{dstart}\n"
688
- # info "programme start : #{dstart}\n"
689
- next
690
- end
691
-
692
- # If programme starts before the desired start time, change start
693
- if (not @@options['start_time'].empty?) and (dstart < @@options['start_time'])
694
- # info "Change Start - new start : "
695
- # $stderr.print "Change Start - new start : #{$params.start_time}, "
696
- # $stderr.print "old start: #{dstart}\n"
697
- # ndesc = "(" + start[8..9] + ":" + start[10..11] + ") "
698
-
699
- start = @@options['start_time'] + ext
700
- dstart = start[0..13]
701
- end
702
-
703
-
704
- # If programme ends after the desired stop time, change stop
705
- if (not @@options['stop_time'].empty?) and (dstop > @@options['stop_time'])
706
- stop = @@options['stop_time'] + ext
707
- # info "Change Stop - new stopt : "
708
- dstop = stop[0..13]
709
- end
694
+ dstop = stop[0..13] if stop
710
695
 
711
696
  @firstShowStartDate = dstart if @firstShowStartDate > dstart
712
697
  @lastShowStartDate = dstart if @lastShowStartDate < dstart
@@ -726,34 +711,126 @@ class XmlTV
726
711
  # Check to see if user want to use special CSS class for category
727
712
  # FIXME: What happens when more than 1 category is triggered?
728
713
  if e.name == "category"
729
- if @@options['categories'].has_key?(e.text())
730
- cats = @@options['categories'][e.text()];
714
+ if @@options[:categories].has_key?(e.text())
715
+ cats = @@options[:categories][e.text()];
731
716
  end
732
717
  end
733
718
  }
734
-
735
- title.gsub!(/[\"\'\`]/,'') # Remove "'`
736
- title = title.unpack("U*").pack("C*")
737
719
 
738
- subtitle = "" if not subtitle
739
- subtitle.gsub!(/[\"\'\`]/,'') # Remove "'`
740
-
741
- desc = "" if not desc
742
- desc.gsub!(/[\"\'\`]/,'') # Remove "'`
743
- desc = desc.unpack("U*").pack("C*")
744
- desc = ndesc + desc if ndesc
745
-
746
- rating = "" if not rating
747
- rating.gsub!(/[\"\'\`]/,'') # Remove "'`
748
- #$stderr.print "title=#{title}, desc=#{desc}, rating=#{rating}\n"
749
-
750
- p = Programme.new(
751
- title, subtitle, channel, start, stop, desc, rating, cats, rerun)
752
- # plist[channel] = p
753
- channels[channel] << p
720
+ channels[channel] << Programme.new(title, subtitle, channel,
721
+ start, stop, desc, rating,
722
+ cats, rerun)
723
+ }
724
+
725
+ channels.each { |id, c|
726
+ if c.number_of_programmes < 1
727
+ die "No programmes for channel #{id} in the input file!"
728
+ end
754
729
  }
755
730
  end
756
731
 
732
+ # Set :start_time and :stop_time if needed.
733
+ # Adjust start/stop_time to round to next hour
734
+ # Add stop time, should be very last programme stop time.
735
+ # Correct start, stop times due to --starttime, --stoptime
736
+ # Remove programmes that are too short
737
+ # Remove programmes which stop before --starttime
738
+ # Remove programmes which start after --stoptime
739
+ def filterProgrammes
740
+ # $stderr.print "@firstShowStartDate=#{@firstShowStartDate}\n"
741
+ # $stderr.print "@lastShowStartDate =#{@lastShowStartDate}\n"
742
+ # $stderr.print "@lastShowStopDate =#{@lastShowStopDate}\n"
743
+
744
+ # Set if --starttime= nor --stoptime= not given.
745
+ if (@@options[:start_time].empty?)
746
+ @@options[:start_time] = @firstShowStartDate
747
+ end
748
+ if (@@options[:stop_time].empty?)
749
+ @@options[:stop_time] = @lastShowStopDate
750
+ end
751
+
752
+ # Force start/stop time on hour
753
+ @@options[:start_time][10,4] = "0000"
754
+
755
+ if @@options[:stop_time][10,2] != "00"
756
+ hour = (@@options[:stop_time][8,2]).to_i + 1
757
+ if hour > 23 # Next day
758
+ pstop = Time.parse(@@options[:stop_time]) + (3600)
759
+ @@options[:stop_time] = pstop.strftime("%Y%m%d%H%M%S")
760
+ @@options[:stop_time][12,2] = "00"
761
+ end
762
+ # FIXME: Below still needed?
763
+ @@options[:stop_time][8,2] = hour.to_s.rjust(2).sub(/\s/,'0') if hour < 10
764
+ end
765
+ @@options[:stop_time][10,4] = "0000"
766
+
767
+
768
+ channels = Channels.instance
769
+
770
+ channels.each { |id, c|
771
+ programmes = c.programmes
772
+ # $stderr.print "\n# programmes=#{c.number_of_programmes}\n\n"
773
+
774
+ programmes.each { | id, p|
775
+ delete_indicies = []
776
+ p.each_with_index { |programme, index|
777
+
778
+ if !programme.stopTimeStr
779
+ programme.setStopTime @@options[:stop_time]
780
+ end
781
+
782
+ dstart = programme.startTimeStr
783
+ dstop = programme.stopTimeStr
784
+
785
+ # If programme ends before the desired start time...drop it.
786
+ nstart = @@options[:start_time].clone
787
+ nstart[10..11] = @@options[:time_divisor].to_s
788
+ if dstop < nstart
789
+ # $stderr.print "#{index}, programme ends #{dstop} before start #{nstart}\n"
790
+ # p.delete programme
791
+ # p = p.compact
792
+ delete_indicies << index
793
+ next
794
+ end
795
+
796
+ # If programme starts after the desired stop time...drop it.
797
+ if (dstart >= @@options[:stop_time])
798
+ # $stderr.print "#{index}, programme starts #{dstart} after stoptime #{@@options[:stop_time]}\n"
799
+ # p.delete programme
800
+ # p = p.compact
801
+ delete_indicies << index
802
+ next
803
+ end
804
+
805
+ # If programme starts before the desired start time, change it.
806
+ if (dstart < @@options[:start_time])
807
+ programme.setStartTime @@options[:start_time]
808
+ end
809
+
810
+ # If programme stops after the desired stop time, change it.
811
+ if (dstop > @@options[:stop_time])
812
+ programme.setStopTime @@options[:stop_time]
813
+ end
814
+
815
+ programme.calculateTimeData
816
+ programme.calculateProgrammeSlots
817
+ if programme.spanSlots < 1
818
+ # $stderr.print "span slot=#{programme.spanSlots}\n"
819
+ delete_indicies << index
820
+ next
821
+ end
822
+ }
823
+
824
+ # Delete programme's in reverse order
825
+ delete_indicies.reverse_each { |i|
826
+ c.programmes[id].delete_at i
827
+ c.programmes[id].compact!
828
+ }
829
+ c.verifyStopDate
830
+ # $stderr.print "# programmes=#{c.number_of_programmes}\n"
831
+ }
832
+ }
833
+ end
757
834
 
758
835
  end
759
836
 
@@ -772,33 +849,22 @@ class XMLTV2HTML2
772
849
  @xml.parseChannels
773
850
  @xml.parseProgrammes
774
851
 
852
+ @xml.filterProgrammes
775
853
 
776
- @@options['start_date'] = @xml.firstShowStartDate
777
- @@options['stop_date'] = @xml.lastShowStopDate
854
+ #$stderr.print "start_time=#{@@options[:start_time]}\n"
855
+ #$stderr.print "stop_time= #{@@options[:stop_time]}\n"
778
856
 
779
- # Force start/stop time on hour
780
- @@options['start_date'][10,4] = "0000"
781
-
782
- # info "start_date=",@@options['start_date']
783
- # info "stop_date= ",@@options['stop_date']
784
- if @@options['stop_date'][10,2] != "00"
785
- hour = (@@options['stop_date'][8,2]).to_i + 1
786
- if hour > 23
787
- $stderr.print "yuck #{hour}\n"
788
- end
789
- @@options['stop_date'][8,2] = hour.to_s.rjust(2).sub(/\s/,'0')
790
- end
791
- @@options['stop_date'][10,4] = "0000"
857
+ pstart = Time.parse(@@options[:start_time])
792
858
 
793
- pstart = Time.parse(@@options['start_date'])
794
- pstop = Time.parse(@@options['stop_date'])
795
- @@options['total_hours'] = ((pstop - pstart) / 3600).to_i
859
+ pstop = Time.parse(@@options[:stop_time])
860
+ @@options[:total_hours] = ((pstop - pstart) / 3600).to_i
796
861
 
862
+ #$stderr.print " hours #{@@options[:total_hours]}\n"
797
863
  channels = Channels.instance
798
864
  channels.calc_programmes_slots
799
865
 
800
- fdate = @@options['start_date'][0,8]
801
- ldate = @@options['stop_date'][0,8]
866
+ fdate = @@options[:start_time][0,8]
867
+ ldate = @@options[:stop_time][0,8]
802
868
 
803
869
  @xml.setTitle(@dates)
804
870
 
@@ -824,7 +890,7 @@ class XMLTV2HTML2
824
890
 
825
891
  @out.doctype
826
892
  @out.header(@xml.HTML_title)
827
- generatePopups if @@options['use_programme_popup']
893
+ generatePopups if @@options[:use_programme_popup]
828
894
  @out.text_before_table(@xml.top_title)
829
895
  @out.table_start
830
896
  @out.table_times
@@ -836,6 +902,7 @@ class XMLTV2HTML2
836
902
  @out.outputChannelBegin
837
903
  slot_list = c.createSlotList
838
904
  next unless slot_list
905
+
839
906
  i = 0
840
907
  pi = -1
841
908
  slot_list.each { |entry|
@@ -848,14 +915,26 @@ class XMLTV2HTML2
848
915
  sindex += 1
849
916
  pi += 1
850
917
  prog = c.programme_at(pi)
918
+
919
+ # Where we had to add dummy in middle
920
+ if prog.title == "No Data"
921
+ @out.outputDummyProgramme(span)
922
+ next
923
+ end
924
+
851
925
  @out.outputProgramme(prog, sindex, span)
852
- # @out.outputProgramme(c.programme_at(pi), sindex, span)
853
- if @@options['use_favorites'] and @@options['output_favorites'] and @@options['favorites'].include?(prog.title)
926
+ if @@options[:use_favorites] and @@options[:output_favorites] and @@options[:favorites].include?(prog.title)
854
927
  #$stderr.print "found a fav #{prog.title}\n"
855
928
  favorites_list << prog
856
929
  end
857
930
  when "Q" # Use previous Programme's info
858
- @out.outputProgramme(c.programme_at(pi), sindex, span)
931
+ prog = c.programme_at(pi)
932
+ # Where we had to add dummy in middle
933
+ if prog.title == "No Data"
934
+ @out.outputDummyProgramme(span)
935
+ next
936
+ end
937
+ @out.outputProgramme(prog, sindex, span)
859
938
  when "C"
860
939
  @out.outputChannel(c)
861
940
  else
@@ -864,8 +943,8 @@ class XMLTV2HTML2
864
943
  i += 1
865
944
  }
866
945
  @out.outputChannelEnd
867
- if @@options['times_interval'] > 0 and
868
- ((times_counter % @@options['times_interval']) == 0)
946
+ if @@options[:times_interval] > 0 and
947
+ ((times_counter % @@options[:times_interval]) == 0)
869
948
  @out.table_times
870
949
  end
871
950
  times_counter += 1
@@ -907,11 +986,11 @@ class Html
907
986
  print '<title>'
908
987
  print title if title
909
988
  print '</title>'; nl
910
- print '<link rel="stylesheet" href="', @@options['css_filename']
989
+ print '<link rel="stylesheet" href="', @@options[:css_filename]
911
990
  print '" type="text/css">'; nl
912
991
 
913
- if @@options['use_programme_popup']
914
- if @@options['programme_popup_method'] == "DHTML"
992
+ if @@options[:use_programme_popup]
993
+ if @@options[:programme_popup_method] == "DHTML"
915
994
  print '<script language="JavaScript1.2" src="popup.js" type="text/javascript"></script>'; nl
916
995
  else
917
996
  print '<script language="JavaScript1.2" type="text/javascript">'
@@ -936,17 +1015,17 @@ class Html
936
1015
 
937
1016
  # Styles
938
1017
  print 'Style[1]=['
939
- print '"', @@options['popup_title_color'], '",'
940
- print '"', @@options['popup_body_color'], '",'
941
- print '"', @@options['popup_title_background_color'], '",'
942
- print '"', @@options['popup_body_background_color'], '",'
1018
+ print '"', @@options[:popup_title_color], '",'
1019
+ print '"', @@options[:popup_body_color], '",'
1020
+ print '"', @@options[:popup_title_background_color], '",'
1021
+ print '"', @@options[:popup_body_background_color], '",'
943
1022
  print '"","","","",'
944
- print '"', @@options['popup_title_font'], '",'
945
- print '"', @@options['popup_body_font'], '",'
1023
+ print '"', @@options[:popup_title_font], '",'
1024
+ print '"', @@options[:popup_body_font], '",'
946
1025
  print '"center","",'
947
- print '"', @@options['popup_title_font_size'], '",'
948
- print '"', @@options['popup_body_font_size'], '",'
949
- print @@options['popup_body_width'], ','
1026
+ print '"', @@options[:popup_title_font_size], '",'
1027
+ print '"', @@options[:popup_body_font_size], '",'
1028
+ print @@options[:popup_body_width], ','
950
1029
  print '"",'
951
1030
  print '3,' # Border width
952
1031
  print '10,' # Padding around body text
@@ -961,9 +1040,9 @@ class Html
961
1040
  def outputPopupDescs(c, cindex)
962
1041
  # The descriptions go here...Text[#]=["title","text"]
963
1042
  c.programmes[c.id()].each { |s|
964
- title = @@options['popup_title_format'].sub(/\%T/, s.title)
1043
+ title = @@options[:popup_title_format].sub(/\%T/, s.title)
965
1044
  title.sub!(/\%R/, s.rating)
966
- desc = @@options['popup_body_format'].gsub(/%T/, s.title)
1045
+ desc = @@options[:popup_body_format].gsub(/%T/, s.title)
967
1046
  desc.sub!(/\%S/, s.subtitle)
968
1047
  if (s.previouslyShown) # rerun
969
1048
  desc.sub!(/\%P/, "(R)")
@@ -993,32 +1072,32 @@ class Html
993
1072
  print text
994
1073
  print '</h3></center>'; nl
995
1074
  end
996
- if @@options['url_prev']
1075
+ if @@options[:url_prev]
997
1076
  print '<a class="links" href="'
998
- print @@options['url_prev']
1077
+ print @@options[:url_prev]
999
1078
  print '"><<< Previous</a> | '
1000
1079
  end
1001
- if @@options['url_next']
1080
+ if @@options[:url_next]
1002
1081
  print '<a class="links" href="'
1003
- print @@options['url_next']
1082
+ print @@options[:url_next]
1004
1083
  print '">Next >>></a>'
1005
1084
  end
1006
1085
  end
1007
1086
 
1008
1087
  def text_after_table
1009
- if @@options['url_prev']
1088
+ if @@options[:url_prev]
1010
1089
  print '<a class="links" href="'
1011
- print @@options['url_prev']
1090
+ print @@options[:url_prev]
1012
1091
  print '"><<< Previous</a> | '
1013
1092
  end
1014
- if @@options['url_next']
1093
+ if @@options[:url_next]
1015
1094
  print '<a class="links" href="'
1016
- print @@options['url_next']
1095
+ print @@options[:url_next]
1017
1096
  print '">Next >>></a>'
1018
1097
  end
1019
1098
  print '<br />'
1020
1099
  outputInfo
1021
- outputLinks if @@options['output_links']
1100
+ outputLinks if @@options[:output_links]
1022
1101
  end
1023
1102
 
1024
1103
  def table_start
@@ -1036,7 +1115,7 @@ class Html
1036
1115
  def outputDate
1037
1116
  days = @hours/24
1038
1117
  colspan = 96
1039
- colspan += 96 / @@options['channels_interval'] if @@options['channels_interval'] > 0
1118
+ colspan += 96 / @@options[:channels_interval] if @@options[:channels_interval] > 0
1040
1119
 
1041
1120
  print '<tr class="date">'; nl
1042
1121
  (0 .. days-1).each { |d|
@@ -1046,12 +1125,12 @@ class Html
1046
1125
  end
1047
1126
 
1048
1127
  def table_times
1049
- intervals = 60 / @@options['time_divisor']
1128
+ intervals = 60 / @@options[:time_divisor]
1050
1129
 
1051
1130
 
1052
1131
  # Need hour to start.... we'll force it to be on an hour later
1053
- starting_day = @@options['start_date'][6,2].to_i
1054
- starting_hour = @@options['start_date'][8,2].to_i
1132
+ starting_day = @@options[:start_time][6,2].to_i
1133
+ starting_hour = @@options[:start_time][8,2].to_i
1055
1134
  # $stderr.print "Day to start: #{starting_day}\n"
1056
1135
  # $stderr.print "Hour to start: #{starting_hour}\n"
1057
1136
  # $stderr.print "Total hours: #{$params.total_hours}\n"
@@ -1060,13 +1139,13 @@ class Html
1060
1139
  output_channel_space
1061
1140
 
1062
1141
  cs = 0
1063
- (starting_hour .. starting_hour + @@options['total_hours'] - 1).each { |h|
1142
+ (starting_hour .. starting_hour + @@options[:total_hours] - 1).each { |h|
1064
1143
  (0 .. intervals-1).each { |hh|
1065
1144
  print '<td>';
1066
- printf "%02d", hh * @@options['time_divisor']; print '</td>';
1145
+ printf "%02d", hh * @@options[:time_divisor]; print '</td>';
1067
1146
  }
1068
1147
  cs += 1
1069
- output_channel_space if @@options['channels_interval'] > 0 and cs % @@options['channels_interval'] == 0
1148
+ output_channel_space if @@options[:channels_interval] > 0 and cs % @@options[:channels_interval] == 0
1070
1149
  }
1071
1150
  print '</tr>'; nl
1072
1151
 
@@ -1074,17 +1153,17 @@ class Html
1074
1153
  output_channel_space
1075
1154
  days = @hours/24
1076
1155
  cs = 0
1077
- cdate = Time.parse(@@options['start_date'])
1156
+ cdate = Time.parse(@@options[:start_time])
1078
1157
 
1079
- (starting_hour .. starting_hour + @@options['total_hours'] - 1).each { |hi|
1158
+ (starting_hour .. starting_hour + @@options[:total_hours] - 1).each { |hi|
1080
1159
  h = hi % 24
1081
1160
  print '<td colspan="',intervals,'" class="time">';
1082
1161
 
1083
- if @@options['output_date_in_time']
1162
+ if @@options[:output_date_in_time]
1084
1163
  nl; print '<table width="100%" border="0" cellpadding="0">'; nl
1085
1164
  print '<tr><td align="left" class="time">';
1086
1165
  end
1087
- if @@options['time_format_12']
1166
+ if @@options[:time_format_12]
1088
1167
  if h < 12
1089
1168
  out = "#{h} am"
1090
1169
  else
@@ -1095,16 +1174,16 @@ class Html
1095
1174
  out = sprintf "%02d", h
1096
1175
  end
1097
1176
  print out
1098
- if @@options['output_date_in_time']
1177
+ if @@options[:output_date_in_time]
1099
1178
  print '<td align="right" class="date_in_time">';
1100
- print cdate.strftime(@@options['date_format'])
1179
+ print cdate.strftime(@@options[:date_format])
1101
1180
  print '</td></tr>'; nl; print '</table></td>'; nl
1102
1181
  else
1103
1182
  print '</td>';
1104
1183
  end
1105
1184
  cs += 1
1106
1185
  cdate += 3600 # Add 1 hour
1107
- output_channel_space if @@options['channels_interval'] > 0 and cs % @@options['channels_interval'] == 0
1186
+ output_channel_space if @@options[:channels_interval] > 0 and cs % @@options[:channels_interval] == 0
1108
1187
  }
1109
1188
  print '</tr>'; nl
1110
1189
  end
@@ -1125,7 +1204,7 @@ class Html
1125
1204
  end
1126
1205
 
1127
1206
  def outputProgramme(s, index, slots)
1128
- return if s.spanSlots == 0 # Invalid programme - too short
1207
+ return if !s or s.spanSlots == 0 # Invalid programme - too short
1129
1208
  if slots > 0
1130
1209
  print '<td colspan="', slots, '" class="'
1131
1210
  else
@@ -1133,7 +1212,7 @@ class Html
1133
1212
  end
1134
1213
 
1135
1214
  # Favorites override category.
1136
- if @@options['use_favorites'] and @@options['favorites'].include?(s.title)
1215
+ if @@options[:use_favorites] and @@options[:favorites].include?(s.title)
1137
1216
  print 'favorite">'
1138
1217
  elsif s.category
1139
1218
  print s.category,'">'
@@ -1141,9 +1220,9 @@ class Html
1141
1220
  print 'programme">'
1142
1221
  end
1143
1222
  # Styles : 12=right; 1=center; 2=left; 3=float
1144
- if @@options['use_programme_popup']
1223
+ if @@options[:use_programme_popup]
1145
1224
  if s.popupIndex >= 0
1146
- if @@options['programme_popup_method'] == "DHTML"
1225
+ if @@options[:programme_popup_method] == "DHTML"
1147
1226
  print '<a onmouseover="stm(Text[', s.popupIndex
1148
1227
  print '],Style[1])" onmouseout="htm()">'; nl
1149
1228
  else
@@ -1182,11 +1261,11 @@ class Html
1182
1261
  outputProgramme(p, p.popupIndex, 1)
1183
1262
 
1184
1263
  print '<td align="center">'; nl
1185
- print p.times.fullStartTime.strftime("%a %b %d %I:%M %p")
1264
+ print p.startTime.strftime("%a %b %d %I:%M %p")
1186
1265
  print '</td>'; nl
1187
1266
 
1188
1267
  print '<td align="center">'; nl
1189
- print p.times.fullStopTime.strftime("%a %b %d %I:%M %p")
1268
+ print p.stopTime.strftime("%a %b %d %I:%M %p")
1190
1269
  print '</td>'; nl
1191
1270
 
1192
1271
  print '</tr>'; nl