Commit 952e93d8 authored by Henrik Andersson's avatar Henrik Andersson

Added a new request_image_filename listener interface function for camctl

Updated gconf schema to use Pascal's namingconvention for directorystructure @ import
Change import job to support variables in path and filename
Change import dialog to actually support the new strings for forwarding to job init
Update capture to construct import path string and initialize import job
Updated default values for import  at init in control.c
Change semantics when import in camctl to support requesting listener for new filename at import.
parent b9820ee3
......@@ -175,7 +175,7 @@
<applyto>/apps/darktable/capture/camera/storage/subpath</applyto>
<owner>darktable</owner>
<type>string</type>
<default>$(EXIF_YEAR)/$(EXIF_YEAR)$(EXIF_MONTH)$(EXIF_DAY)/$(JOBID)</default>
<default>$(YEAR)$(MONTH)$(DAY)_$(JOBCODE)</default>
<gettext_domain>darktable</gettext_domain>
<locale name="C">
<short>subpath pattern in storage for captured camera images</short>
......@@ -188,7 +188,7 @@
<applyto>/apps/darktable/capture/camera/storage/namepattern</applyto>
<owner>darktable</owner>
<type>string</type>
<default>$(EXIF_YEAR)$(EXIF_MONTH)$(EXIF_DAY)-$(EXIF_HOUR)$(EXIF_MINUTE)_$(IMPORT_SEQUENCE)-f$(EXIF_APERTURE)_iso$(EXIF_ISO)</default>
<default>$(YEAR)$(MONTH)$(DAY)_$(SEQUENCE).$(FILE_EXTENSION)</default>
<gettext_domain>darktable</gettext_domain>
<locale name="C">
<short>rename pattern for captured images</short>
......@@ -201,7 +201,7 @@
<applyto>/apps/darktable/capture/camera/import/jobcode</applyto>
<owner>darktable</owner>
<type>string</type>
<default>default</default>
<default>noname</default>
<gettext_domain>darktable</gettext_domain>
<locale name="C">
<short>jobcode of import job</short>
......
......@@ -36,6 +36,7 @@ void _camctl_unlock(const dt_camctl_t *c);
/** Dispatch functions for listener interfaces */
const char *_dispatch_request_image_path(const dt_camctl_t *c,const dt_camera_t *camera);
const char *_dispatch_request_image_filename(const dt_camctl_t *c,const char *filename,const dt_camera_t *camera);
void _dispatch_camera_image_downloaded(const dt_camctl_t *c,const dt_camera_t *camera,const char *filename);
void _dispatch_camera_connected(const dt_camctl_t *c,const dt_camera_t *camera);
void _dispatch_camera_disconnected(const dt_camctl_t *c,const dt_camera_t *camera);
......@@ -301,23 +302,28 @@ void dt_camctl_import(const dt_camctl_t *c,const dt_camera_t *cam,GList *images)
strncat(folder,file,eos-file);
strcat(filename,eos+1);
char outputfile[4096]={0};
const char *fname = _dispatch_request_image_filename(c,filename,cam);
if(!fname) fname=filename;
/*char outputfile[4096]={0};
strcat(outputfile,output_path);
if(outputfile[strlen(outputfile)]!='/') strcat(outputfile,"/");
strcat(outputfile,filename);
strcat(outputfile,filename);*/
char *output = g_build_filename(output_path,fname,NULL);
// Now we have filenames lets download file and notify listener of image download
CameraFile *destination;
int handle = open( outputfile, O_CREAT | O_WRONLY,0666);
int handle = open( output, O_CREAT | O_WRONLY,0666);
if( handle > 0 ) {
gp_file_new_from_fd( &destination , handle );
if( gp_camera_file_get( cam->gpcam, folder , filename, GP_FILE_TYPE_NORMAL, destination, c->gpcontext) == GP_OK)
{
close( handle );
_dispatch_camera_image_downloaded(c,cam,outputfile);
_dispatch_camera_image_downloaded(c,cam,output);
}
else
dt_print(DT_DEBUG_CAMCTL,"[camera_control] Failed to download file %s\n",outputfile);
dt_print(DT_DEBUG_CAMCTL,"[camera_control] Failed to download file %s\n",output);
}
......@@ -484,6 +490,21 @@ void _camera_poll_events(const dt_camctl_t *c,const dt_camera_t *cam)
}
}
const char *_dispatch_request_image_filename(const dt_camctl_t *c,const char *filename,const dt_camera_t *camera)
{
dt_camctl_t *camctl=(dt_camctl_t *)c;
GList *listener;
const char *path=NULL;
if((listener=g_list_first(camctl->listeners))!=NULL)
do
{
if( ((dt_camctl_listener_t*)listener->data)->request_image_filename != NULL )
path=((dt_camctl_listener_t*)listener->data)->request_image_filename(camera,filename,((dt_camctl_listener_t*)listener->data)->data);
} while((listener=g_list_next(listener))!=NULL);
return path;
}
const char *_dispatch_request_image_path(const dt_camctl_t *c,const dt_camera_t *camera)
{
dt_camctl_t *camctl=(dt_camctl_t *)c;
......
......@@ -87,6 +87,10 @@ typedef struct dt_camctl_listener_t
/** Invoked before images are fetched from camera and when tethered capture fetching an image. \note That only one listener should implement this... */
const char * (*request_image_path)(const dt_camera_t *camera,void *data);
/** Invoked before images are fetched from camera and when tethered capture fetching an image. \note That only one listener should implement this... */
const char * (*request_image_filename)(const dt_camera_t *camera,const char *filename,void *data);
/** Invoked when a image is downloaded while in tethered mode or by import */
void (*image_downloaded)(const dt_camera_t *camera,const char *filename,void *data);
......
......@@ -59,7 +59,7 @@ gchar *_string_substitute(gchar *string,const gchar *search,const gchar *replace
gchar *nstring=g_malloc(strlen(string)+(sl*occurences)+1);
gchar *np=nstring;
gchar *s=string,*p=string;
fprintf(stderr,"replace %s with %s strdiff %d, occurences %d, oldstring %d, newstring %d\n",search,replace,sl,occurences,strlen(string),strlen(string)+(sl*occurences)+1);
//fprintf(stderr,"replace %s with %s strdiff %d, occurences %d, oldstring %d, newstring %d\n",search,replace,sl,occurences,strlen(string),strlen(string)+(sl*occurences)+1);
if( (s=g_strstr_len(s,strlen(s),search)) != NULL)
{
do
......@@ -195,7 +195,7 @@ gboolean dt_variables_expand(dt_variables_params_t *params, gchar *string, gbool
{
if( (result=_string_substitute(params->data->result,variable,value)) != params->data->result && result != params->data->source)
{ // we got a result
fprintf(stderr,"Got result: %s\n",result);
//fprintf(stderr,"Got result: %s\n",result);
if( params->data->result != params->data->source)
g_free(params->data->result);
params->data->result=result;
......
......@@ -26,10 +26,10 @@ typedef struct dt_variables_params_t
gboolean validate_only;
/** Used for expanding variables that uses filename $(FILE_NAME) and $(FILE_EXTENSION). */
gchar *filename;
const gchar *filename;
/** Used for expanding variable $(JOBCODE) */
gchar *jobcode;
const gchar *jobcode;
/** Used for expanding variables such as $(IMAGE_WIDTH) $(IMAGE_HEIGT). */
struct dt_image_t *img;
......
......@@ -83,9 +83,9 @@ void dt_ctl_settings_default(dt_control_t *c)
// Import settings
dt_conf_set_string ("capture/camera/storage/basedirectory", "$(PICTURES_FOLDER)/darktable");
dt_conf_set_string ("capture/camera/storage/subpath", "$(EXIF_YEAR)/$(EXIF_YEAR)$(EXIF_MONTH)$(EXIF_DAY)/$(JOBCODE)");
dt_conf_set_string ("capture/camera/storage/namepattern", "$(EXIF_YEAR)$(EXIF_MONTH)$(EXIF_DAY)-$(EXIF_HOUR)$(EXIF_MINUTE)_$(IMPORT_SEQUENCE)-f$(EXIF_APERTURE)_iso$(EXIF_ISO)");
dt_conf_set_string ("capture/camera/import/jobcode", "default");
dt_conf_set_string ("capture/camera/storage/subpath", "$(YEAR)$(MONTH)$(DAY)_$(JOBCODE)");
dt_conf_set_string ("capture/camera/storage/namepattern", "$(YEAR)$(MONTH)$(DAY)_$(SEQUENCE).$(FILE_EXTENSION)");
dt_conf_set_string ("capture/camera/import/jobcode", "noname");
dt_conf_set_float("gamma_linear", .1f);
dt_conf_set_float("gamma_gamma", .45f);
......
......@@ -66,14 +66,18 @@ void dt_captured_image_import_job_init(dt_job_t *job, const char *filename)
t->filename=g_strdup(filename);
}
void dt_camera_import_job_init(dt_job_t *job,char *path, GList *images,dt_camera_t *camera)
void dt_camera_import_job_init(dt_job_t *job,char *jobcode, char *path,char *filename,GList *images, struct dt_camera_t *camera)
{
dt_control_job_init(job, "import selected images from camera");
job->execute = &dt_camera_import_job_run;
dt_camera_import_t *t = (dt_camera_import_t *)job->param;
dt_variables_params_init(&t->vp);
t->images=g_list_copy(images);
t->camera=camera;
t->import_path=g_strdup(path);
t->vp->jobcode=g_strdup(jobcode);
t->path=g_strdup(path);
t->filename=g_strdup(filename);
}
void _camera_image_downloaded(const dt_camera_t *camera,const char *filename,void *data)
......@@ -82,9 +86,19 @@ void _camera_image_downloaded(const dt_camera_t *camera,const char *filename,voi
dt_camera_import_t *t = (dt_camera_import_t *)data;
dt_film_image_import(t->film,filename);
dt_control_log(_("file %s imported from camera."), filename);
fprintf(stderr,"File downloaded: %s\n",filename);
}
const char *_camera_request_image_filename(const dt_camera_t *camera,const char *filename,void *data)
{
dt_camera_import_t *t = (dt_camera_import_t *)data;
t->vp->filename=filename;
dt_variables_expand( t->vp, t->filename, TRUE );
return dt_variables_get_result(t->vp);
}
const char *_camera_request_image_path(const dt_camera_t *camera,void *data)
{
// :) yeap this is kind of stupid yes..
......@@ -98,14 +112,12 @@ void dt_camera_import_job_run(dt_job_t *job)
dt_control_log(_("starting import job of images from camera"));
// Setup a new filmroll to import images to....
char buffer[512]={0};
t->film=(dt_film_t*)g_malloc(sizeof(dt_film_t));
dt_film_init(t->film);
const time_t tim=time(NULL);
struct tm *ts=localtime(&tim);
strftime(buffer,512,"%Y-%m-%d camera import",ts);
sprintf(t->film->dirname,"%s/%s",t->import_path,buffer);
dt_variables_expand( t->vp, t->path, FALSE );
sprintf(t->film->dirname,"%s",dt_variables_get_result(t->vp));
pthread_mutex_lock(&t->film->images_mutex);
t->film->ref++;
......@@ -140,11 +152,15 @@ void dt_camera_import_job_run(dt_job_t *job)
listener.data=t;
listener.image_downloaded=_camera_image_downloaded;
listener.request_image_path=_camera_request_image_path;
listener.request_image_filename=_camera_request_image_filename;
// start download of images
dt_camctl_register_listener(darktable.camctl,&listener);
dt_camctl_import(darktable.camctl,t->camera,t->images);
dt_camctl_unregister_listener(darktable.camctl,&listener);
dt_variables_params_destroy(t->vp);
}
else
dt_control_log(_("failed to create filmroll for camera import, import of images aborted."));
......
......@@ -21,6 +21,7 @@
#include <glib.h>
#include "common/image.h"
#include "common/variables.h"
#include "control/control.h"
#include "common/film.h"
#include "develop/develop.h"
......@@ -48,12 +49,14 @@ typedef struct dt_camera_import_t
{
GList *images;
struct dt_camera_t *camera;
char *import_path;
dt_variables_params_t *vp;
dt_film_t *film;
gchar *path;
gchar *filename;
}
dt_camera_import_t;
void dt_camera_import_job_run(dt_job_t *job);
void dt_camera_import_job_init(dt_job_t *job, char *path,GList *images, struct dt_camera_t *camera);
void dt_camera_import_job_init(dt_job_t *job,char *jobcode, char *path,char *filename,GList *images, struct dt_camera_t *camera);
typedef struct dt_film_import1_t
......
......@@ -36,6 +36,15 @@
*/
typedef struct _camera_gconf_widget_t
{
GtkWidget *widget;
GtkWidget *entry;
gchar *value;
}
_camera_gconf_widget_t;
typedef struct _camera_import_dialog_t {
GtkWidget *dialog;
......@@ -43,16 +52,16 @@ typedef struct _camera_import_dialog_t {
struct {
GtkWidget *page;
GtkWidget *jobname;
_camera_gconf_widget_t *jobname;
GtkWidget *treeview;
GtkWidget *info;
} import;
struct {
GtkWidget *page;
GtkWidget *basedirectory;
GtkWidget *subdirectory;
GtkWidget *namepattern;
_camera_gconf_widget_t *basedirectory;
_camera_gconf_widget_t *subdirectory;
_camera_gconf_widget_t *namepattern;
} settings;
GtkListStore *store;
......@@ -62,12 +71,6 @@ typedef struct _camera_import_dialog_t {
}
_camera_import_dialog_t;
typedef struct _camera_gconf_widget_t
{
GtkWidget *widget;
GtkWidget *entry;
}
_camera_gconf_widget_t;
......@@ -80,7 +83,8 @@ store_callback (GtkDarktableButton *button, gpointer user_data)
if(newvalue && strlen(newvalue) > 0 )
{
dt_conf_set_string(configstring,newvalue);
g_object_set_data(G_OBJECT(gcw->widget),"gconf:value",(gchar *)newvalue);
if(gcw->value) g_free(gcw->value);
gcw->value=g_strdup(newvalue);
}
}
......@@ -92,21 +96,35 @@ reset_callback (GtkDarktableButton *button, gpointer user_data)
gchar *value=dt_conf_get_string(configstring);
if(value) {
gtk_entry_set_text( GTK_ENTRY( gcw->entry ),value);
g_object_set_data(G_OBJECT(gcw->widget),"gconf:value",value);
if(gcw->value) g_free(gcw->value);
gcw->value=g_strdup(value);
}
}
static gboolean
entry_keypress_callback(GtkWidget *widget,GdkEventKey *event,gpointer data)
static void
_entry_text_changed(_camera_gconf_widget_t *gcw,GtkEntryBuffer *entrybuffer)
{
fprintf(stderr,"Entry changed: %s\n",gtk_entry_get_text(GTK_ENTRY(widget)));
g_object_set_data(G_OBJECT( ((_camera_gconf_widget_t *)data)->widget),"gconf:value",(gchar *)gtk_entry_get_text(GTK_ENTRY(widget)));
return FALSE;
const gchar *value=gtk_entry_buffer_get_text(entrybuffer);
//fprintf(stderr,"Entry changed: %s\n",value);
if(gcw->value) g_free(gcw->value);
gcw->value=g_strdup(value);
}
static void
entry_dt_callback(GtkEntryBuffer *entrybuffer,guint a1, guint a2,gpointer user_data)
{
_entry_text_changed((_camera_gconf_widget_t*)user_data,entrybuffer);
}
static void
entry_it_callback(GtkEntryBuffer *entrybuffer,guint a1, gchar *a2, guint a3,gpointer user_data)
{
_entry_text_changed((_camera_gconf_widget_t*)user_data,entrybuffer);
}
GtkWidget *_camera_import_gconf_widget(gchar *label,gchar *confstring)
_camera_gconf_widget_t *_camera_import_gconf_widget(gchar *label,gchar *confstring)
{
_camera_gconf_widget_t *gcw=malloc(sizeof(_camera_gconf_widget_t));
......@@ -120,11 +138,13 @@ GtkWidget *_camera_import_gconf_widget(gchar *label,gchar *confstring)
if( dt_conf_get_string (confstring) )
{
gtk_entry_set_text( GTK_ENTRY( gcw->entry ),dt_conf_get_string (confstring));
g_object_set_data(G_OBJECT(vbox),"gconf:value",dt_conf_get_string (confstring));
gcw->value=g_strdup(dt_conf_get_string (confstring));
}
g_signal_connect (G_OBJECT (gcw->entry), "key-press-event",
G_CALLBACK (entry_keypress_callback), gcw);
g_signal_connect (G_OBJECT(gtk_entry_get_buffer(GTK_ENTRY(gcw->entry))), "inserted-text",
G_CALLBACK (entry_it_callback), gcw);
g_signal_connect (G_OBJECT(gtk_entry_get_buffer(GTK_ENTRY(gcw->entry))), "deleted-text",
G_CALLBACK (entry_dt_callback), gcw);
gtk_box_pack_start(GTK_BOX(hbox),GTK_WIDGET(gcw->entry),TRUE,TRUE,0);
......@@ -149,7 +169,7 @@ GtkWidget *_camera_import_gconf_widget(gchar *label,gchar *confstring)
gtk_box_pack_start(GTK_BOX(vbox),GTK_WIDGET(hbox),FALSE,FALSE,0);
return vbox;
return gcw;
}
void _camera_import_dialog_new(_camera_import_dialog_t *data) {
......@@ -172,7 +192,7 @@ void _camera_import_dialog_new(_camera_import_dialog_t *data) {
// GtkBox *hbox=GTK_BOX(gtk_hbox_new(FALSE,2));
data->import.jobname=_camera_import_gconf_widget(_("jobcode"),"capture/camera/import/jobcode");
gtk_box_pack_start(GTK_BOX(data->import.page),GTK_WIDGET(data->import.jobname),FALSE,FALSE,0);
gtk_box_pack_start(GTK_BOX(data->import.page),GTK_WIDGET(data->import.jobname->widget),FALSE,FALSE,0);
// Create the treview with list model data store
......@@ -206,14 +226,14 @@ void _camera_import_dialog_new(_camera_import_dialog_t *data) {
data->settings.basedirectory=_camera_import_gconf_widget(_("storage directory"),"capture/camera/storage/basedirectory");
gtk_box_pack_start(GTK_BOX(data->settings.page),GTK_WIDGET(data->settings.basedirectory),FALSE,FALSE,0);
gtk_box_pack_start(GTK_BOX(data->settings.page),GTK_WIDGET(data->settings.basedirectory->widget),FALSE,FALSE,0);
data->settings.subdirectory=_camera_import_gconf_widget(_("directory structure"),"capture/camera/storage/subpath");
gtk_box_pack_start(GTK_BOX(data->settings.page),GTK_WIDGET(data->settings.subdirectory),FALSE,FALSE,0);
gtk_box_pack_start(GTK_BOX(data->settings.page),GTK_WIDGET(data->settings.subdirectory->widget),FALSE,FALSE,0);
data->settings.namepattern=_camera_import_gconf_widget(_("filename structure"),"capture/camera/storage/namepattern");
gtk_box_pack_start(GTK_BOX(data->settings.page),GTK_WIDGET(data->settings.namepattern),FALSE,FALSE,0);
gtk_box_pack_start(GTK_BOX(data->settings.page),GTK_WIDGET(data->settings.namepattern->widget),FALSE,FALSE,0);
......@@ -295,7 +315,8 @@ void _camera_import_dialog_run(_camera_import_dialog_t *data)
if( result == GTK_RESPONSE_ACCEPT)
{
GtkTreeIter iter;
all_good=TRUE;
// Now build up result from store into GList **result
if(data->params->result)
g_list_free(data->params->result);
......@@ -315,19 +336,36 @@ void _camera_import_dialog_run(_camera_import_dialog_t *data)
}
// Lets check jobcode, basedir etc..
data->params->jobcode = g_object_get_data(G_OBJECT(data->import.jobname),"gconf:value");
data->params->basedirectory = g_object_get_data(G_OBJECT(data->settings.basedirectory),"gconf:value");
data->params->jobcode = data->import.jobname->value;
data->params->basedirectory = data->settings.basedirectory->value;
data->params->subdirectory = data->settings.subdirectory->value;
data->params->filenamepattern = data->settings.namepattern->value;
if( data->params->jobcode == NULL || strlen(data->params->jobcode) <=0 )
data->params->jobcode = dt_conf_get_string("capture/camera/import/jobcode");
if( data->params->basedirectory != NULL && strlen( data->params->basedirectory ) > 0 ) all_good=TRUE;
else
if( data->params->basedirectory == NULL || strlen( data->params->basedirectory ) <= 0 )
{
GtkWidget *dialog=gtk_message_dialog_new(NULL,GTK_DIALOG_DESTROY_WITH_PARENT,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_("please set the basedirectory settings before importing"));
g_signal_connect_swapped (dialog, "response",G_CALLBACK (gtk_widget_destroy),dialog);
gtk_dialog_run (GTK_DIALOG (dialog));
all_good=FALSE;
}
else if( data->params->subdirectory == NULL || strlen( data->params->subdirectory ) <= 0 )
{
GtkWidget *dialog=gtk_message_dialog_new(NULL,GTK_DIALOG_DESTROY_WITH_PARENT,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_("please set the subdirectory settings before importing"));
g_signal_connect_swapped (dialog, "response",G_CALLBACK (gtk_widget_destroy),dialog);
gtk_dialog_run (GTK_DIALOG (dialog));
all_good=FALSE;
}
else if( data->params->filenamepattern == NULL || strlen( data->params->filenamepattern ) <= 0 )
{
GtkWidget *dialog=gtk_message_dialog_new(NULL,GTK_DIALOG_DESTROY_WITH_PARENT,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_("please set the filenamepattern settings before importing"));
g_signal_connect_swapped (dialog, "response",G_CALLBACK (gtk_widget_destroy),dialog);
gtk_dialog_run (GTK_DIALOG (dialog));
all_good=FALSE;
}
}
else
{
......
......@@ -28,7 +28,8 @@ typedef struct dt_camera_import_dialog_param_t
dt_camera_t *camera;
gchar *jobcode;
gchar *basedirectory;
gchar *subdirectory;
gchar *filenamepattern;
/** Filenames of selected images to import*/
GList *result;
}
......
......@@ -82,22 +82,19 @@ static void detect_source_callback(GtkButton *button,gpointer data)
static void import_callback(GtkButton *button,gpointer data)
{
dt_camera_import_dialog_param_t params={0};
params.camera = (dt_camera_t*)data;
dt_camera_import_dialog_param_t *params=(dt_camera_import_dialog_param_t *)g_malloc(sizeof(dt_camera_import_dialog_param_t));
params->camera = (dt_camera_t*)data;
dt_camera_import_dialog_new(&params);
if( params.result )
dt_camera_import_dialog_new(params);
if( params->result )
{
char path[4096]={0};
// Let's expand the basedirectory and construct full path of import
//sprintf(path,"%s/%s",params.basedirectory,params.jobcode);
sprintf(path,"/tmp/import");
gchar *path = g_build_path(G_DIR_SEPARATOR_S,params->basedirectory,params->subdirectory,NULL);
dt_job_t j;
dt_camera_import_job_init(&j,path,params.result,params.camera);
dt_camera_import_job_init(&j,params->jobcode,path,params->filenamepattern,params->result,params->camera);
dt_control_add_job(darktable.control, &j);
g_free(path);
g_free(params);
}
}
......@@ -120,12 +117,6 @@ static void tethered_callback(GtkToggleButton *button,gpointer data)
void dt_gui_capture_init()
{
/* dt_string_params_t params;
params.time=time(NULL);
params.jobcode="Studio_shoot2";
params.source="$(PICTURES_FOLDER)/$(YEAR)$(MONTH)$(DAY)_$(JOBCODE)/HA_$(YEAR)$(MONTH)$(DAY)_$(SEQUENCE)";
dt_variables_expand( &params );
fprintf(stderr,"result: '%s'\n",params.result);*/
memset(&_gui_camctl_listener,0,sizeof(dt_camctl_listener_t));
_gui_camctl_listener.control_status= _camctl_camera_control_status_callback;
dt_camctl_register_listener( darktable.camctl, &_gui_camctl_listener );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment