#!/usr/pkg/bin/ruby24
#
#  x11rec - a very ad hoc X11 capture software which creates movie!
#
# USAGE: 
#
#   % x11rec foo.gif  # creates animation GIF
#   % x11rec foo.mng  # creates MNG
#
# REQUIREMENTS:
#
#   * ImageMagick - to create MNG or animation GIF movies.
#   * xwd         - to capture window's image. x11rec employs it highly!
#   * xwininfo    - to get window's id.
#
# Copyright (C) 2001 Satoru Takabayashi <satoru@namazu.org> 
#     All rights reserved.
#     This is free software with ABSOLUTELY NO WARRANTY.
#
# You can redistribute it and/or modify it under the terms of 
# the GNU General Public License version 2.
#

require 'getopts'

module X11rec
  VERSION = 0.3
end

class Xrecorder
  def initialize (filename)
    @filename = filename
    @frames = 0
    @id = nil
    @start_time = nil
    @finish_time = nil
    @tmpprefix = "xrec.tmp.#{$$}"
    STDOUT.sync = true
  end

  def target
    $stderr.puts "** Select an X window with a mouse. **" 
    IO.popen("/usr/X11R7/bin/xwininfo").each do |line|
      if /id: (\S+)/ =~ line then
	@id = $1
      end
    end
    printf "id: %s\n", id
  end

  def record
    @start_time = Time.new.localtime.to_i
    $stderr.puts "** Hit Ctrl+Z to finish the recording. **"
    while true
      tmp1 = sprintf "%s.1.%06d", @tmpprefix, @frames # may be broken.
      tmp2 = sprintf "%s.2.%06d", @tmpprefix, @frames # safe to use.
      system "/usr/X11R7/bin/xwd -silent -id #{@id} > #{tmp1}"
      File.rename tmp1, tmp2
      @frames += 1
      printf "frames: %d\r", @frames
    end
  end

  def convert
    # -delay <1/100ths of a second>
    #        display the next image after pausing.
    delay = ((@finish_time - @start_time).to_f / @frames * 100).to_i

    tmpgif1 = "#{@tmpprefix}.1.gif"
    tmpgif2 = "#{@tmpprefix}.2.gif"

    files = Dir.glob("#{@tmpprefix}.2.*")
    files.each_with_index do |file, i|
      $stderr.printf "converting each xwd file into a gif file: %d/%d\r",
	i + 1, files.length
      system "/usr/pkg/bin/convert #{file} #{file}.gif"
    end
    puts

    $stderr.puts "creating the resulting movie file..."
    system "/usr/pkg/bin/gifsicle --colors 256 -O2 --delay #{delay} #{@tmpprefix}.2.*.gif > #{tmpgif2}"

    if /^(.*)\.mng$/ =~ @filename then
      # create MNG with ImageMagick if needed.
      system "/usr/pkg/bin/convert #{tmpgif2} #{@filename}"
    else
      # just rename the temporary file.
      File.rename tmpgif2, @filename
    end
  end

  def clean
    $stderr.puts "removing temporary files..."
    system "rm -f #{@tmpprefix}.1.*"
    system "rm -f #{@tmpprefix}.2.*"
  end

  def finalize
    @finish_time = Time.new.localtime.to_i
    recording_time = (@finish_time - @start_time)
    fps = @frames / recording_time.to_f
    puts
    printf "time: %d sec.\n", recording_time
    printf "fps: %.2f\n", fps

    convert()
    clean()

    printf "size: %d bytes\n", File.size(@filename)
    $stderr.puts "done."
  end
end

def print_usage
  puts "x11rec <filename>"
  puts "  % x11rec foo.gif - create an animation GIF movie."
  puts "  % x11rec foo.mng - create an MNG movie."
end

if ARGV.length != 1 then
  print_usage
  exit 1
end

filename = ARGV[0]
r = Xrecorder.new(filename)

trap('TSTP') do
  r.finalize
  exit 0
end

r.target
r.record

