Hi all,

please find attached below a patch meant to improve on user experience with
darktable-viewer, including some documentation for it.

The changes essentially replace the sleep statements with equally long SDL
timeout events, so keyboard events can be handled promptly without any dead
times due to sleep.

On this basis, more keybindings are introduced: pausing the slideshow or
manually switching to previous/next image.

Moreover, this patch ensures dtview-specific command line parameters do not
get in the way of general darktable options through dt_init.

What do you think?

Next, what I would like to do is add a command line option for positioning
the image within the screen (instead of centered) -- as a workaround for
missing RandR in SDL 1.2: with multiple monitors connected and set up, SDL
only gets to see the total sum resolution of them, and with dtview's
write_image choosing to center the image on the screen, it ends up half-way
on both monitors. Has anyone suggestions or comments on that one, perhaps?

Regards,
Robert
From 63efbbb311443e8d45b16cf7029998a4cebd60f1 Mon Sep 17 00:00:00 2001
From: Robert Schubert <robert.schub...@mathint.com>
Date: Sun, 12 Jul 2015 01:31:47 +0200
Subject: [PATCH] Modified dtview to make it more responsive to user (more
 keybindings, no dead times).

Added manpage for darktable-viewer akin to darktable-cli.
---
 doc/CMakeLists.txt       |  14 +++++-
 doc/darktable-viewer.pod | 120 +++++++++++++++++++++++++++++++++++++++++++++++
 src/dtview/main.c        | 109 ++++++++++++++++++++++++++++++++++--------
 3 files changed, 222 insertions(+), 21 deletions(-)
 create mode 100644 doc/darktable-viewer.pod

diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
index fc253f2..63facf4 100644
--- a/doc/CMakeLists.txt
+++ b/doc/CMakeLists.txt
@@ -27,7 +27,17 @@ add_custom_command(
 	
 )
 
-add_custom_target(manpages ALL DEPENDS darktable.1 darktable-cli.1)
+add_custom_command(
+	OUTPUT darktable-viewer.1
+	SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/darktable-viewer.pod
+	COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/../tools/makeman.sh ${CMAKE_CURRENT_SOURCE_DIR}/darktable-viewer.pod ${CMAKE_CURRENT_BINARY_DIR}/../src/config.h ${CMAKE_CURRENT_SOURCE_DIR}/AUTHORS ${CMAKE_CURRENT_BINARY_DIR}/darktable-viewer.1
+	${CMAKE_CURRENT_SOURCE_DIR}/darktable-viewer.pod 
+	${CMAKE_CURRENT_BINARY_DIR}/darktable-viewer.1 
+	DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/darktable-viewer.pod ${CMAKE_CURRENT_SOURCE_DIR}/AUTHORS ${CMAKE_CURRENT_BINARY_DIR}/../src/config.h
+	
+)
+
+add_custom_target(manpages ALL DEPENDS darktable.1 darktable-cli.1 darktable-viewer.1)
 
 if(NOT MAN_INSTALL_DIR)
 	if(CMAKE_SYSTEM_NAME MATCHES "^(DragonFly|FreeBSD|NetBSD|OpenBSD)$")
@@ -37,7 +47,7 @@ if(NOT MAN_INSTALL_DIR)
 	endif()
 endif(NOT MAN_INSTALL_DIR)
 
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/darktable.1 ${CMAKE_CURRENT_BINARY_DIR}/darktable-cli.1 DESTINATION ${MAN_INSTALL_DIR})
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/darktable.1 ${CMAKE_CURRENT_BINARY_DIR}/darktable-cli.1 ${CMAKE_CURRENT_BINARY_DIR}/darktable-viewer.1 DESTINATION ${MAN_INSTALL_DIR})
 
 
 if(NOT ${Xsltproc_BIN} STREQUAL "Xsltproc_BIN-NOTFOUND")
diff --git a/doc/darktable-viewer.pod b/doc/darktable-viewer.pod
new file mode 100644
index 0000000..a7be084
--- /dev/null
+++ b/doc/darktable-viewer.pod
@@ -0,0 +1,120 @@
+
+=head1 NAME
+
+darktable-viewer - slideshow viewer for darktable
+
+=head1 SYNOPSIS
+
+    darktable-viewer [options]
+
+Options:
+
+    --repeat
+    --random
+    --window
+    --help        
+    <darktable options>
+
+=head1 DESCRIPTION
+
+B<darktable> is a digital photography workflow application for B<Linux> 
+and B<Mac OS X> in the lines of B<Adobe Lightroom> and B<Apple Aperture>.
+It's described further in L<darktable(1)|darktable(1)>.
+
+B<darktable-viewer> is a variant to be used for showing all images 
+in the last active collection as slideshow on the screen, given 
+the raw file and the accompanying xmp file.
+
+=head1 COMMAND LINE ARGUMENTS
+
+=over
+
+=item B<< --random >>
+
+Show the images in randomised order (but each only once) instead of
+their order in the collection.
+
+=item B<< --repeat >>
+
+When reaching the end of the current collection, start all over
+(in the same order) instead of terminating.
+
+=item B<< --window >>
+
+Start with window manager decorations initially instead of fullscreen
+mode. 
+See also key binding for C<f>.
+
+=item B<< <darktable options>  >>
+
+All other command line parameters are passed to the darktable core and 
+handled as standard parameters. See L<darktable(1)|darktable(1)> 
+for a detailed description of the options.
+
+=back
+
+=head1 DEFAULT KEYBINDINGS
+
+=over
+
+=item B<Esc, q>
+
+Quit
+
+=item B<f>
+
+Toggle fullscreen mode.
+
+=item B<Space, p>
+
+Pause the slideshow. Images can still be selected manually.
+
+=item B<PageUp, Left, Up>
+
+Select the last image (without waiting any longer, except loading delay).
+
+=item B<PageDown, Right, Down>
+
+Select the next image (without waiting any longer, except loading delay).
+
+=back
+
+=head1 SEE ALSO
+
+L<darktable(1)|darktable(1)>
+
+=head1 OTHER INFO
+
+Please visit B<darktable>'s website for news, bug tracker and forum: L<http://www.darktable.org/>
+
+=head1 REPORTING BUGS
+
+Please use the bug tracker on
+L<http://www.darktable.org/redmine/projects/darktable/issues/> to report
+bugs, feature requests and so on.
+
+=head1 AUTHORS
+
+The principal developer of darktable is Johannes Hanika. The (hopefully)
+complete list of contributors to the project is:
+
+DREGGNAUTHORS
+
+This man page was written by Alexandre Prokoudine 
+E<lt>alexandre.prokoud...@gmail.come<gt> and Richard Levitte
+E<lt>rich...@levittr.orge<gt>.
+
+=head1 HISTORY
+
+The project was started by Johannes Hanika in early 2009 to fill the gap 
+(or, rather, a black hole) of a digital photography workflow tool on Linux.
+
+=head1 COPYRIGHT AND LICENSE
+
+B<Copyright (C)> 2009-2013 by Authors.
+
+B<darktable> is free software; you can redistribute it and/or modify it
+under the terms of the GPL v3 or (at your option) any later version.
+
+=for comment
+$Date$
diff --git a/src/dtview/main.c b/src/dtview/main.c
index f4a057f..68c34ed 100644
--- a/src/dtview/main.c
+++ b/src/dtview/main.c
@@ -36,7 +36,8 @@ void srand48(long int);
 #include <unistd.h>
 #include <inttypes.h>
 
-int running;
+int running, paused, waiting, fullscreen;
+int counter = 1;
 int width, height;
 uint32_t random_state;
 int32_t repeat;
@@ -54,7 +55,7 @@ int init(int argc, char *arg[])
   gettimeofday(&time, NULL);
   scramble = time.tv_sec + time.tv_usec;
 
-  if(SDL_Init(SDL_INIT_VIDEO) < 0)
+  if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
   {
     fprintf(stderr, "[%s] video initialization failed: %s\n", arg[0], SDL_GetError());
     exit(1);
@@ -81,7 +82,10 @@ int init(int argc, char *arg[])
   SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
   SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
 
-  flags = SDL_OPENGL | SDL_FULLSCREEN;
+  if (fullscreen)
+    flags = SDL_OPENGL | SDL_FULLSCREEN;
+  else
+    flags = SDL_OPENGL;
 
   if(SDL_SetVideoMode(width, height, bpp, flags) == 0)
   {
@@ -135,7 +139,40 @@ static void handle_event(const SDL_Event *event)
     case SDL_KEYDOWN:
     {
       const SDLKey keysym = event->key.keysym.sym;
-      if(keysym == SDLK_ESCAPE) running = 0;
+      if(keysym == SDLK_ESCAPE || keysym == SDLK_q)   
+      {
+        running = 0;
+      }
+      if(keysym == SDLK_SPACE || keysym == SDLK_p)    
+      { 
+        paused = !paused; 
+        if(!paused)
+        {
+          waiting = 0; 
+          counter++;
+        }
+      }
+      if(keysym == SDLK_PAGEUP || keysym == SDLK_UP || keysym == SDLK_LEFT)   
+      { 
+        counter--;
+        waiting = 0; 
+      }
+      if(keysym == SDLK_PAGEDOWN || keysym == SDLK_DOWN || keysym == SDLK_RIGHT) 
+      {
+        counter++;
+        waiting = 0;
+      }
+      if(keysym == SDLK_f)        
+        SDL_WM_ToggleFullScreen(SDL_GetVideoSurface());
+      break;
+    }
+    case SDL_USEREVENT:
+    {
+      if(event->user.code == 1)  // timeout? 
+      {
+        if(event->user.data1) // increase counter for next?
+          counter++;
+      }
       break;
     }
     default:
@@ -143,12 +180,39 @@ static void handle_event(const SDL_Event *event)
   }
 }
 
+// callback for SDL timer
+uint32_t pushevent (uint32_t interval, void* param) {
+  SDL_Event event;
+  event.type = SDL_USEREVENT;
+  event.user.code = 1;
+  event.user.data1 = param;
+
+  SDL_PushEvent (&event);
+
+  return 0; // disable timer again
+}
+
 static void pump_events()
 {
   SDL_Event event;
   while(SDL_PollEvent(&event)) handle_event(&event);
 }
 
+static void wait_event(uint32_t ms, int auto_inc)
+{
+  SDL_Event event;
+  if(ms > 0)
+  {
+    SDL_TimerID timeout = SDL_AddTimer (ms, pushevent, auto_inc ? &counter : NULL); // add (self-disabling) timeout event
+    if(SDL_WaitEvent(&event)) handle_event(&event);
+    if (!waiting) SDL_RemoveTimer(timeout); // keyboard event: prevent timeout carrying over to other image
+  }
+  else
+    if(SDL_WaitEvent(&event)) handle_event(&event);
+
+  pump_events(); // flush event queue
+}
+
 static void update(const int frame)
 {
   // copy over the buffer, so we can blend smoothly.
@@ -233,7 +297,6 @@ uint32_t next_random()
 
 static int process_next_image()
 {
-  static int counter = 0;
   dt_imageio_module_format_t buf;
   dt_imageio_module_data_t dat;
   buf.mime = mime;
@@ -248,7 +311,8 @@ static int process_next_image()
   int32_t id = 0;
   const uint32_t cnt = dt_collection_get_count(darktable.collection);
   // enumerated all images?
-  if(++counter >= cnt) return 1;
+  if(counter < 1) counter = 1;
+  if(counter >= cnt) return 1;
   uint32_t ran = counter - 1;
   if(use_random)
   {
@@ -280,17 +344,25 @@ int main(int argc, char *arg[])
 {
   gtk_init(&argc, &arg);
   repeat = random_state = use_random = 0;
+  fullscreen = 1;
   for(int k = 1; k < argc; k++)
   {
+    int dtview_option = 1;
     if(!strcmp(arg[k], "--random"))
       use_random = 1;
     else if(!strcmp(arg[k], "--repeat"))
       repeat = -1;
+    else if(!strcmp(arg[k], "--window"))
+      fullscreen = 0;
     else if(!strcmp(arg[k], "-h") || !strcmp(arg[k], "--help"))
     {
-      fprintf(stderr, "usage: %s [--random] [--repeat]\n", arg[0]);
+      fprintf(stderr, "usage: %s [--random] [--repeat] [--window]\n", arg[0]);
       exit(0);
     }
+    else
+      dtview_option = 0;
+    if(dtview_option)
+      *arg[k] = 0; // prevent dt_init seeing this dtview-specific option
   }
   // init dt without gui:
   if(dt_init(argc, arg, 0, NULL)) exit(1);
@@ -299,13 +371,12 @@ int main(int argc, char *arg[])
   const gchar *overprofile = "X profile";
   dt_conf_set_string("plugins/lighttable/export/iccprofile", overprofile);
   running = init(argc, arg);
+  paused = 0;
   srand48(SDL_GetTicks());
   if(use_random) random_state = drand48() * INT_MAX;
   if(repeat < 0) repeat = random_state;
   while(running)
   {
-    pump_events();
-    if(!running) break;
     if(process_next_image())
     {
       if(repeat >= 0)
@@ -316,20 +387,20 @@ int main(int argc, char *arg[])
       }
       break;
     }
-    for(int k = 0; k <= 18; k++)
+    waiting = 1;
+    pump_events(); // any keyboard events since preparing next image?
+    for(int k = 0; k <= 18 && waiting && running; k++)
     {
       update(k);
-
-      struct timespec time = { 0, 10000000L };
-      nanosleep(&time, NULL);
+      wait_event(10, 0); // timeout, no auto-increment
     }
-    for(int k = 0; k < 100; k++)
-    {
-      pump_events();
-      if(!running) break;
 
-      struct timespec time = { 0, 35000000L };
-      nanosleep(&time, NULL);
+    if(waiting && running) // not interrupted by user?
+    {
+      if(paused)
+        wait_event(0, 0); // no timeout, no auto-increment
+      else
+        wait_event(35*100, 1); // timeout, auto-increment
     }
   }
   if(oldprofile)
-- 
1.9.1

Attachment: signature.asc
Description: OpenPGP digital signature

------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
darktable-devel mailing list
darktable-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/darktable-devel

Reply via email to