trecs 0.0.1.alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f6e8706df641c011fc594a3589b732af9903e583
4
+ data.tar.gz: 55584a0ad79f7860e323e92717158cecd52b495d
5
+ SHA512:
6
+ metadata.gz: 87c2377954222bf2af45037321ff28fe74a9ab8a302d0b78e8f3391f08fc2d6a3d07b1e31e38e32c68d64869f73558ee58131470cce8142d704148221623b622
7
+ data.tar.gz: c4118a76ee41f5c279d0b911a19772fdb8953319c7f7d4b310fbd51e15855f793daab5486c44610b85d1bbd14d439a1b4287d4a08e66598488e1696aa544ccf7
data/.bundle/config ADDED
@@ -0,0 +1 @@
1
+ --- {}
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ tmp/
2
+ doc/todo.org
3
+ /sandbox/*
4
+ /README.html
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.spec ADDED
File without changes
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ rvm:
2
+ - 2.1.0
3
+ - 2.1.1
4
+ - 2.1.2
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "https://rubygems.org"
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,38 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ trecs (0.0.1.alpha)
5
+ rubyzip (~> 1.0.0)
6
+ trollop (~> 2.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ diff-lcs (1.2.4)
12
+ given_core (3.5.4)
13
+ sorcerer (>= 0.3.7)
14
+ rake (10.3.2)
15
+ rspec (2.13.0)
16
+ rspec-core (~> 2.13.0)
17
+ rspec-expectations (~> 2.13.0)
18
+ rspec-mocks (~> 2.13.0)
19
+ rspec-core (2.13.1)
20
+ rspec-expectations (2.13.0)
21
+ diff-lcs (>= 1.1.3, < 2.0)
22
+ rspec-given (3.5.4)
23
+ given_core (= 3.5.4)
24
+ rspec (>= 2.12)
25
+ rspec-mocks (2.13.1)
26
+ rubyzip (1.0.0)
27
+ sorcerer (1.0.2)
28
+ trollop (2.0)
29
+
30
+ PLATFORMS
31
+ ruby
32
+
33
+ DEPENDENCIES
34
+ bundler (~> 1.6)
35
+ rake
36
+ rspec (~> 2.12)
37
+ rspec-given (~> 3.5.4)
38
+ trecs!
data/LICENCE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Federico Iachetti
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.org ADDED
@@ -0,0 +1,44 @@
1
+ #+TITLE: README.org
2
+ #+AUTHOR: Federico Martín Iachetti
3
+ #+EMAIL: iachetti.federico@gmail.com
4
+ #+LANGUAGE: en
5
+ #+OPTIONS: H:3 num:t toc:t \n:nil @:t ::t |:t ^:nil -:t f:t *:t <:t
6
+ #+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc
7
+ #+INFOJS_OPT: view:nil toc:nil ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js
8
+ #+EXPORT_SELECT_TAGS: export
9
+ #+EXPORT_EXCLUDE_TAGS: noexport
10
+
11
+ #+BEGIN_EXAMPLE
12
+ __________
13
+ / o \
14
+ | ____|
15
+ | |___
16
+ | ____/
17
+ _| |
18
+ _| |===E
19
+ /\ _| ===E
20
+ \ \___| |
21
+ \___ /
22
+ _____ ____ _/
23
+ |_ _| _ \ ___ ___ ___
24
+ | | | |_) / _ \/ __/ __|
25
+ | | | _ < __/ (__\__ \
26
+ |_| |_| \_\___|\___|___/
27
+
28
+ #+END_EXAMPLE
29
+ * T-Recs
30
+ Text Recordings.
31
+
32
+ Record screencasts in plain text.
33
+
34
+ ** Just an Idea
35
+ The idea is to create a tool that allows to record text somehow and then reproduce it just as you would reproduce a video.
36
+
37
+ ** Some specifications
38
+
39
+ - It should have controls (play, pause, ffw, rew, stop, rec)
40
+ - It should have some kind of timestamp, so it can be synchronized with other resources
41
+ - The other resources:
42
+ + Audio track
43
+ + Video track
44
+ + Browser extension (so, if you are recording the development of a web page, you could see in a browser the current snapshot of the page)
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
data/bin/trecs ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.expand_path("../../lib", __FILE__))
4
+
5
+ require "trollop"
6
+
7
+ require "timestamps"
8
+ require "players/zip_file_player"
9
+
10
+ options = Trollop::options do
11
+ opt :file_name, "File to process", short: 'f', type: String
12
+ opt :time, "Frame at time", short: 't', type: String
13
+ opt :current_time, "Returns the current playback time", short: 'c'
14
+ opt :step, "Time im ms between frames", short: 's', default: 100
15
+
16
+ opt :timestamps, "Returns the list of existing frame timestamps"
17
+
18
+ opt :testing, "Ticks without waiting. Use this option only for testing purpuses"
19
+ end
20
+
21
+ file_name = options[:file_name]
22
+ if file_name
23
+ if File.exist?(file_name)
24
+ player = TRecs::ZipFilePlayer.new(options)
25
+ if options[:timestamps]
26
+ p player.timestamps
27
+ else
28
+ player.play
29
+ end
30
+ else
31
+ puts "File #{file_name} does not exist."
32
+ end
33
+ end
data/bin/trecs_message ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.expand_path("../../lib", __FILE__))
4
+
5
+ require "trollop"
6
+
7
+ require "recorders/message_recorder"
8
+
9
+ options = Trollop::options do
10
+ opt :file_name, "File to process", short: 'f', type: String
11
+ opt :message, "Message to record", short: 'm', type: String
12
+ opt :step, "Time between frames in milliseconds", short: 's', default: 100
13
+ end
14
+
15
+ if options[:file_name]
16
+ recorder = TRecs::MessageRecorder.new(options)
17
+ recorder.record
18
+ else
19
+ puts "Please give a file name"
20
+ end
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.expand_path("../../lib", __FILE__))
4
+
5
+ require "trollop"
6
+
7
+ require "recorders/ttyrec_recorder"
8
+
9
+ options = Trollop::options do
10
+ # opt :input_file, "File to process", short: 'i', type: String
11
+ opt :output_file, "Output file", short: 'o', type: String
12
+ end
13
+
14
+ options[:input_file] ||= "/tmp/ttyrecord"
15
+
16
+ if options[:output_file] # && options[:input_file]
17
+ puts "Recording ..."
18
+ options[:height], options[:width] = `stty size`.split(" ").map(&:to_i)
19
+ system "ttyrec #{options[:input_file]}"
20
+ recorder = TRecs::TtyrecRecorder.new(options)
21
+ recorder.record
22
+ puts "Finish Recording ..."
23
+ else
24
+ puts "Please give an input and an output file file name"
25
+ end
data/doc/steps.org ADDED
@@ -0,0 +1,18 @@
1
+ #+OPTIONS: H:3 num:t toc:t \n:nil @:t ::t |:t ^:nil -:t f:t *:t <:t
2
+ #+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc
3
+ #+INFOJS_OPT: view:nil toc:nil ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js
4
+
5
+ * Crear el binario trecs
6
+ Ésto es para poder comenzar a testear con código que funcione de una
7
+ trecs reproduce un archivo *.trecs conformado por un zip y una serie de archivos que representan los frames
8
+
9
+ * Extraer Player en su propia clase
10
+ Hacer que el binario llame directamente a la clase
11
+
12
+ * Extraer todo lo relacionado con el formato en particular a una nueva clase
13
+ Extraer todo lo relacionado con el formato en particular a una nueva clase, dejando sólo lo relacionado con reproducir frames, timestamps en Player
14
+
15
+ * Crear clase Screen
16
+ Screen sería el lugar sonde va a ir a parar el frame para ser visualizado.
17
+ * Extraer todo lo posible del binario hacia player
18
+ Hacer que el binario sea una cáscara y que el player sea el verdadero "main"
data/lib/player.rb ADDED
@@ -0,0 +1,75 @@
1
+ require "timestamps"
2
+ require "screens/terminal_screen"
3
+
4
+ module TRecs
5
+ class Player
6
+ attr_reader :output
7
+
8
+ def initialize(time: nil, step: 100, output: TerminalScreen.new, testing: false, **options)
9
+ @current_time = time
10
+ @step = step
11
+ @ticks = time ? Array(time.to_i) : ticks
12
+ @output = output
13
+ @testing = testing
14
+ end
15
+
16
+ def play
17
+ ticks.each do |time|
18
+ play_frame(time)
19
+ sleep(sleep_time) unless testing
20
+ end
21
+ end
22
+
23
+ def tick(time=current_time)
24
+ self.current_time = time
25
+ get_frame(time)
26
+ end
27
+
28
+ def timestamps
29
+ @timestamps ||= get_timestamps.sort
30
+ end
31
+
32
+ def generate_ticks
33
+ ticks = [0]
34
+ curr = 0
35
+ while(curr < timestamps.last.to_i)
36
+ curr += step
37
+ ticks << curr
38
+ end
39
+ ticks
40
+ end
41
+
42
+ def ticks
43
+ @ticks ||= generate_ticks
44
+ end
45
+
46
+ def play_frame(time)
47
+ output.clear
48
+ output.puts tick(time_at(time))
49
+ end
50
+
51
+ def time_at(time)
52
+ Timestamps.new(timestamps).time_at(time)
53
+ end
54
+
55
+ private
56
+ attr_accessor :current_time
57
+ attr_reader :step
58
+ attr_reader :testing
59
+
60
+
61
+
62
+ def get_timestamps
63
+ []
64
+ end
65
+
66
+ def get_frame(time)
67
+ ""
68
+ end
69
+
70
+ def sleep_time
71
+ # TODO: Fix this to use the current time
72
+ @sleep_time ||= (step/1000.0)*0.8
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,56 @@
1
+ require "zip"
2
+ require "player"
3
+
4
+ module TRecs
5
+ class ZipFilePlayer < Player
6
+ include FileUtils
7
+
8
+ def initialize(file_name: "", **options)
9
+ @file_name = file_name
10
+
11
+ create_directory
12
+ extract_file
13
+
14
+ super(**options)
15
+ end
16
+
17
+ # this
18
+ def get_frame(time)
19
+ File.read(file_to_read(time))
20
+ end
21
+
22
+ # this
23
+ def get_timestamps
24
+ return [] unless file_name
25
+ Dir.glob("#{dir}/*").each.map do |line|
26
+ line[/\/(\d++)\Z/, 1].to_i
27
+ end
28
+ end
29
+
30
+ private
31
+ attr_reader :file_name
32
+ attr_reader :dir
33
+
34
+ def file_to_read(time)
35
+ file_array = []
36
+ file_array << @dir
37
+ file_array << "/"
38
+ file_array << time
39
+ file_to_read = file_array.join
40
+ end
41
+
42
+ def create_directory
43
+ @dir = Dir.mktmpdir
44
+ end
45
+
46
+ def extract_file
47
+ Zip::File.open(file_name) do |file|
48
+ file.each do |f|
49
+ f.extract "#{dir}/#{f.name}"
50
+ end
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+ end
data/lib/recorder.rb ADDED
@@ -0,0 +1,68 @@
1
+ module TRecs
2
+ class Recorder
3
+ attr_writer :current_time
4
+ attr_reader :step
5
+
6
+ def initialize(step: 100, **options)
7
+ @step = step
8
+ end
9
+
10
+ def next_timestamp
11
+ @current_time = -step unless @current_time
12
+ @current_time += step
13
+ end
14
+
15
+ def current_time(time=nil)
16
+ if time
17
+ @current_time = time
18
+ end
19
+ @current_time
20
+ end
21
+
22
+ def current_content(content=nil)
23
+ if content
24
+ @current_content = content
25
+ end
26
+ @current_content
27
+ end
28
+
29
+ def current_frame(time: next_timestamp, content:)
30
+ current_time(time)
31
+ current_content(content)
32
+
33
+ if previous_content != content
34
+ create_frame
35
+ self.previous_content = content
36
+ end
37
+ end
38
+
39
+ def record
40
+ start
41
+ perform_recording
42
+ finish
43
+ end
44
+
45
+ private
46
+ attr_accessor :recording
47
+ attr_accessor :previous_content
48
+ attr_reader :recording_strategy
49
+
50
+ def start
51
+ self.current_time = nil
52
+ self.recording = true
53
+ setup
54
+ end
55
+
56
+ def finish
57
+ render
58
+ self.recording = false
59
+ end
60
+
61
+ def create_frame
62
+ end
63
+
64
+ def perform_recording
65
+ recording_strategy.perform
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,18 @@
1
+ require "timestamps"
2
+
3
+ require "recorders/zip_file_recorder"
4
+ require "recording_strategies/incremental_recording_strategy"
5
+
6
+
7
+ module TRecs
8
+ class MessageRecorder < ZipFileRecorder
9
+ attr_reader :message
10
+
11
+ def initialize(message:, **options)
12
+ @message = message
13
+ @recording_strategy = IncrementalRecordingStrategy.new(recorder: self, message: message)
14
+ super(**options)
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ require "timestamps"
2
+
3
+ require "recorders/zip_file_recorder"
4
+ require "recording_strategies/ttyrec_recording_strategy"
5
+
6
+ module TRecs
7
+ class TtyrecRecorder < ZipFileRecorder
8
+ def initialize(input_file:, output_file:, **options)
9
+ @recording_strategy = TtyrecRecordingStrategy.new(recorder: self, file: input_file, **options)
10
+ super(file_name: output_file, **options)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,41 @@
1
+ require "zip"
2
+ require "recorder"
3
+
4
+ module TRecs
5
+ class ZipFileRecorder < Recorder
6
+ include FileUtils
7
+ def initialize(file_name:, **options)
8
+ super(**options)
9
+ @file_name = file_name
10
+ delete_file
11
+ end
12
+
13
+ private
14
+ attr_reader :file_name
15
+ attr_reader :frames
16
+
17
+ # this
18
+ def setup
19
+ @frames = {}
20
+ end
21
+
22
+ def render
23
+ Zip::File.open(file_name, Zip::File::CREATE) do |trecs_file|
24
+ frames.each do |timestamp, content|
25
+ Tempfile.open(timestamp.to_s) do |temp_file|
26
+ temp_file.write(content)
27
+ trecs_file.add(timestamp.to_s, temp_file)
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ def create_frame
34
+ frames[current_time] = current_content
35
+ end
36
+
37
+ def delete_file
38
+ rm file_name if File.exists? file_name
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,25 @@
1
+ require "recording_strategy"
2
+ module TRecs
3
+ class IncrementalRecordingStrategy < RecordingStrategy
4
+ def initialize(message:, **options)
5
+ @message = message
6
+ super(**options)
7
+ end
8
+
9
+ def perform
10
+ message.each_char.each_with_object("") do |current_char, current_msg|
11
+ current_msg << current_char
12
+
13
+ time = timestamp_for(current_msg)
14
+ content = current_msg.dup
15
+ recorder.current_frame(time: time, content: content)
16
+ end
17
+ end
18
+ private
19
+ attr_reader :message
20
+
21
+ def timestamp_for(message)
22
+ (message.size - 1) * recorder.step
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,30 @@
1
+ require "recording_strategy"
2
+ module TRecs
3
+ class TtyrecRecordingStrategy < RecordingStrategy
4
+ def initialize(file:, height: 24, width: 80, **options)
5
+ @file = File.new(file)
6
+ @frames = []
7
+ @full_output = ""
8
+ @height = height
9
+ @width = width
10
+ super
11
+ end
12
+
13
+ def perform
14
+ while !@file.eof?
15
+ sec, usec, len = @file.read(12).unpack('VVV')
16
+ @full_output << @file.read(len)
17
+
18
+ data_array = @full_output.each_line.to_a
19
+ height = data_array.size > @height ? @height : 0
20
+ frame = data_array[-height..-1].join
21
+
22
+ prev_timestamp ||= [ sec, usec ].join('.').to_f
23
+ curr_timestamp = [ sec, usec ].join('.').to_f
24
+ offset = ((curr_timestamp - prev_timestamp)*1000).to_i
25
+
26
+ recorder.current_frame(time: offset, content: frame)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,10 @@
1
+ module TRecs
2
+ class RecordingStrategy
3
+ def initialize(recorder:, **optionsx)
4
+ @recorder = recorder
5
+ end
6
+
7
+ private
8
+ attr_reader :recorder
9
+ end
10
+ end
@@ -0,0 +1,22 @@
1
+ require "delegate"
2
+
3
+ module TRecs
4
+ class TerminalScreen < SimpleDelegator
5
+ def clear
6
+ puts "\e[H\e[2J"
7
+ end
8
+
9
+ def initialize
10
+ @obj = $stdout
11
+ super(@obj)
12
+ end
13
+
14
+ def __getobj__
15
+ @obj
16
+ end
17
+
18
+ def __setobj__(obj)
19
+ @obj = obj
20
+ end
21
+ end
22
+ end
data/lib/timestamps.rb ADDED
@@ -0,0 +1,22 @@
1
+ class Timestamps
2
+ attr_reader :collection
3
+
4
+ def initialize(collection)
5
+ @collection = collection
6
+ end
7
+
8
+ def time_at(time=0)
9
+ time = time.to_s.to_i
10
+ return 0 if collection.empty?
11
+ return collection.first if time <= collection.first
12
+ return collection.last if time >= collection.last
13
+ collection.each_cons(2) do |a, b|
14
+ if b == time
15
+ return b
16
+ end
17
+ if b > time
18
+ return a
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module TRecs
2
+ VERSION = "0.0.1.alpha"
3
+ end
@@ -0,0 +1,28 @@
1
+ require "fileutils"
2
+ require 'zip'
3
+
4
+ include FileUtils
5
+ def create_recording(file_name: "")
6
+ rm file_name if File.exists? file_name
7
+ recording_dir = "./frames"
8
+ rm_rf recording_dir
9
+ mkdir_p recording_dir
10
+
11
+ yield recording_dir
12
+
13
+ files_to_record = Dir.glob("#{recording_dir}/*")
14
+
15
+ Zip::File.open(file_name, Zip::File::CREATE) do |trecs_file|
16
+ files_to_record.each do |file_to_rec|
17
+ dest_file_name = File.basename(file_to_rec)
18
+ trecs_file.add(dest_file_name, file_to_rec)
19
+ end
20
+ end
21
+ rm_rf Dir.glob("#{recording_dir}")
22
+ end
23
+
24
+ def create_frame(content: "", time: 0)
25
+ File.open("./frames/#{time.to_i}", File::WRONLY|File::CREAT) do |f|
26
+ f << content
27
+ end
28
+ end
@@ -0,0 +1 @@
1
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
@@ -0,0 +1 @@
1
+ Lorem ipsum dolor sit amet.