require 'booh/booh-lib'
include Booh
require 'booh/UndoHandler'
-require 'booh/Synchronizator'
#- options
#- default values for some globals
$xmldir = nil
-$xmlaccesslock = Object.new
$modified = false
$current_cursor = nil
$ignore_videos = false
def color_swap(xmldir, attributes_prefix)
$modified = true
- if xmldir.attributes["#{attributes_prefix}color-swap"]
- xmldir.delete_attribute("#{attributes_prefix}color-swap")
- else
- xmldir.add_attribute("#{attributes_prefix}color-swap", '1')
- end
+ rexml_thread_protect {
+ if xmldir.attributes["#{attributes_prefix}color-swap"]
+ xmldir.delete_attribute("#{attributes_prefix}color-swap")
+ else
+ xmldir.add_attribute("#{attributes_prefix}color-swap", '1')
+ end
+ }
end
def enhance(xmldir, attributes_prefix)
$modified = true
- if xmldir.attributes["#{attributes_prefix}enhance"]
- xmldir.delete_attribute("#{attributes_prefix}enhance")
- else
- xmldir.add_attribute("#{attributes_prefix}enhance", '1')
- end
+ rexml_thread_protect {
+ if xmldir.attributes["#{attributes_prefix}enhance"]
+ xmldir.delete_attribute("#{attributes_prefix}enhance")
+ else
+ xmldir.add_attribute("#{attributes_prefix}enhance", '1')
+ end
+ }
end
def change_seektime(xmldir, attributes_prefix, value)
$modified = true
- xmldir.add_attribute("#{attributes_prefix}seektime", value)
+ rexml_thread_protect {
+ xmldir.add_attribute("#{attributes_prefix}seektime", value)
+ }
end
def ask_new_seektime(xmldir, attributes_prefix)
- if xmldir
- value = xmldir.attributes["#{attributes_prefix}seektime"]
- else
- value = ''
- end
+ rexml_thread_protect {
+ if xmldir
+ value = xmldir.attributes["#{attributes_prefix}seektime"]
+ else
+ value = ''
+ end
+ }
dialog = Gtk::Dialog.new(utf8(_("Change seek time")),
$main_window,
def change_pano_amount(xmldir, attributes_prefix, value)
$modified = true
- if value.nil?
- xmldir.delete_attribute("#{attributes_prefix}pano-amount")
- else
- xmldir.add_attribute("#{attributes_prefix}pano-amount", value.to_s)
- end
+ rexml_thread_protect {
+ if value.nil?
+ xmldir.delete_attribute("#{attributes_prefix}pano-amount")
+ else
+ xmldir.add_attribute("#{attributes_prefix}pano-amount", value.to_s)
+ end
+ }
end
def ask_new_pano_amount(xmldir, attributes_prefix)
- if xmldir
- value = xmldir.attributes["#{attributes_prefix}pano-amount"]
- else
- value = nil
- end
+ rexml_thread_protect {
+ if xmldir
+ value = xmldir.attributes["#{attributes_prefix}pano-amount"]
+ else
+ value = nil
+ end
+ }
dialog = Gtk::Dialog.new(utf8(_("Specify panorama amount")),
$main_window,
end
end
+$max_gen_thumbnail_threads = nil
+$current_gen_thumbnail_threads = 0
+$gen_thumbnail_monitor = Monitor.new
+
def gen_real_thumbnail(type, origfile, destfile, xmldir, size, img, infotype)
- Thread.new {
+ if $max_gen_thumbnail_threads.nil?
+ $max_gen_thumbnail_threads = 1 + $config['mproc'].to_i || 1
+ end
+ genproc = Proc.new {
push_mousecursor_wait
- gen_real_thumbnail_core(type, origfile, destfile, Synchronizator.new(xmldir, $xmlaccesslock), size, infotype)
+ gen_real_thumbnail_core(type, origfile, destfile, xmldir, size, infotype)
gtk_thread_protect {
img.set(destfile)
$modified_pixbufs[destfile] = { :orig => img.pixbuf, :pixbuf => img.pixbuf, :angle_to_orig => 0 }
}
pop_mousecursor
}
+ usethread = false
+ $gen_thumbnail_monitor.synchronize {
+ if $current_gen_thumbnail_threads < $max_gen_thumbnail_threads
+ $current_gen_thumbnail_threads += 1
+ usethread = true
+ end
+ }
+ if usethread
+ Thread.new {
+ genproc.call
+ $gen_thumbnail_monitor.synchronize {
+ $current_gen_thumbnail_threads -= 1
+ }
+ }
+ else
+ genproc.call
+ end
end
def popup_thumbnail_menu(event, optionals, fullpath, type, xmldir, attributes_prefix, possible_actions, closures)
end
}
if !possible_actions[:can_multiple] || $selected_elements.length == 0
- menu.append(enhance = Gtk::ImageMenuItem.new(utf8(xmldir.attributes["#{attributes_prefix}enhance"] ? _("Original contrast") :
- _("Enhance constrast"))))
+ menu.append(enhance = Gtk::ImageMenuItem.new(utf8(rexml_thread_protect { xmldir.attributes["#{attributes_prefix}enhance"] } ? _("Original contrast") :
+ _("Enhance constrast"))))
else
menu.append(enhance = Gtk::ImageMenuItem.new(utf8(_("Toggle contrast enhancement"))))
end
cleanup_all_thumbnails.call
#- refresh is not undoable and doesn't change the album, however we must regenerate all thumbnails when generating the album
$modified = true
- $xmldir.delete_attribute('already-generated')
+ rexml_thread_protect {
+ $xmldir.delete_attribute('already-generated')
+ }
my_gen_real_thumbnail.call
}
rotate_and_cleanup = proc { |angle|
cleanup_all_thumbnails.call
- rotate(angle, thumbnail_img, img, $xmldir.elements["*[@filename='#{filename}']"], '', $default_thumbnails[:x], $default_thumbnails[:y])
+ rexml_thread_protect {
+ rotate(angle, thumbnail_img, img, $xmldir.elements["*[@filename='#{filename}']"], '', $default_thumbnails[:x], $default_thumbnails[:y])
+ }
}
move = proc { |direction|
color_swap_and_cleanup = proc {
perform_color_swap_and_cleanup = proc {
cleanup_all_thumbnails.call
- color_swap($xmldir.elements["*[@filename='#{filename}']"], '')
+ rexml_thread_protect {
+ color_swap($xmldir.elements["*[@filename='#{filename}']"], '')
+ }
my_gen_real_thumbnail.call
}
change_seektime_and_cleanup_real = proc { |values|
perform_change_seektime_and_cleanup = proc { |val|
cleanup_all_thumbnails.call
- change_seektime($xmldir.elements["*[@filename='#{filename}']"], '', val)
+ rexml_thread_protect {
+ change_seektime($xmldir.elements["*[@filename='#{filename}']"], '', val)
+ }
my_gen_real_thumbnail.call
}
perform_change_seektime_and_cleanup.call(values[:new])
}
change_seektime_and_cleanup = proc {
- if values = ask_new_seektime($xmldir.elements["*[@filename='#{filename}']"], '')
- change_seektime_and_cleanup_real.call(values)
- end
+ rexml_thread_protect {
+ if values = ask_new_seektime($xmldir.elements["*[@filename='#{filename}']"], '')
+ change_seektime_and_cleanup_real.call(values)
+ end
+ }
}
change_pano_amount_and_cleanup_real = proc { |values|
perform_change_pano_amount_and_cleanup = proc { |val|
cleanup_all_thumbnails.call
- change_pano_amount($xmldir.elements["*[@filename='#{filename}']"], '', val)
+ rexml_thread_protect {
+ change_pano_amount($xmldir.elements["*[@filename='#{filename}']"], '', val)
+ }
}
perform_change_pano_amount_and_cleanup.call(values[:new])
}
change_pano_amount_and_cleanup = proc {
- if values = ask_new_pano_amount($xmldir.elements["*[@filename='#{filename}']"], '')
- change_pano_amount_and_cleanup_real.call(values)
- end
+ rexml_thread_protect {
+ if values = ask_new_pano_amount($xmldir.elements["*[@filename='#{filename}']"], '')
+ change_pano_amount_and_cleanup_real.call(values)
+ end
+ }
}
whitebalance_and_cleanup_real = proc { |values|
perform_change_whitebalance_and_cleanup = proc { |val|
cleanup_all_thumbnails.call
- change_whitebalance($xmldir.elements["*[@filename='#{filename}']"], '', val)
- recalc_whitebalance(val, fullpath, thumbnail_img, img,
- $xmldir.elements["*[@filename='#{filename}']"], '', $default_thumbnails[:x], $default_thumbnails[:y], '')
+ rexml_thread_protect {
+ change_whitebalance($xmldir.elements["*[@filename='#{filename}']"], '', val)
+ recalc_whitebalance(val, fullpath, thumbnail_img, img,
+ $xmldir.elements["*[@filename='#{filename}']"], '', $default_thumbnails[:x], $default_thumbnails[:y], '')
+ }
}
perform_change_whitebalance_and_cleanup.call(values[:new])
}
whitebalance_and_cleanup = proc {
- if values = ask_whitebalance(fullpath, thumbnail_img, img,
- $xmldir.elements["*[@filename='#{filename}']"], '', $default_thumbnails[:x], $default_thumbnails[:y], '')
- whitebalance_and_cleanup_real.call(values)
- end
+ rexml_thread_protect {
+ if values = ask_whitebalance(fullpath, thumbnail_img, img,
+ $xmldir.elements["*[@filename='#{filename}']"], '', $default_thumbnails[:x], $default_thumbnails[:y], '')
+ whitebalance_and_cleanup_real.call(values)
+ end
+ }
}
gammacorrect_and_cleanup_real = proc { |values|
perform_change_gammacorrect_and_cleanup = Proc.new { |val|
cleanup_all_thumbnails.call
- change_gammacorrect($xmldir.elements["*[@filename='#{filename}']"], '', val)
- recalc_gammacorrect(val, fullpath, thumbnail_img, img,
- $xmldir.elements["*[@filename='#{filename}']"], '', $default_thumbnails[:x], $default_thumbnails[:y], '')
+ rexml_thread_protect {
+ change_gammacorrect($xmldir.elements["*[@filename='#{filename}']"], '', val)
+ recalc_gammacorrect(val, fullpath, thumbnail_img, img,
+ $xmldir.elements["*[@filename='#{filename}']"], '', $default_thumbnails[:x], $default_thumbnails[:y], '')
+ }
}
perform_change_gammacorrect_and_cleanup.call(values[:new])
}
gammacorrect_and_cleanup = Proc.new {
- if values = ask_gammacorrect(fullpath, thumbnail_img, img,
- $xmldir.elements["*[@filename='#{filename}']"], '', $default_thumbnails[:x], $default_thumbnails[:y], '')
- gammacorrect_and_cleanup_real.call(values)
- end
+ rexml_thread_protect {
+ if values = ask_gammacorrect(fullpath, thumbnail_img, img,
+ $xmldir.elements["*[@filename='#{filename}']"], '', $default_thumbnails[:x], $default_thumbnails[:y], '')
+ gammacorrect_and_cleanup_real.call(values)
+ end
+ }
}
enhance_and_cleanup = proc {
perform_enhance_and_cleanup = proc {
cleanup_all_thumbnails.call
- enhance($xmldir.elements["*[@filename='#{filename}']"], '')
+ rexml_thread_protect {
+ enhance($xmldir.elements["*[@filename='#{filename}']"], '')
+ }
my_gen_real_thumbnail.call
}
if !$ignore_next_release
x, y = autotable.get_current_pos(vbox)
next_ = autotable.get_next_widget(vbox)
- popup_thumbnail_menu(event, ['delete'], fullpath, type, $xmldir.elements["*[@filename='#{filename}']"], '',
+ popup_thumbnail_menu(event, ['delete'], fullpath, type, rexml_thread_protect { $xmldir.elements["*[@filename='#{filename}']"] }, '',
{ :can_left => x > 0, :can_right => next_ && autotable.get_current_pos(next_)[0] > x,
:can_up => y > 0, :can_down => y < autotable.get_max_y, :can_multiple => true, :can_panorama => true },
{ :rotate => rotate_and_cleanup, :move => move, :color_swap => color_swap_and_cleanup, :enhance => enhance_and_cleanup,
#- already-generated markers in original file
if $generated_outofline
begin
- $xmldoc = Synchronizator.new(REXML::Document.new(File.new($orig_filename)), $xmlaccesslock)
+ $xmldoc = REXML::Document.new(File.new($orig_filename))
mark_document_as_dirty
ios = File.open($orig_filename, "w")
$xmldoc.write(ios, 0)
$modified = true
save_changes
current_order = []
- $xmldir.elements.each { |element|
- if element.name == 'image' || element.name == 'video'
- current_order << element.attributes['filename']
- end
+ rexml_thread_protect {
+ $xmldir.elements.each { |element|
+ if element.name == 'image' || element.name == 'video'
+ current_order << element.attributes['filename']
+ end
+ }
}
#- look for EXIF dates
end
saves = {}
- $xmldir.elements.each { |element|
- if element.name == 'image' || element.name == 'video'
- saves[element.attributes['filename']] = element.remove
- end
+ rexml_thread_protect {
+ $xmldir.elements.each { |element|
+ if element.name == 'image' || element.name == 'video'
+ saves[element.attributes['filename']] = element.remove
+ end
+ }
}
neworder = smartsort(current_order, dates)
- neworder.each { |f|
- $xmldir.add_element(saves[f].name, saves[f].attributes)
+ rexml_thread_protect {
+ neworder.each { |f|
+ $xmldir.add_element(saves[f].name, saves[f].attributes)
+ }
}
#- let the auto-table reflect new ordering
$subalbums = Gtk::Table.new(0, 0, true)
current_y_sub_albums = 0
- $xmldir = Synchronizator.new($xmldoc.elements["//dir[@path='#{$current_path}']"], $xmlaccesslock)
+ $xmldir = $xmldoc.elements["//dir[@path='#{$current_path}']"]
$subalbums_edits = {}
subalbums_counter = 0
subalbums_edits_bypos = {}
end
begin
- $xmldoc = Synchronizator.new(REXML::Document.new(File.new(filename)), $xmlaccesslock)
+ $xmldoc = REXML::Document.new(File.new(filename))
rescue Exception
$xmldoc = nil
end
if Thread.current == Thread.main
proc.call
else
- $protect_gtk_pending_calls.synchronize {
+ $gtk_pending_calls.synchronize {
$gtk_pending_calls << proc
}
end
end
def gtk_thread_flush
- #- try to lock. we cannot synchronize blindly because this might be called from
- #- within the timeout flushing procs. if this is the case, not doing anything
- #- should be ok since the timeout is already flushing them all.
- if $protect_gtk_pending_calls.try_lock
- for closure in $gtk_pending_calls
+ closure = nil
+ continue = true
+ begin
+ $gtk_pending_calls.synchronize {
+ closure = $gtk_pending_calls.shift
+ continue = $gtk_pending_calls.size > 0
+ }
+ if closure
closure.call
end
- $gtk_pending_calls = []
- $protect_gtk_pending_calls.unlock
- end
+ end while continue
end
def ask_password_protect
false
}
- $protect_gtk_pending_calls = Mutex.new
$gtk_pending_calls = []
+ $gtk_pending_calls.extend(MonitorMixin)
Gtk.timeout_add(100) {
- $protect_gtk_pending_calls.synchronize {
- for closure in $gtk_pending_calls
- closure.call
- end
- $gtk_pending_calls = []
- }
+ gtk_thread_flush
true
}
require 'iconv'
require 'timeout'
require 'tempfile'
+require 'monitor'
require 'booh/rexml/document'
end
def gen_thumbnails_element(orig, xmldirorelem, allow_background, dests)
- if xmldirorelem.name == 'dir'
- xmldirorelem = xmldirorelem.elements["*[@filename='#{utf8(File.basename(orig))}']"]
- end
+ rexml_thread_protect {
+ if xmldirorelem.name == 'dir'
+ xmldirorelem = xmldirorelem.elements["*[@filename='#{utf8(File.basename(orig))}']"]
+ end
+ }
gen_thumbnails(orig, allow_background, dests, xmldirorelem, '')
end
if entry2type(orig) == 'image'
if felem
- if whitebalance = felem.attributes["#{attributes_prefix}white-balance"]
+ if whitebalance = rexml_thread_protect { felem.attributes["#{attributes_prefix}white-balance"] }
neworig = "#{dest_dir}/#{File.basename(orig)}-whitebalance#{whitebalance}.jpg"
cmd = "booh-fix-whitebalance '#{orig}' '#{neworig}' #{whitebalance}"
sys(cmd)
orig = neworig
end
end
- if gammacorrect = felem.attributes["#{attributes_prefix}gamma-correction"]
+ if gammacorrect = rexml_thread_protect { felem.attributes["#{attributes_prefix}gamma-correction"] }
neworig = "#{dest_dir}/#{File.basename(orig)}-gammacorrect#{gammacorrect}.jpg"
cmd = "booh-gamma-correction '#{orig}' '#{neworig}' #{gammacorrect}"
sys(cmd)
orig = neworig
end
end
- rotate = felem.attributes["#{attributes_prefix}rotate"]
+ rotate = rexml_thread_protect { felem.attributes["#{attributes_prefix}rotate"] }
if !rotate
- felem.add_attribute("#{attributes_prefix}rotate", rotate = guess_rotate(orig).to_s)
+ rexml_thread_protect { felem.add_attribute("#{attributes_prefix}rotate", rotate = guess_rotate(orig).to_s) }
end
convert_options += "-rotate #{rotate} "
- if felem.attributes["#{attributes_prefix}enhance"]
+ if rexml_thread_protect { felem.attributes["#{attributes_prefix}enhance"] }
convert_options += ($config['convert-enhance'] || $convert_enhance) + " "
end
end
elsif entry2type(orig) == 'video'
if felem
#- seektime is an attribute that allows to specify where the frame to use for the thumbnail must be taken
- seektime = felem.attributes["#{attributes_prefix}seektime"]
+ seektime = rexml_thread_protect { felem.attributes["#{attributes_prefix}seektime"] }
if ! seektime
- felem.add_attribute("#{attributes_prefix}seektime", seektime = "0")
+ rexml_thread_protect { felem.add_attribute("#{attributes_prefix}seektime", seektime = "0") }
end
seektime = seektime.to_f
- if rotate = felem.attributes["#{attributes_prefix}rotate"]
+ if rotate = rexml_thread_protect { felem.attributes["#{attributes_prefix}rotate"] }
convert_options += "-rotate #{rotate} "
end
- if felem.attributes["#{attributes_prefix}enhance"]
+ if rexml_thread_protect { felem.attributes["#{attributes_prefix}enhance"] }
convert_options += ($config['convert-enhance'] || $convert_enhance) + " "
end
end
for dest in dests
if ! File.exists?(dest['filename'])
- tmpdir = gen_video_thumbnail(orig, felem && felem.attributes["#{attributes_prefix}color-swap"], seektime)
+ tmpdir = gen_video_thumbnail(orig, felem && rexml_thread_protect { felem.attributes["#{attributes_prefix}color-swap"] }, seektime)
if tmpdir.nil?
return false
end
tmpfile = "#{tmpdir}/00000001.jpg"
alltmpfiles = [ tmpfile ]
- if felem && whitebalance = felem.attributes["#{attributes_prefix}white-balance"]
+ if felem && whitebalance = rexml_thread_protect { felem.attributes["#{attributes_prefix}white-balance"] }
if whitebalance.to_f != 0
neworig = "#{tmpdir}/whitebalance#{whitebalance}.jpg"
cmd = "booh-fix-whitebalance '#{tmpfile}' '#{neworig}' #{whitebalance}"
end
end
end
- if felem && gammacorrect = felem.attributes["#{attributes_prefix}gamma-correction"]
+ if felem && gammacorrect = rexml_thread_protect { felem.attributes["#{attributes_prefix}gamma-correction"] }
if gammacorrect.to_f != 0
neworig = "#{tmpdir}/gammacorrect#{gammacorrect}.jpg"
cmd = "booh-gamma-correction '#{tmpfile}' '#{neworig}' #{gammacorrect}"
ios.close
end
+ $xmlaccesslock = Monitor.new
+
+ def rexml_thread_protect(&proc)
+ $xmlaccesslock.synchronize {
+ proc.call
+ }
+ end
+
def check_browser
browser_binary = $config['browser'].split.first
if browser_binary && !File.executable?(browser_binary)