Пример #1
0
int32_t dt_control_add_job_res(dt_control_t *control, _dt_job_t *job, int32_t res)
{
  if(((unsigned int)res) >= DT_CTL_WORKER_RESERVED || !job)
  {
    dt_control_job_dispose(job);
    return 1;
  }

  // TODO: pthread cancel and restart in tough cases?
  dt_pthread_mutex_lock(&control->queue_mutex);

  // if there is a job in the queue we have to discard that first
  if(control->job_res[res])
  {
    dt_control_job_set_state(control->job_res[res], DT_JOB_STATE_DISCARDED);
    dt_control_job_dispose(control->job_res[res]);
  }

  dt_print(DT_DEBUG_CONTROL, "[add_job_res] %d | ", res);
  dt_control_job_print(job);
  dt_print(DT_DEBUG_CONTROL, "\n");

  dt_control_job_set_state(job, DT_JOB_STATE_QUEUED);
  control->job_res[res] = job;
  control->new_res[res] = 1;

  dt_pthread_mutex_unlock(&control->queue_mutex);

  dt_pthread_mutex_lock(&control->cond_mutex);
  pthread_cond_broadcast(&control->cond);
  dt_pthread_mutex_unlock(&control->cond_mutex);

  return 0;
}
Пример #2
0
dt_job_t *dt_camera_import_job_create(const char *jobcode, GList *images, struct dt_camera_t *camera,
                                      time_t time_override)
{
  dt_job_t *job = dt_control_job_create(&dt_camera_import_job_run, "import selected images from camera");
  if(!job) return NULL;
  dt_camera_import_t *params = dt_camera_import_alloc();
  if(!params)
  {
    dt_control_job_dispose(job);
    return NULL;
  }
  dt_control_job_add_progress(job, _("import images from camera"), FALSE);
  dt_control_job_set_params(job, params, dt_camera_import_cleanup);

  /* intitialize import session for camera import job */
  if(time_override != 0) dt_import_session_set_time(params->shared.session, time_override);
  dt_import_session_set_name(params->shared.session, jobcode);

  params->fraction = 0;
  params->images = g_list_copy(images);
  params->camera = camera;
  params->import_count = 0;
  params->job = job;
  return job;
}
Пример #3
0
static int32_t dt_control_run_job(dt_control_t *control)
{
  _dt_job_t *job = dt_control_schedule_job(control);

  if(!job) return -1;

  /* change state to running */
  dt_pthread_mutex_lock(&job->wait_mutex);
  if(dt_control_job_get_state(job) == DT_JOB_STATE_QUEUED)
  {
    dt_print(DT_DEBUG_CONTROL, "[run_job+] %02d %f ", DT_CTL_WORKER_RESERVED + dt_control_get_threadid(),
             dt_get_wtime());
    dt_control_job_print(job);
    dt_print(DT_DEBUG_CONTROL, "\n");

    dt_control_job_set_state(job, DT_JOB_STATE_RUNNING);

    /* execute job */
    job->result = job->execute(job);

    dt_control_job_set_state(job, DT_JOB_STATE_FINISHED);

    dt_print(DT_DEBUG_CONTROL, "[run_job-] %02d %f ", DT_CTL_WORKER_RESERVED + dt_control_get_threadid(),
             dt_get_wtime());
    dt_control_job_print(job);
    dt_print(DT_DEBUG_CONTROL, "\n");
  }

  /* free job */
  dt_pthread_mutex_unlock(&job->wait_mutex);
  dt_control_job_dispose(job);

  return 0;
}
Пример #4
0
void dt_lua_init(lua_State*L,const char *lua_command)
{
  /*
     Note to reviewers
     this is the only place where lua code is run without the lua lock.
     At this point, no user script has been called,
     so we are completely thread-safe. no need to lock

     This is also the only place where lua code is run with the gdk lock
     held, but this is not a problem because it is very brief, user calls
     are delegated to a secondary job
     */
  char tmp_path[PATH_MAX];
  // init the lua environment
  lua_CFunction* cur_type = init_funcs;
  while(*cur_type)
  {
    (*cur_type)(L);
    cur_type++;
  }
  // build the table containing the configuration info

  lua_getglobal(L,"package");
  dt_lua_goto_subtable(L,"loaded");
  lua_pushstring(L,"darktable");
  dt_lua_push_darktable_lib(L);
  lua_settable(L,-3);
  lua_pop(L,1);

  lua_getglobal(L,"package");
  lua_getfield(L,-1,"path");
  lua_pushstring(L,";");
  dt_loc_get_datadir(tmp_path, sizeof(tmp_path));
  lua_pushstring(L,tmp_path);
  lua_pushstring(L,"/lua/?.lua");
  lua_pushstring(L,";");
  dt_loc_get_user_config_dir(tmp_path, sizeof(tmp_path));
  lua_pushstring(L,tmp_path);
  lua_pushstring(L,"/lua/?.lua");
  lua_concat(L,7);
  lua_setfield(L,-2,"path");
  lua_pop(L,1);



  dt_job_t *job = dt_control_job_create(&run_early_script, "lua: run initial script");
  dt_control_job_set_params(job, g_strdup(lua_command));
  if(darktable.gui)
  {
    dt_control_add_job(darktable.control, DT_JOB_QUEUE_USER_BG, job);
  }
  else
  {
    run_early_script(job);
    dt_control_job_dispose(job);
  }

}
Пример #5
0
static void free_params_wrapper(struct dt_imageio_module_storage_t *self, dt_imageio_module_data_t *data)
{
  dt_job_t *job = dt_control_job_create(&free_param_wrapper_job, "lua: destroy storage param");
  if(!job) return;
  free_param_wrapper_data *t = (free_param_wrapper_data *)calloc(1, sizeof(free_param_wrapper_data));
  if(!t)
  {
    dt_control_job_dispose(job);
    return;
  }
  dt_control_job_set_params(job, t, free_param_wrapper_destroy);
  t->data = (lua_storage_t *)data;
  dt_control_add_job(darktable.control, DT_JOB_QUEUE_SYSTEM_BG, job);
}
Пример #6
0
dt_job_t * dt_image_load_job_create(int32_t id, dt_mipmap_size_t mip)
{
  dt_job_t *job = dt_control_job_create(&dt_image_load_job_run, "load image %d mip %d", id, mip);
  if(!job) return NULL;
  dt_image_load_t *params = (dt_image_load_t *)calloc(1, sizeof(dt_image_load_t));
  if(!params)
  {
    dt_control_job_dispose(job);
    return NULL;
  }
  dt_control_job_set_params(job, params);
  params->imgid = id;
  params->mip = mip;
  return job;
}
Пример #7
0
dt_job_t * dt_image_import_job_create(uint32_t filmid, const char *filename)
{
  dt_image_import_t *params;
  dt_job_t *job = dt_control_job_create(&dt_image_import_job_run, "import image");
  if(!job) return NULL;
  params = (dt_image_import_t *)calloc(1, sizeof(dt_image_import_t));
  if(!params)
  {
    dt_control_job_dispose(job);
    return NULL;
  }
  dt_control_job_set_params(job, params);
  params->filename = g_strdup(filename);
  params->film_id = filmid;
  return job;
}
Пример #8
0
static void on_image_imported(gpointer instance,uint32_t id, gpointer user_data){
  dt_job_t *job = dt_control_job_create(&on_image_imported_callback_job, "lua: on image imported");
  if(job)
  {
    on_image_imported_callback_data_t *t = (on_image_imported_callback_data_t*)calloc(1, sizeof(on_image_imported_callback_data_t));
    if(!t)
    {
      dt_control_job_dispose(job);
    }
    else
    {
      dt_control_job_set_params(job, t);
      t->imgid = id;
      dt_control_add_job(darktable.control, DT_JOB_QUEUE_USER_FG, job);
    }
  }
}
Пример #9
0
dt_job_t *dt_film_import1_create(dt_film_t *film)
{
  dt_job_t *job = dt_control_job_create(&dt_film_import1_run, "cache load raw images for preview");
  if(!job) return NULL;
  dt_film_import1_t *params = (dt_film_import1_t *)calloc(1, sizeof(dt_film_import1_t));
  if(!params)
  {
    dt_control_job_dispose(job);
    return NULL;
  }
  dt_control_job_add_progress(job, _("import images"), FALSE);
  dt_control_job_set_params(job, params, dt_film_import1_cleanup);
  params->film = film;
  dt_pthread_mutex_lock(&film->images_mutex);
  film->ref++;
  dt_pthread_mutex_unlock(&film->images_mutex);
  return job;
}
Пример #10
0
static void on_mouse_over_image_changed(gpointer instance, gpointer user_data)
{
  dt_job_t *job = dt_control_job_create(&on_mouse_over_image_changed_callback_job, "lua: on mouse over image changed");
  if(job)
  {
    on_mouse_over_image_changed_callback_data_t *t
        = (on_mouse_over_image_changed_callback_data_t *)calloc(1, sizeof(on_mouse_over_image_changed_callback_data_t));
    if(!t)
    {
      dt_control_job_dispose(job);
    }
    else
    {
      dt_control_job_set_params(job, t);
      t->imgid = dt_control_get_mouse_over_id();
      dt_control_add_job(darktable.control, DT_JOB_QUEUE_USER_FG, job);
    }
  }
}
Пример #11
0
dt_job_t *dt_camera_get_previews_job_create(dt_camera_t *camera, dt_camctl_listener_t *listener,
                                            uint32_t flags, void *data)
{
  dt_job_t *job = dt_control_job_create(&dt_camera_get_previews_job_run, "get camera previews job");
  if(!job) return NULL;
  dt_camera_get_previews_t *params = dt_camera_get_previews_alloc();
  if(!params)
  {
    dt_control_job_dispose(job);
    return NULL;
  }
  dt_control_job_set_params(job, params, dt_camera_get_previews_cleanup);

  memcpy(params->listener, listener, sizeof(dt_camctl_listener_t));

  params->camera = camera;
  params->flags = flags;
  params->data = data;
  return job;
}
Пример #12
0
static void on_view_changed(gpointer instance, dt_view_t *old_view, dt_view_t *new_view, gpointer user_data)
{
  dt_job_t *job = dt_control_job_create(&view_changed_callback_job, "lua: on view changed");
  if(job)
  {
    view_changed_callback_data_t *t
        = (view_changed_callback_data_t *)calloc(1, sizeof(view_changed_callback_data_t));
    if(!t)
    {
      dt_control_job_dispose(job);
    }
    else
    {
      dt_control_job_set_params(job, t);
      t->old_view = old_view;
      t->new_view = new_view;
      dt_control_add_job(darktable.control, DT_JOB_QUEUE_USER_FG, job);
    }
  }
}
Пример #13
0
static int32_t dt_control_run_job(dt_control_t *control)
{
  _dt_job_t *job = dt_control_schedule_job(control);

  if(!job) return -1;

  /* change state to running */
  dt_pthread_mutex_lock(&job->wait_mutex);
  if(dt_control_job_get_state(job) == DT_JOB_STATE_QUEUED)
  {
    dt_print(DT_DEBUG_CONTROL, "[run_job+] %02d %f ", DT_CTL_WORKER_RESERVED + dt_control_get_threadid(),
             dt_get_wtime());
    dt_control_job_print(job);
    dt_print(DT_DEBUG_CONTROL, "\n");

    dt_control_job_set_state(job, DT_JOB_STATE_RUNNING);

    /* execute job */
    job->result = job->execute(job);

    dt_control_job_set_state(job, DT_JOB_STATE_FINISHED);

    dt_print(DT_DEBUG_CONTROL, "[run_job-] %02d %f ", DT_CTL_WORKER_RESERVED + dt_control_get_threadid(),
             dt_get_wtime());
    dt_control_job_print(job);
    dt_print(DT_DEBUG_CONTROL, "\n");
  }

  dt_pthread_mutex_unlock(&job->wait_mutex);

  // remove the job from scheduled job array (for job deduping)
  dt_pthread_mutex_lock(&control->queue_mutex);
  control->job[dt_control_get_threadid()] = NULL;
  if(job->queue == DT_JOB_QUEUE_USER_EXPORT) control->export_scheduled = FALSE;
  dt_pthread_mutex_unlock(&control->queue_mutex);

  // and free it
  dt_control_job_dispose(job);

  return 0;
}
Пример #14
0
dt_job_t * dt_camera_capture_job_create(const char *jobcode, uint32_t delay, uint32_t count, uint32_t brackets, uint32_t steps)
{
  dt_job_t *job = dt_control_job_create(&dt_camera_capture_job_run, "remote capture of image(s)");
  if(!job) return NULL;
  dt_camera_capture_t *params = (dt_camera_capture_t *)calloc(1, sizeof(dt_camera_capture_t));
  if(!params)
  {
    dt_control_job_dispose(job);
    return NULL;
  }
  dt_control_job_set_params(job, params);

  params->shared.session = dt_import_session_new();
  dt_import_session_set_name(params->shared.session, jobcode);

  params->delay=delay;
  params->count=count;
  params->brackets=brackets;
  params->steps=steps;
  return job;
}
Пример #15
0
dt_job_t *dt_camera_capture_job_create(const char *jobcode, uint32_t delay, uint32_t count, uint32_t brackets,
                                       uint32_t steps)
{
  dt_job_t *job = dt_control_job_create(&dt_camera_capture_job_run, "remote capture of image(s)");
  if(!job) return NULL;
  dt_camera_capture_t *params = dt_camera_capture_alloc();
  if(!params)
  {
    dt_control_job_dispose(job);
    return NULL;
  }
  dt_control_job_add_progress(job, _("capture images"), FALSE);
  dt_control_job_set_params(job, params, dt_camera_capture_cleanup);

  dt_import_session_set_name(params->shared.session, jobcode);

  params->delay = delay;
  params->count = count;
  params->brackets = brackets;
  params->steps = steps;
  return job;
}
Пример #16
0
static int32_t dt_control_run_job_res(dt_control_t *control, int32_t res)
{
  if(((unsigned int)res) >= DT_CTL_WORKER_RESERVED) return -1;

  _dt_job_t *job = NULL;
  dt_pthread_mutex_lock(&control->queue_mutex);
  if(control->new_res[res])
  {
    job = control->job_res[res];
    control->job_res[res] = NULL; // this job belongs to us now, the queue may not touch it any longer
  }
  control->new_res[res] = 0;
  dt_pthread_mutex_unlock(&control->queue_mutex);
  if(!job) return -1;

  /* change state to running */
  dt_pthread_mutex_lock(&job->wait_mutex);
  if(dt_control_job_get_state(job) == DT_JOB_STATE_QUEUED)
  {
    dt_print(DT_DEBUG_CONTROL, "[run_job+] %02d %f ", res, dt_get_wtime());
    dt_control_job_print(job);
    dt_print(DT_DEBUG_CONTROL, "\n");

    dt_control_job_set_state(job, DT_JOB_STATE_RUNNING);

    /* execute job */
    job->result = job->execute(job);

    dt_control_job_set_state(job, DT_JOB_STATE_FINISHED);
    dt_print(DT_DEBUG_CONTROL, "[run_job-] %02d %f ", res, dt_get_wtime());
    dt_control_job_print(job);
    dt_print(DT_DEBUG_CONTROL, "\n");
  }
  dt_pthread_mutex_unlock(&job->wait_mutex);
  dt_control_job_dispose(job);
  return 0;
}
Пример #17
0
static int32_t dt_control_run_job(dt_control_t *control)
{
  _dt_job_t *job = dt_control_schedule_job(control);

  if(!job) return -1;

  /* change state to running */
  dt_pthread_mutex_lock(&job->wait_mutex);
  if(dt_control_job_get_state(job) == DT_JOB_STATE_QUEUED)
    dt_control_job_execute(job);

  dt_pthread_mutex_unlock(&job->wait_mutex);

  // remove the job from scheduled job array (for job deduping)
  dt_pthread_mutex_lock(&control->queue_mutex);
  control->job[dt_control_get_threadid()] = NULL;
  if(job->queue == DT_JOB_QUEUE_USER_EXPORT) control->export_scheduled = FALSE;
  dt_pthread_mutex_unlock(&control->queue_mutex);

  // and free it
  dt_control_job_dispose(job);

  return 0;
}
Пример #18
0
int dt_control_add_job(dt_control_t *control, dt_job_queue_t queue_id, _dt_job_t *job)
{
  if(((unsigned int)queue_id) >= DT_JOB_QUEUE_MAX || !job)
  {
    dt_control_job_dispose(job);
    return 1;
  }

  job->queue = queue_id;

  dt_pthread_mutex_lock(&control->queue_mutex);

  GList **queue = &control->queues[queue_id];
  size_t length = control->queue_length[queue_id];

  dt_print(DT_DEBUG_CONTROL, "[add_job] %ld | ", length);
  dt_control_job_print(job);
  dt_print(DT_DEBUG_CONTROL, "\n");

  if(queue_id == DT_JOB_QUEUE_SYSTEM_FG)
  {
    // this is a stack with limited size and bubble up and all that stuff
    job->priority = DT_CONTROL_FG_PRIORITY;

    // if the job is already in the queue -> move it to the top
    for(GList *iter = *queue; iter; iter = g_list_next(iter))
    {
      _dt_job_t *other_job = (_dt_job_t *)iter->data;
      if(dt_control_job_equal(job, other_job))
      {
        dt_print(DT_DEBUG_CONTROL, "[add_job] found job already in queue: ");
        dt_control_job_print(job);
        dt_print(DT_DEBUG_CONTROL, "\n");

        *queue = g_list_delete_link(*queue, iter);
        length--;
        dt_control_job_set_state(job, DT_JOB_STATE_DISCARDED);
        dt_control_job_dispose(job);
        job = other_job;
        break; // there can't be any further copy in the list
      }
    }

    // now we can add the new job to the list
    *queue = g_list_prepend(*queue, job);
    length++;

    // and take care of the maximal queue size
    if(length > DT_CONTROL_MAX_JOBS)
    {
      GList *last = g_list_last(*queue);
      dt_control_job_set_state((_dt_job_t *)last->data, DT_JOB_STATE_DISCARDED);
      *queue = g_list_delete_link(*queue, last);
      length--;
    }

    control->queue_length[queue_id] = length;
  }
  else
  {
    // the rest are FIFOs
    if(queue_id == DT_JOB_QUEUE_USER_BG || queue_id == DT_JOB_QUEUE_SYSTEM_BG)
      job->priority = 0;
    else
      job->priority = DT_CONTROL_FG_PRIORITY;
    *queue = g_list_append(*queue, job);
    control->queue_length[queue_id]++;
  }
  dt_control_job_set_state(job, DT_JOB_STATE_QUEUED);
  dt_pthread_mutex_unlock(&control->queue_mutex);

  // notify workers
  dt_pthread_mutex_lock(&control->cond_mutex);
  pthread_cond_broadcast(&control->cond);
  dt_pthread_mutex_unlock(&control->cond_mutex);

  return 0;
}
Пример #19
0
int dt_control_add_job(dt_control_t *control, dt_job_queue_t queue_id, _dt_job_t *job)
{
  if(((unsigned int)queue_id) >= DT_JOB_QUEUE_MAX || !job)
  {
    dt_control_job_dispose(job);
    return 1;
  }

  if(!control->running)
  {
    // whatever we are adding here won't be scheduled as the system isn't running. execute it synchronous instead.
    dt_pthread_mutex_lock(&job->wait_mutex); // is that even needed?
    dt_control_job_execute(job);
    dt_pthread_mutex_unlock(&job->wait_mutex);

    dt_control_job_dispose(job);
    return 0;
  }

  job->queue = queue_id;

  _dt_job_t *job_for_disposal = NULL;

  dt_pthread_mutex_lock(&control->queue_mutex);

  GList **queue = &control->queues[queue_id];
  size_t length = control->queue_length[queue_id];

  dt_print(DT_DEBUG_CONTROL, "[add_job] %zu | ", length);
  dt_control_job_print(job);
  dt_print(DT_DEBUG_CONTROL, "\n");

  if(queue_id == DT_JOB_QUEUE_SYSTEM_FG)
  {
    // this is a stack with limited size and bubble up and all that stuff
    job->priority = DT_CONTROL_FG_PRIORITY;

    // check if we have already scheduled the job
    for(int k = 0; k < control->num_threads; k++)
    {
      _dt_job_t *other_job = (_dt_job_t *)control->job[k];
      if(dt_control_job_equal(job, other_job))
      {
        dt_print(DT_DEBUG_CONTROL, "[add_job] found job already in scheduled: ");
        dt_control_job_print(other_job);
        dt_print(DT_DEBUG_CONTROL, "\n");

        dt_pthread_mutex_unlock(&control->queue_mutex);

        dt_control_job_set_state(job, DT_JOB_STATE_DISCARDED);
        dt_control_job_dispose(job);

        return 0; // there can't be any further copy
      }
    }

    // if the job is already in the queue -> move it to the top
    for(GList *iter = *queue; iter; iter = g_list_next(iter))
    {
      _dt_job_t *other_job = (_dt_job_t *)iter->data;
      if(dt_control_job_equal(job, other_job))
      {
        dt_print(DT_DEBUG_CONTROL, "[add_job] found job already in queue: ");
        dt_control_job_print(other_job);
        dt_print(DT_DEBUG_CONTROL, "\n");

        *queue = g_list_delete_link(*queue, iter);
        length--;

        job_for_disposal = job;

        job = other_job;
        break; // there can't be any further copy in the list
      }
    }

    // now we can add the new job to the list
    *queue = g_list_prepend(*queue, job);
    length++;

    // and take care of the maximal queue size
    if(length > DT_CONTROL_MAX_JOBS)
    {
      GList *last = g_list_last(*queue);
      dt_control_job_set_state((_dt_job_t *)last->data, DT_JOB_STATE_DISCARDED);
      dt_control_job_dispose((_dt_job_t *)last->data);
      *queue = g_list_delete_link(*queue, last);
      length--;
    }

    control->queue_length[queue_id] = length;
  }
  else
  {
    // the rest are FIFOs
    if(queue_id == DT_JOB_QUEUE_USER_BG ||
       queue_id == DT_JOB_QUEUE_USER_EXPORT ||
       queue_id == DT_JOB_QUEUE_SYSTEM_BG)
      job->priority = 0;
    else
      job->priority = DT_CONTROL_FG_PRIORITY;
    *queue = g_list_append(*queue, job);
    control->queue_length[queue_id]++;
  }
  dt_control_job_set_state(job, DT_JOB_STATE_QUEUED);
  dt_pthread_mutex_unlock(&control->queue_mutex);

  // notify workers
  dt_pthread_mutex_lock(&control->cond_mutex);
  pthread_cond_broadcast(&control->cond);
  dt_pthread_mutex_unlock(&control->cond_mutex);

  // dispose of dropped job, if any
  dt_control_job_set_state(job_for_disposal, DT_JOB_STATE_DISCARDED);
  dt_control_job_dispose(job_for_disposal);

  return 0;
}