root/lang/ruby/partty/trunk/captty.rb @ 8952

Revision 8952, 1.7 kB (checked in by frsyuki, 5 years ago)

lang/ruby/partty: added Captty recording feature

Line 
1require 'zlib'
2
3module Captty
4
5        module FRAME
6                OUTPUT = 0
7                WINDOW_SIZE = 1
8                HEADER_SIZE = 8 + 1 + 2
9        end
10
11        module BLOCK
12                UNCOMPRESSED_FRAMES = 0
13                COMPRESSED_FRAMES = 1
14                HEADER_SIZE = 8 + 1 + 2
15        end
16
17        BLOCK_TIME_SPAN = 30   # seconds
18        MAX_BLOCK_SIZE = 1 << 19
19
20
21
22        class Recorder
23                def initialize(output_stream)
24                        @out = output_stream
25                        @block = ""
26                        @ftime = Time.now
27                        @btime = Time.now
28                end
29
30                def write(buf)
31                        append_frame(
32                                ftdiff_forward,
33                                buf,
34                                FRAME::OUTPUT
35                        )
36                end
37
38                def set_window_size(row, col)
39                        buf = [row, col].pack("vv")
40                        append_frame(
41                                ftdiff_forward,
42                                buf,
43                                FRAME::WINDOW_SIZE
44                        )
45                end
46
47                def flush
48                        reserve(MAX_BLOCK_SIZE+1)
49                end
50
51
52        private
53                def append_frame(ftdiff, buf, flag)
54                        reserve(FRAME::HEADER_SIZE + buf.length)
55                        @block << [ftdiff, flag, buf.length].pack("VCv")
56                        @block << buf
57                        buf
58                end
59
60                # ftdiff in microseconds
61                def ftdiff_forward
62                        n = Time.now
63                        ftdiff = ((n - @ftime).to_f * 1000 * 1000).to_i
64                        @ftime = n
65                        ftdiff
66                end
67
68                def reserve(length)
69                        n = Time.now
70                        if (n - @btime).to_i > BLOCK_TIME_SPAN ||
71                                @block.length + length > MAX_BLOCK_SIZE
72                                write_block( (n - @btime).to_i )
73                                @btime = n
74                                @block.slice!(0..-1)  # == @block.clear (1.9 feature)
75                        end
76                end
77
78                def write_block(btdiff)
79                        failed = false
80                        begin
81                                cblock = Zlib::Deflate.deflate(@block)
82                        rescue
83                                failed = true
84                        end
85                        failed = true   # FIXME  compression doesn't work?
86                        if !failed && cblock.length < @block.length
87                                write_block_data(BLOCK::COMPRESSED_FRAMES, btdiff, cblock)
88                        else
89                                write_block_data(BLOCK::UNCOMPRESSED_FRAMES, btdiff, @block)
90                        end
91                end
92
93                def write_block_data(flag, btdiff, data)
94                        @out.write [btdiff, flag, data.length].pack("vCV")
95                        @out.write @block
96                end
97        end
98
99end
100
Note: See TracBrowser for help on using the browser.