11
class Progress < Gtk::ProgressBar
12
def initialize(parent, length, title)
16
#eventbox = Gtk::EventBox.new
18
window = Gtk::Window.new(Gtk::Window::TOPLEVEL)
20
window.set_size_request(400, 30)
21
window.transient_for=parent
26
window.deletable = false
33
parent_window.title = title
36
# if Gtk.events_pending?
37
# while Gtk.main_iteration
44
set_fraction(Float(@iteration) / @length)
47
# while (Gtk.events_pending?)
58
# if Gtk.events_pending?
64
class Player < Gtk::Builder
67
def initialize(fps, width, height, images, real_frames)
68
if images.class == Array
74
@images = Dir.glob(sprintf("saved_camera_images/%s/*.tif", images))
77
pixbuf = Gdk::Pixbuf.new(@images[0])
79
height = pixbuf.height
83
@real_frames = real_frames
85
size = @images.length * width * height / 1024 / 1024
87
@size = (size < 4096)?sprintf("%i MB", size):sprintf("%i GB", (Float(size)/1024).round)
98
add_from_file('player.glade')
99
connect_signals { |handler| method(handler) }
101
@player = get_object('player')
104
@player.title = sprintf("Current (%i frames, %s)", @images.length, @size)
105
elsif @session =~ /^(\d{8}_\d{6})(\.(.+))?$/ then
106
@player.title = sprintf("%s (%i frames, %s)", $2?$3:$1, @images.length, @size)
108
@player.title = sprintf("%s (%i frames, %s)", @session, @images.length, @size)
112
@area = get_object('draw')
113
@area.set_gl_capability(Gdk::GLConfig.new(Gdk::GLConfig::MODE_DEPTH | Gdk::GLConfig::MODE_DOUBLE | Gdk::GLConfig::MODE_RGB))
114
@area.set_size_request(width, height)
116
Gtk::Drag.source_set(@area,
117
Gdk::Window::BUTTON1_MASK,
118
[["frame-number", Gtk::Drag::TARGET_SAME_APP, 1]],
119
Gdk::DragContext::ACTION_COPY
122
from = get_object('from')
123
to = get_object('to')
126
@area.signal_connect("button-press-event") { |w, e|
127
if (e.event_type == Gdk::Event::BUTTON2_PRESS) then
128
widget = @input_field?to:from
129
widget.text = sprintf("%i", @framesel.value)
130
@input_field = !@input_field
134
[from, to].each { |widget|
135
Gtk::Drag.dest_set(widget,
136
Gtk::Drag::DEST_DEFAULT_MOTION | Gtk::Drag::DEST_DEFAULT_HIGHLIGHT,
137
[["frame-number", Gtk::Drag::TARGET_SAME_APP, 1]],
138
Gdk::DragContext::ACTION_COPY)
140
widget.signal_connect("drag-drop") { |w, dc, x, y, time|
141
w.text = sprintf("%i", @framesel.value)
145
@player.visible = true
147
@region = Gdk::Rectangle.new(0, 0, width, height)
149
@framesel = get_object('frame')
150
@framesel.set_range(1, @images.length)
153
frame_value_changed_cb(@framesel)
156
# Player window callbacks
157
def frame_value_changed_cb(widget)
158
@frame = widget.value
159
@area.window.invalidate(@region, false)
162
def frame_format_value_cb(widget, digits)
164
return @real_frames?sprintf('%i (%i)', val, @real_frames[val - 1]):sprintf('%i', val)
167
def play_clicked_cb(widget)
168
get_object('play').sensitive = false
172
@frame = 1 if @frame == @images.length
174
GLib::Timeout.add(@ms) {
175
if (@play) and (@frame < @images.length) then
176
@framesel.value = @frame + 1
179
get_object('play').sensitive = true
187
def forward_clicked_cb(widget)
188
if (@frame < @images.length) then
189
@framesel.value = @frame + 1
195
def back_clicked_cb(widget)
197
@framesel.value = @frame - 1
199
@framesel.value = @images.length - 1
203
def pause_clicked_cb(widget)
207
def draw_expose_event_cb(area, event)
209
Gdk::RGB.draw_gray_image(area.window, area.style.fg_gc(area.state), 0, 0, @width, @height, Gdk::RGB::DITHER_NORMAL, @images[@frame - 1], @width)
211
# image = ImageList.new(@images[@frame - 1]).first
212
pixbuf = Gdk::Pixbuf.new(@images[@frame - 1], @width, @height)
213
@area.window.draw_pixbuf(nil, pixbuf, 0, 0, 0, 0, @width, @height, Gdk::RGB::DITHER_NORMAL, 0, 0)
217
def save_images(name, progress)
218
if @memory and not @writed then
219
geometry = Magick::Geometry.new(@width, @height, nil, nil, Magick::AspectGeometry)
222
basename = (name =~ /([^\/]+)\.avi$/i)?$1:name
223
@session = sprintf("%02i%02i%02i_%02i%02i%02i.", time.year, time.month, time.day, time.hour, time.min, time.sec) + basename
224
FileUtils::mkdir_p('saved_camera_images/' + @session)
227
@images.each { |data|
228
img = Image.from_blob(data) {
235
img.write(sprintf("saved_camera_images/%s/PIC%09i.tif", @session, key))
238
progress.iteration if progress
246
if @memory and not @writed then
248
fs = Gtk::Dialog.new("Please select a name", @player, Gtk::Dialog::DESTROY_WITH_PARENT,
249
[ Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL ],
250
[ Gtk::Stock::OK, Gtk::Dialog::RESPONSE_ACCEPT ]
253
entry = Gtk::Entry.new
258
name = entry.text if response == Gtk::Dialog::RESPONSE_ACCEPT
263
progress = Progress.new(@player, @images.length, sprintf("Saving %i images (%s)", @images.length, @size))
266
save_images(name, progress)
278
def save_clicked_cb(widget)
282
def video_clicked_cb(widget)
283
FileUtils::mkdir_p("saved_camera_videos")
285
filter = Gtk::FileFilter.new
286
filter.name = "Video Files"
287
filter.add_pattern('*.avi')
289
fs = Gtk::FileChooserDialog.new("Please select a file to save", nil, Gtk::FileChooser::ACTION_SAVE, nil,
290
[ Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL ],
291
[ Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT ]
293
fs.current_folder = 'saved_camera_videos'
294
fs.add_filter(filter)
300
if response == Gtk::Dialog::RESPONSE_ACCEPT
301
name = name + '.avi' if name !~ /\.avi$/i
303
progress = Progress.new(@player, @images.length, sprintf("Saving %i images (%s)", @images.length, @size))
306
save_images(name, progress)
308
FileUtils::mkdir_p("temporary_camera_images/" + @session)
310
progress.title = sprintf("Converting %i images (%s)", @images.length, @size)
312
Dir.glob(sprintf("saved_camera_images/%s/*.tif", @session)) { |image_name|
313
output = image_name.sub(/saved_camera_images/, "temporary_camera_images")
314
output.sub!(/tif$/, "bmp")
316
image = Magick::ImageList.new(image_name)
323
progress.title = sprintf("Encoding %i images (%s)", @images.length, @size)
324
mplayer = open("|mencoder mf://temporary_camera_images/#{@session}/*.bmp -mf fps=#{@fps}:type=bmp -ovc x264 -x264encopts bitrate=3000 -o #{name} 2>/dev/null") { |pipe|
325
pipe.each("r") { |line|
326
progress.set_fraction(Float($1)/100) if line =~ /Pos:[^(]*\(\s*(\d+)%\)/
331
progress.title = "Cleaning temporary files"
332
FileUtils::remove_dir("temporary_camera_images/" + @session)
334
#system "./encode.sh \"#{name}\" \"#{@session}\" #{@fps}"
344
def cut_clicked_cb(widget)
346
from = Integer(get_object('from').text)
352
to = Integer(get_object('to').text)
354
to = @images.length - 1
357
from = 0 if (from < 0)
358
to = @images.length -1 if (to <= 0) or (to >= @images.length)
361
Player.new(@fps, @width, @height, @images[from..to], (@real_frames)?(@real_frames[from..to]):nil)
365
fs = Gtk::Dialog.new("Please select a name", @player, Gtk::Dialog::DESTROY_WITH_PARENT,
366
[ Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL ],
367
[ Gtk::Stock::OK, Gtk::Dialog::RESPONSE_ACCEPT ]
370
entry = Gtk::Entry.new
375
name = entry.text if response == Gtk::Dialog::RESPONSE_ACCEPT
380
session = sprintf("%02i%02i%02i_%02i%02i%02i.", time.year, time.month, time.day, time.hour, time.min, time.sec) + name
382
session = sprintf("%02i%02i%02i_%02i%02i%02i", time.year, time.month, time.day, time.hour, time.min, time.sec)
385
FileUtils::mkdir_p('saved_camera_images/' + session)
388
@images[from..to].each { |src|
390
dst = sprintf("saved_camera_images/%s/PIC%09i.tif", session, key)
391
FileUtils::ln(src, dst)
394
Player.new(@fps, @width, @height, session, (@real_frames)?(@real_frames[from..to]):nil)
398
def gtk_widget_delete(widget, ev)
405
# Generally we should somehow clean complete object, do it later
415
def gtk_widget_destroy(widget)
419
if $*.length > 0 then
420
player = Player.new(25, -1, -1, $*[0], nil)
422
#metaclass = class << player; self; end
423
#metaclass.send(:define_method, :gtk_widget_destroy) { Gtk.main_quit }
424
#player.gtk_widget_destroy(nil)
426
player.player.signal_connect('destroy') { Gtk.main_quit }