On 2017-01-30 22:21, jeremy rosen wrote:
Ok, i'm at home with a little more time on my hand.

I didn't manage to reproduce any gui blockage, though I managed to make
it very sluggish. I don't have shotwell so I did a little test script
but my tests were limited

so my first question is : What exactly do you see. Is it a complete gui
blockage, or is it just slugishness ? does the dt.gui.selection trick
make it completely responsive, or less sluggish ?

If I do nothing in the loop to yield control to the gui, the program is by all means unresponsive. If there is some kind of response it is way below any reasonable level of usefulness.

The dt.gui.selection trick renders the gui almost normally responsive (there are two in-process sql queries run for each file one of which is far less than optimal), and the progress bar updates neatly, and the cancel button works.

I'm not completely clear how you block the gtk thread, my guess is that
you don't but that somehow some lua is called on each redraw, and when
your process is running in a secondary thread, it blocks the lua lock
which in turn blocks the gtk thread trying to run lua code.

I have no other lua scripts loaded.

calling dt.gui.selection will force lua to run some code in the "real"
gtk thread. To do that, lua programs a task to be run in the gtk thread,
release the lua lock, and wait for the job on the gtk thread to do what
it has to do. So this call not only releases the lua lock, it also
forces a task switch

a very short sleep timer will release the lua lock, but take it
immediately before the scheduler can run another thread which would take
the lock.

In fact, very short sleeps didn't do any good. It only made a difference when the sleep approached 1000ms.

The core problem is that your main loop is a case I hadn't thought of. I
had thought of long-running shell scripts (darktable.control.execute)
waiting for some data to be availalbe on a socket or device
(darktable.control.read) or an infinite loop that sleeps for "a long
time" (darktable.control.sleep) I hadn't thought of a loop that makes
most of its processing in lua and tries to not sleep, but still need to
release the lock.

That'll be your just punishment for making the program so extensible - you get people like me doing odd stuff :-)

could you test if replacing your call to dt.gui.selection to a call to
dt.control.execute("true") also fixes your issue ?

There is some responsiveness, but much less than with the dt.guid.selection call. The gui is active but very sluggish and the progress bar doesn't update smoothly any more.

if that helps, I will add a call to g_thread_yield at a strategic place
in dt.control.sleep and you will be able to call dt.control.sleep(0)

That would definitely look less obscure than the selection call.

Please let me know if there's anything I can do to help.

I've written another similar script that sets the selection in lighttable to all missing files in the current collection.

The script logic is practically the same, it just tries to open the files instead of looking stuff up in an sqlite db. This script doesn't slow down or block the gui, even if I leave out calls to dt.gui.selection or dt.control.execute.

The main difference between the two scripts is now cpu-intensive they are. The shotwell script does loads of work on luasql, while the missing files script just opens a file and closes it again.

I've attached the thing.



Thanks for darktable. Now I've learned how to use it a bit, I can't imaging how I did without it.

--
René Seindal - [email protected]

____________________________________________________________________________
darktable user mailing list
to unsubscribe send a mail to [email protected]
#!/usr/bin/lua

local dt = require "darktable"

dt.configuration.check_version(...,{4,0,0})

local function printf(fmt, ...) dt.print_error(string.format(fmt, ...)) end

local function select_missing_files(images)
   local selection = {};
   
   local cancelled = false
   local progress = dt.gui.create_job('Checking for missing files', true, function() cancelled = true; end)
   local total = #images

   printf('checking %d images for missing files', total)
   
   progress.percent = 0;
   for count, image in ipairs(images)  do
      local file = image.path .. '/' .. image.filename
      -- printf('file %s', file)

      local fp = io.open(file)
      if not fp then
	 table.insert(selection, image)
	 -- printf('\tmissing')
      else
	 io.close(fp)
      end

      progress.percent = count / total
      -- dt.control.execute("/bin/true")
      -- dt.gui.selection()
      -- this function has attribute implicit_yield
      -- and the progress bar updates
      if cancelled then break end
   end
   progress.valid = false

   return selection
end


dt.register_event(
   "shortcut",
  function(event, shortcut) return select_missing_files(dt.collection) end,
  "select missing files only"
)

dt.gui.libs.select.register_selection(
  "select missing",
  function(event, images) return select_missing_files(images) end,
  "select missing files only"
)

Reply via email to