return $config['thumbnails-height'].to_i
end
- attr_accessor :path, :guipath, :type, :angle, :button, :image, :alignment, :removed, :labeled
+ attr_accessor :path, :guipath, :type, :angle, :button, :image, :alignment, :removed, :labeled, :loader
def initialize(path, type, guipath)
@path = path
end
private
- def cleanup_dir(dir)
- Dir.entries(dir).each { |file| file != '.' && file != '..' and File.delete(File.join(dir, file)) }
- Dir.delete(dir)
- end
-
def load_into_pixbuf_full
if @pixbuf_full.nil?
msg 3, ">>> load_into_pixbuf_full #{path}"
end
def load_into_pixbuf_at_size(&specify_size)
- pixbuf = nil
if @type == 'video'
- tmp = Tempfile.new("boohclassifiertemp")
- dest_dir = tmp.path
- tmp.close!
- Dir.mkdir(dest_dir)
- orig_base = File.basename(path)
- tmpdir = gen_video_thumbnail(path, false, 0)
- if tmpdir.nil?
- return
+ if @video_image_path.nil?
+ orig_base = File.basename(path)
+ tmpdir = gen_video_thumbnail(path, false, 0)
+ if tmpdir.nil?
+ return
+ end
+ @video_image_path = "#{tmpdir}/00000001.jpg"
end
- image_path = "#{tmpdir}/00000001.jpg"
+ image_path = @video_image_path
else
image_path = @path
end
end
end
begin
- #- use a pixbuf loader and trigger Gtk.main_iteration on each chunk if needed, to keep the UI responsive even
+ #- use a pixbuf loader and check Gtk.events_pending? on each chunk, to keep the UI responsive even
#- if loaded pictures are several MBs large
- loader = Gdk::PixbufLoader.new
- loader.signal_connect('size-prepared') { |l, w, h|
- r = specify_size.call(w, h)
- #msg 3, "specified sizes: #{r[0]} #{r[1]}"
- 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, id)
+ if @loader.nil?
+ @loader = Gdk::PixbufLoader.new
+ @loader.signal_connect('size-prepared') { |l, w, h|
+ @loader.set_size(*specify_size.call(w, h))
+ }
+ @loader.signal_connect('area-prepared') { @loaded_pixbuf = @loader.pixbuf }
+ @loader_offset = 0
+ end
+ msg 3, "calling load_not_freezing_ui on #{image_path}, offset #{@loader_offset}"
+ @loader_offset = @loader.load_not_freezing_ui(image_path, @loader_offset)
+ if @loader_offset > 0
#- interrupted
raise InterruptedLoading
end
- if pixbuf.nil?
+ @loader = nil
+ if @loaded_pixbuf.nil?
raise "Loaded pixbuf nil - #{path} #{image_path}"
end
rescue
msg 0, "Cannot load #{image_path}: #{$!}"
return
ensure
- if @type == 'video'
- File.delete(image_path)
- Dir.rmdir(tmpdir)
+ if @video_image_path && @loader.nil?
+ File.delete(@video_image_path)
+ Dir.rmdir(File.dirname(@video_image_path))
+ @video_image_path = nil
end
end
- if pixbuf
+ if @loaded_pixbuf
if @angle != 0
msg 3, ">>> load_into_pixbuf_full #{image_path} => rotate #{@angle}"
- pixbuf = rotate_pixbuf(pixbuf, @angle)
+ @loaded_pixbuf = rotate_pixbuf(@loaded_pixbuf, @angle)
end
end
- if @type == 'video'
- cleanup_dir(dest_dir)
- end
- return pixbuf
+ retval = @loaded_pixbuf
+ @loaded_pixbuf = nil
+ return retval
end
def to_s
evt.modify_bg(Gtk::StateType::ACTIVE, $color_red.lighter)
end
+def cleanup_loaders
+ $allentries.each { |e|
+ if ! e.loader.nil?
+ begin
+ e.loader.close
+ rescue
+ #- ignore loader errors, at that point they are fairly normal
+ end
+ end
+ }
+end
+
def reset_thumbnails
+ cleanup_loaders
$allentries = []
if $preloader_running
$preloader_force_exit = true
end
Gtk.main
+cleanup_loaders
+
write_config
}
// internalize pixbuf loading for 30% more speedup
-static VALUE load_not_freezing_ui(VALUE self, VALUE path, VALUE area_prepared_signal_id) {
+static VALUE load_not_freezing_ui(VALUE self, VALUE path, VALUE offset) {
char buf[65536];
size_t amount;
+ size_t off = NUM2INT(offset);
GdkPixbufLoader* loader = GDK_PIXBUF_LOADER(RVAL2GOBJ(self));
GError* error = NULL;
FILE* f = fopen(RVAL2CSTR(path), "r");
gdk_pixbuf_loader_close(loader, NULL);
rb_raise(rb_eRuntimeError, "Unable to open file %s for reading", RVAL2CSTR(path));
}
+ if (off > 0) {
+ if (fseek(f, off, SEEK_SET) != 0) {
+ rb_raise(rb_eRuntimeError, "Unable to seek file %s", RVAL2CSTR(path));
+ fclose(f);
+ return 0;
+ }
+ }
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 (gtk_events_pending()) {
+ off += amount;
+ if (gtk_events_pending() && !feof(f)) {
// 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);
+ // display; we temporarily interrupt this loading
fclose(f);
- return Qfalse;
+ return INT2NUM(off);
}
}
gdk_pixbuf_loader_close(loader, NULL);
fclose(f);
- return Qtrue;
+ return INT2NUM(0);
}
extern "C" {