end
def get_mem
- IO.readlines('/proc/self/status').join =~ /VmRSS.*?(\d+)\s*kB/
- msg 3, "RSS: #{$1}"
+ IO.readlines('/proc/self/status').join =~ /VmSize.*?(\d+)\s*kB/
+ msg 3, "VmSize: #{$1}"
return $1.to_i
end
end
end
+class InterruptedLoading < Exception
+ #- not a StandardError, not catched by a simple rescue
+end
+
class Entry
@@max_width = nil
def Entry.thumbnails_height
end
end
- def pixbuf_full
- if @pixbuf_full.nil?
- msg 3, ">>> pixbuf_full #{path}"
- load_into_pixbuf_full
- end
- return @pixbuf_full
- end
def free_pixbuf_full
if @pixbuf_full.nil?
return false
return true
end
end
- def pixbuf_main(interruptable)
+ def pixbuf_main
+ Gtk.main_iteration while Gtk.events_pending?
width, height = $mainview.window.size
width = MainView.get_usable_width(width)
height = MainView.get_usable_height(height)
if @pixbuf_main.nil? || width != @width || height != @height
- msg 3, ">>> pixbuf_main #{path}"
@width = width
@height = height
- load_into_pixbuf_full(interruptable) #- make sure it is loaded
+ load_into_pixbuf_full #- make sure it is loaded
if @pixbuf_full.nil?
return
end
end
end
def pixbuf_thumbnail
+ Gtk.main_iteration while Gtk.events_pending?
if @pixbuf_thumbnail.nil?
if @pixbuf_main
msg 3, ">>> pixbuf_thumbnail from main #{path}"
@pixbuf_thumbnail = @pixbuf_main.scale(@pixbuf_main.width * (Entry.thumbnails_height.to_f/@pixbuf_main.height), Entry.thumbnails_height, Gdk::Pixbuf::INTERP_BILINEAR)
else
msg 3, ">>> pixbuf_thumbnail from file #{path}"
- @pixbuf_thumbnail = load_into_pixbuf_at_size(false) { |w, h|
+ @pixbuf_thumbnail = load_into_pixbuf_at_size { |w, h|
if @angle == 0
if h > Entry.thumbnails_height
[ w * Entry.thumbnails_height.to_f/h, Entry.thumbnails_height ]
Dir.delete(dir)
end
- def load_into_pixbuf_full(interruptable)
+ def load_into_pixbuf_full
if @pixbuf_full.nil?
msg 3, ">>> load_into_pixbuf_full #{path}"
- @pixbuf_full = load_into_pixbuf_at_size(interruptable) { |w, h|
+ @pixbuf_full = load_into_pixbuf_at_size { |w, h|
if @angle == 0
if w > @@max_width
#- save memory and speedup (+35%) loading
end
end
- def load_into_pixbuf_at_size(interruptable, &specify_size)
+ def load_into_pixbuf_at_size(&specify_size)
pixbuf = nil
if @type == 'video'
tmp = Tempfile.new("boohclassifiertemp")
loader.set_size(*specify_size.call(w, h))
}
id = loader.signal_connect('area-prepared') { pixbuf = loader.pixbuf }
- if ! loader.load_not_freezing_ui(image_path, interruptable, id)
- return
+ if ! loader.load_not_freezing_ui(image_path, id)
+ #- interrupted
+ raise InterruptedLoading
end
- loader.close
if pixbuf.nil?
raise "Loaded pixbuf nil - #{path} #{image_path}"
end
rescue
msg 0, "Cannot load #{image_path}: #{$!}"
- begin
- loader.close
- rescue
- end
return
ensure
if @type == 'video'
def run_preloader_real
msg 3, "*** >> main preloading triggered..."
- if $preloader_running
- msg 3, "*** >>>>>> already running, return <<<<<<<<"
- return
- end
- $preloader_running = true
if $mainview.get_shown_entry
if get_mem > $config['cache-memory-use-figure']
msg 3, "too much RSS, stopping preloading, triggering GC"
- $preloader_running = false
gc
get_mem
- return
+ return true
end
if $config['preload-distance'].to_i == 0
free_cache([])
- return
+ return true
end
index = $allentries.index($mainview.get_shown_entry)
index_right = index
right_done = true
else
msg 3, "preloading #{$allentries[index_right].path}"
- $allentries[index_right].pixbuf_main(false)
+ begin
+ $allentries[index_right].pixbuf_main
+ rescue InterruptedLoading
+ msg 3, "*** >>>> interrupted, rerun"
+ return false
+ end
loaded << index_right
loaded_right += 1
if loaded_right == $config['preload-distance'].to_i
left_done = true
else
msg 3, "preloading #{$allentries[index_left].path}"
- $allentries[index_left].pixbuf_main(false)
+ begin
+ $allentries[index_left].pixbuf_main
+ rescue InterruptedLoading
+ msg 3, "*** >>>> interrupted, rerun"
+ return false
+ end
loaded << index_left
loaded_left += 1
if loaded_left == $config['preload-distance'].to_i
#- in case just loaded another directory
if $preloader_force_exit
- $preloader_running = false
$preloader_force_exit = false
- return
+ return true
end
#- in case moved fast
if index != $allentries.index($mainview.get_shown_entry)
msg 3, "*** >>>> moved already, rerun"
- $preloader_running = false
- run_preloader_real
- return
+ return false
end
end
free_cache(loaded)
end
- $preloader_running = false
msg 3, "*** << main preloading finished"
+ return true
end
def run_preloader
msg 3, "*** preloader not yet allowed"
return
end
- Gtk.timeout_add(10) {
- run_preloader_real
- false
+
+ if $preloader_running
+ msg 3, "preloader already running"
+ return
+ end
+ msg 3, "run preloader"
+ $preloader_running = true
+ Gtk.idle_add {
+ msg 3, "begin preloader from timeout "
+ if run_preloader_real
+ $preloader_running = false
+ false
+ else
+ true
+ end
}
end
@@borders_thickness = 5
@@borders_length = 25
+ @@redraw_pending = nil
def MainView.borders_thickness
return @@borders_thickness
return
end
@entry = entry
+ @entry and msg 3, "*** set entry to #{@entry.path}"
redraw
- run_preloader
msg 3, "entry shown in: #{Time.now - t1} s"
end
end
def redraw
+ if @@redraw_pending
+ msg 3, "redraw already pending"
+ return
+ end
+ msg 3, "redraw"
+ @@redraw_pending = Gtk.idle_add {
+ msg 3, "begin redraw from timeout "
+ begin
+ msg 3, "try redraw from timeout"
+ redraw_real
+ @@redraw_pending = nil
+ run_preloader
+ false
+ rescue InterruptedLoading
+ msg 3, "interrupted, will retry"
+ true
+ end
+ }
+ end
+
+ def redraw_real
@entry and sb_msg(_("Selected %s") % @entry.get_beautified_name)
if ! update_shown
return
window.clear
draw
window.end_paint
- Gtk.main_iteration while Gtk.events_pending?
end
def update_shown
if @entry
- $interrupt_loading = false
- pixbuf = @entry.pixbuf_main(true)
- $interrupt_loading = true
+ msg 3, "################################################ trying to show #{@entry.path}"
+ pixbuf = @entry.pixbuf_main
if pixbuf
@pixbuf = pixbuf
width, height = window.size
entry.button.grab_focus
end
update_visibility(entry)
- Gtk.main_iteration while Gtk.events_pending?
end
def show_entries(allentries)
i = 0
tips = Gtk::Tooltips.new
while i < allentries.size
-# printf "%d %s\n", i, __LINE__
- entry = allentries[i]
- if i == 0
- loaded_pixbuf = entry.pixbuf_main(false)
- else
- loaded_pixbuf = entry.pixbuf_thumbnail
+ begin
+ entry = allentries[i]
+ if i == 0
+ loaded_pixbuf = entry.pixbuf_main
+ else
+ loaded_pixbuf = entry.pixbuf_thumbnail
+ end
+ rescue InterruptedLoading
+ redo
end
+
if $allentries != allentries
#- loaded another directory while this one was not yet finished
msg 3, "allentries differ, stopping this deprecated load"
total_loaded_files += 1
i += 1
if i > $config['preload-distance'].to_i && i <= $config['preload-distance'].to_i * 2
- #- when we're at preload distance, beging preloading to preload distance
- allentries[i - $config['preload-distance'].to_i].pixbuf_main(false)
+ #- when we're at preload distance, begin preloading to preload distance
+ begin
+ allentries[i - $config['preload-distance'].to_i].pixbuf_main
+ rescue InterruptedLoading
+ end
end
if i == $config['preload-distance'].to_i * 2 + 1
#- when we're after double preload distance, activate normal preloading
return self;
}
-static int counter = 0;
-
// internalize pixbuf loading for 30% more speedup
-static VALUE load_not_freezing_ui(VALUE self, VALUE path, VALUE interruptable, VALUE area_prepared_signal_id) {
- int interruptable_ = RTEST(interruptable);
+static VALUE load_not_freezing_ui(VALUE self, VALUE path, VALUE area_prepared_signal_id) {
char buf[65536];
size_t amount;
GdkPixbufLoader* loader = GDK_PIXBUF_LOADER(RVAL2GOBJ(self));
GError* error = NULL;
FILE* f = fopen(RVAL2CSTR(path), "r");
if (!f) {
+ gdk_pixbuf_loader_close(loader, NULL);
rb_raise(rb_eRuntimeError, "Unable to open file %s for reading", RVAL2CSTR(path));
}
- counter++;
while ((amount = fread(buf, 1, 65536, f)) > 0) {
if (!gdk_pixbuf_loader_write(loader, (const guchar*) buf, amount, &error)) {
+ gdk_pixbuf_loader_close(loader, NULL);
fclose(f);
RAISE_GERROR(error);
}
- if (counter < 52) {
- // if the user scrolls too fast between thumbnails, there can be large amount of recursions,
- // and program may abort - probably on exhausted stack size; this figure is completely empiric
- while (gtk_events_pending()) {
- gtk_main_iteration();
- }
- if (interruptable_ && RTEST(rb_eval_string("$interrupt_loading"))) {
- // interrupted, case when the user clicked/keyboarded too quickly for this image to
- // display; we cancel this loading, but before we disconnect the area-prepared
- // signal handler, else the call to gdk_pixbuf_loader_get_pixbuf will take ages
- // (between 100 and 400 ms on my p4 for a large photo!)
- g_signal_handler_disconnect(loader, NUM2INT(area_prepared_signal_id));
- gdk_pixbuf_loader_close(loader, NULL);
- fclose(f);
- counter--;
- return Qfalse;
- }
+ if (gtk_events_pending()) {
+ // interrupted, case when the user clicked/keyboarded too quickly for this image to
+ // display; we cancel this loading, but before we disconnect the area-prepared
+ // signal handler, else the call to gdk_pixbuf_loader_get_pixbuf will take ages
+ // (between 100 and 400 ms on my p4 for a large photo!)
+ g_signal_handler_disconnect(loader, NUM2INT(area_prepared_signal_id));
+ gdk_pixbuf_loader_close(loader, NULL);
+ fclose(f);
+ return Qfalse;
}
}
+ gdk_pixbuf_loader_close(loader, NULL);
fclose(f);
- counter--;
return Qtrue;
}
rb_define_method(cinfo->klass, "modify_bg", (VALUE (*)(...)) modify_bg, 2);
cinfo = (RGObjClassInfo*)rbgobj_lookup_class_by_gtype(GDK_TYPE_PIXBUF_LOADER, Qnil);
- rb_define_method(cinfo->klass, "load_not_freezing_ui", (VALUE (*)(...)) load_not_freezing_ui, 3);
+ rb_define_method(cinfo->klass, "load_not_freezing_ui", (VALUE (*)(...)) load_not_freezing_ui, 2);
VALUE exif = rb_define_module("Exif");
rb_define_module_function(exif, "orientation", (VALUE (*)(...)) exif_orientation, 1);