plug-ins: fix #3854 by porting twain to the new plugin framework.

Removed the WinMain specific stuff for the plug-in and determine
hInstance in twainMain which made porting a lot easier.

The _DEBUG enabled functions I have mostly left alone and
should be revised at a later time.
This commit is contained in:
Jacob Boerema 2020-09-18 17:47:42 -04:00
parent b3bed72d84
commit d0b1c143b6
4 changed files with 153 additions and 207 deletions

View File

@ -31,7 +31,4 @@
#define DUMP_NAME "DTWAIN.EXE" #define DUMP_NAME "DTWAIN.EXE"
#define READDUMP_NAME "RTWAIN.EXE" #define READDUMP_NAME "RTWAIN.EXE"
/* Windows uses separate entry point */
#define TWAIN_ALTERNATE_MAIN
#endif #endif

View File

@ -40,7 +40,6 @@ LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int twainMessageLoop(pTW_SESSION); int twainMessageLoop(pTW_SESSION);
int TwainProcessMessage(LPMSG lpMsg, pTW_SESSION twSession); int TwainProcessMessage(LPMSG lpMsg, pTW_SESSION twSession);
extern GimpPlugInInfo PLUG_IN_INFO;
extern pTW_SESSION initializeTwain (); extern pTW_SESSION initializeTwain ();
#ifdef _DEBUG #ifdef _DEBUG
extern void setRunMode(char *argv[]); extern void setRunMode(char *argv[]);
@ -253,78 +252,16 @@ LogLastWinError(void)
LocalFree( lpMsgBuf ); LocalFree( lpMsgBuf );
} }
void twainQuitApplication () void twainQuitApplication (void)
{ {
PostQuitMessage (0); PostQuitMessage (0);
} }
/****************************************************************** /******************************************************************
* Win32 entry point and setup... * Win32 setup...
******************************************************************/ ******************************************************************/
/*
* WinMain
*
* The standard gimp entry point won't quite cut it for
* this plug-in. This plug-in requires creation of a
* standard Win32 window (hidden) in order to receive
* and process window messages on behalf of the TWAIN
* datasource.
*/
int APIENTRY
WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
/*
* Normally, we would do all of the Windows-ish set up of
* the window classes and stuff here in WinMain. But,
* the only time we really need the window and message
* queues is during the plug-in run. So, all of that will
* be done during run(). This avoids all of the Windows
* setup stuff for the query(). Stash the instance handle now
* so it is available from the run() procedure.
*/
hInst = hInstance;
#ifdef _DEBUG
/* When in debug version, we allow different run modes...
* make sure that it is correctly set.
*/
setRunMode(__argv);
#endif /* _DEBUG */
/*
* Now, call gimp_main_legacy... This is what the MAIN() macro
* would usually do.
*/
return gimp_main_legacy(&PLUG_IN_INFO, __argc, __argv);
}
/*
* main
*
* allow to build as console app as well
*/
int main (int argc, char *argv[])
{
#ifdef _DEBUG
/* When in debug version, we allow different run modes...
* make sure that it is correctly set.
*/
setRunMode(__argv);
#endif /* _DEBUG */
/*
* Now, call gimp_main_legacy... This is what the MAIN() macro
* would usually do.
*/
return gimp_main_legacy(&PLUG_IN_INFO, __argc, __argv);
}
/* /*
* InitApplication * InitApplication
* *
@ -403,11 +340,16 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, pTW_SESSION twSession)
* operate. * operate.
*/ */
int int
twainMain() twainMain (void)
{ {
/* Initialize the twain information */ /* Initialize the twain information */
pTW_SESSION twSession = initializeTwain(); pTW_SESSION twSession = initializeTwain();
/* Since we are not using our own WinMain anymore where we
could get hInst we get it here using GetModuleHandle. */
if (!hInst)
hInst = GetModuleHandle(NULL);
/* Perform instance initialization */ /* Perform instance initialization */
if (!InitApplication(hInst)) if (!InitApplication(hInst))
return (FALSE); return (FALSE);

View File

@ -84,9 +84,9 @@
*/ */
#define PLUG_IN_NAME "twain-acquire" #define PLUG_IN_NAME "twain-acquire"
#define PLUG_IN_DESCRIPTION N_("Capture an image from a TWAIN datasource") #define PLUG_IN_DESCRIPTION N_("Capture an image from a TWAIN datasource")
#define PLUG_IN_HELP "This plug-in will capture an image from a TWAIN datasource" #define PLUG_IN_HELP N_("This plug-in will capture an image from a TWAIN datasource")
#define PLUG_IN_AUTHOR "Craig Setera (setera@home.com)" #define PLUG_IN_AUTHOR "Craig Setera (setera@home.com)"
#define PLUG_IN_COPYRIGHT "Craig Setera" #define PLUG_IN_COPYRIGHT "Copyright 2004 by Craig Setera"
#define PLUG_IN_VERSION "v0.6 (07/22/2004)" #define PLUG_IN_VERSION "v0.6 (07/22/2004)"
#ifdef _DEBUG #ifdef _DEBUG
@ -126,23 +126,102 @@ int endTransferCallback (int completionState,
void postTransferCallback (int pendingCount, void postTransferCallback (int pendingCount,
void *clientData); void *clientData);
static void query (void);
static void run (const gchar *name,
gint nparams,
const GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals);
typedef struct _Twain Twain;
typedef struct _TwainClass TwainClass;
const GimpPlugInInfo PLUG_IN_INFO = struct _Twain
{ {
NULL, /* init_proc */ GimpPlugIn parent_instance;
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
}; };
extern void set_gimp_PLUG_IN_INFO_PTR (GimpPlugInInfo *); struct _TwainClass
{
GimpPlugInClass parent_class;
};
#define TWAIN_TYPE (twain_get_type ())
#define TWAIN (obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TWAIN_TYPE, Twain))
GType twain_get_type (void) G_GNUC_CONST;
static GList * twain_query_procedures (GimpPlugIn *plug_in);
static GimpProcedure * twain_create_procedure (GimpPlugIn *plug_in,
const gchar *name);
static GimpValueArray * twain_run (GimpProcedure *procedure,
GimpRunMode run_mode,
GimpImage *image,
GimpDrawable *drawable,
const GimpValueArray *args,
gpointer run_data);
G_DEFINE_TYPE (Twain, twain, GIMP_TYPE_PLUG_IN)
GIMP_MAIN (TWAIN_TYPE)
static void
twain_class_init (TwainClass *klass)
{
GimpPlugInClass *plug_in_class = GIMP_PLUG_IN_CLASS (klass);
plug_in_class->query_procedures = twain_query_procedures;
plug_in_class->create_procedure = twain_create_procedure;
}
static void
twain_init (Twain *twain)
{
}
static GList *
twain_query_procedures (GimpPlugIn *plug_in)
{
return g_list_append (NULL, g_strdup (PLUG_IN_NAME));
}
static GimpProcedure *
twain_create_procedure (GimpPlugIn *plug_in,
const gchar *name)
{
GimpProcedure *procedure = NULL;
if (! strcmp (name, PLUG_IN_NAME))
{
procedure = gimp_image_procedure_new (plug_in, name,
GIMP_PDB_PROC_TYPE_PLUGIN,
twain_run, NULL, NULL);
gimp_procedure_set_image_types (procedure, "*");
gimp_procedure_set_menu_label (procedure, N_("_Scanner/Camera..."));
gimp_procedure_add_menu_path (procedure, "<Image>/File/Create/Acquire");
gimp_procedure_set_documentation (procedure,
PLUG_IN_DESCRIPTION,
PLUG_IN_HELP,
name);
gimp_procedure_set_attribution (procedure,
PLUG_IN_AUTHOR,
PLUG_IN_COPYRIGHT,
PLUG_IN_VERSION);
GIMP_PROC_VAL_INT (procedure, "image-count",
"Number of acquired images",
"Number of acquired images",
0, G_MAXINT, 0,
G_PARAM_READWRITE);
GIMP_PROC_VAL_OBJECT_ARRAY (procedure, "images",
"Array of acquired images",
"Array of acquired images",
GIMP_TYPE_IMAGE,
G_PARAM_READWRITE);
}
return procedure;
}
/* Data structure holding data between runs */ /* Data structure holding data between runs */
/* Currently unused... Eventually may be used /* Currently unused... Eventually may be used
@ -205,21 +284,21 @@ setRunMode (char *argv[])
if (!_stricmp (exeName, DUMP_NAME)) if (!_stricmp (exeName, DUMP_NAME))
twain_run_mode = RUN_DUMP; twain_run_mode = RUN_DUMP;
if (!_stricmp (exeName, RUNDUMP_NAME)) if (!_stricmp (exeName, READDUMP_NAME))
twain_run_mode = RUN_READDUMP; twain_run_mode = RUN_READDUMP;
} }
#endif /* _DEBUG */ #endif /* _DEBUG */
#ifndef TWAIN_ALTERNATE_MAIN
MAIN ()
#endif
int int
scanImage (void) scanImage (void)
{ {
#ifdef _DEBUG #ifdef _DEBUG
if (twain_run_mode == RUN_READDUMP) if (twain_run_mode == RUN_READDUMP)
return readDumpedImage (twSession); {
readDumpedImage (twSession);
return 0;
}
else else
#endif /* _DEBUG */ #endif /* _DEBUG */
return getImage (twSession); return getImage (twSession);
@ -287,93 +366,9 @@ initializeTwain (void)
* GIMP Plug-in entry points * GIMP Plug-in entry points
******************************************************************/ ******************************************************************/
/*
* Plug-in Parameter definitions
*/
#define NUMBER_IN_ARGS 1
#define IN_ARGS { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" }
#define NUMBER_OUT_ARGS 2
#define OUT_ARGS \
{ GIMP_PDB_INT32, "image-count", "Number of acquired images" }, \
{ GIMP_PDB_INT32ARRAY, "image-ids", "Array of acquired image identifiers" }
/*
* query
*
* The plug-in is being queried. Install our procedure for
* acquiring.
*/
static void
query (void)
{
static const GimpParamDef args[] = { IN_ARGS };
static const GimpParamDef return_vals[] = { OUT_ARGS };
#ifdef _DEBUG
if (twain_run_mode == RUN_DUMP)
{
/* the installation of the plugin */
gimp_install_procedure (PLUG_IN_D_NAME,
PLUG_IN_DESCRIPTION,
PLUG_IN_HELP,
PLUG_IN_AUTHOR,
PLUG_IN_COPYRIGHT,
PLUG_IN_VERSION,
"TWAIN (Dump)...",
NULL,
GIMP_PLUGIN,
NUMBER_IN_ARGS,
NUMBER_OUT_ARGS,
args,
return_vals);
gimp_plugin_menu_register (PLUG_IN_D_NAME, "<Image>/File/Create/Acquire");
}
else if (twain_run_mode == RUN_READDUMP)
{
/* the installation of the plugin */
gimp_install_procedure (PLUG_IN_R_NAME,
PLUG_IN_DESCRIPTION,
PLUG_IN_HELP,
PLUG_IN_AUTHOR,
PLUG_IN_COPYRIGHT,
PLUG_IN_VERSION,
"TWAIN (Read)...",
NULL,
GIMP_PLUGIN,
NUMBER_IN_ARGS,
NUMBER_OUT_ARGS,
args,
return_vals);
gimp_plugin_menu_register (PLUG_IN_R_NAME, "<Image>/File/Create/Acquire");
}
else
#endif /* _DEBUG */
{
/* the installation of the plugin */
gimp_install_procedure (PLUG_IN_NAME,
PLUG_IN_DESCRIPTION,
PLUG_IN_HELP,
PLUG_IN_AUTHOR,
PLUG_IN_COPYRIGHT,
PLUG_IN_VERSION,
N_("_Scanner/Camera..."),
NULL,
GIMP_PLUGIN,
NUMBER_IN_ARGS,
NUMBER_OUT_ARGS,
args,
return_vals);
gimp_plugin_menu_register (PLUG_IN_NAME, "<Image>/File/Create/Acquire");
}
}
/* Return values storage */ /* Return values storage */
static GimpParam values[3]; static GList *image_list = NULL;
static gint image_count = 0;
/* /*
* run * run
@ -381,23 +376,24 @@ static GimpParam values[3];
* The plug-in is being requested to run. * The plug-in is being requested to run.
* Capture an image from a TWAIN datasource * Capture an image from a TWAIN datasource
*/ */
static void static GimpValueArray *
run (const gchar *name, twain_run (GimpProcedure *procedure,
gint nparams, GimpRunMode run_mode,
const GimpParam *param, GimpImage *image,
gint *nreturn_vals, GimpDrawable *drawable,
GimpParam **return_vals) const GimpValueArray *args,
gpointer run_data)
{ {
GimpRunMode run_mode = param[0].data.d_int32;
/* Initialize the return values /* Initialize the return values
* Always return at least the status to the caller. * Always return at least the status to the caller.
*/ */
values[0].type = GIMP_PDB_STATUS; GimpPDBStatusType status = GIMP_PDB_SUCCESS;
values[0].data.d_status = GIMP_PDB_SUCCESS; GimpValueArray *return_vals = NULL;
GimpImage **images;
GList *list;
gint num_images;
gint i;
*nreturn_vals = 1;
*return_vals = values;
INIT_I18N (); INIT_I18N ();
gegl_init (NULL, NULL); gegl_init (NULL, NULL);
@ -408,16 +404,10 @@ run (const gchar *name,
*/ */
if (! twainIsAvailable ()) if (! twainIsAvailable ())
{ {
values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR; return gimp_procedure_new_return_values (procedure, GIMP_PDB_EXECUTION_ERROR,
return; NULL);
} }
/* Set up the rest of the return parameters */
values[1].type = GIMP_PDB_INT32;
values[1].data.d_int32 = 0;
values[2].type = GIMP_PDB_INT32ARRAY;
values[2].data.d_int32array = g_new (gint32, MAX_IMAGES);
/* How are we running today? */ /* How are we running today? */
switch (run_mode) switch (run_mode)
{ {
@ -432,8 +422,8 @@ run (const gchar *name,
/* Currently, we don't do non-interactive calls. /* Currently, we don't do non-interactive calls.
* Bail if someone tries to call us non-interactively * Bail if someone tries to call us non-interactively
*/ */
values[0].data.d_status = GIMP_PDB_CALLING_ERROR; return gimp_procedure_new_return_values (procedure, GIMP_PDB_CALLING_ERROR,
return; NULL);
case GIMP_RUN_WITH_LAST_VALS: case GIMP_RUN_WITH_LAST_VALS:
/* Retrieve values from the last run... /* Retrieve values from the last run...
@ -447,13 +437,13 @@ run (const gchar *name,
} }
/* Have we succeeded so far? */ /* Have we succeeded so far? */
if (values[0].data.d_status == GIMP_PDB_SUCCESS) if (status == GIMP_PDB_SUCCESS)
twainMain (); twainMain ();
/* Check to make sure we got at least one valid /* Check to make sure we got at least one valid
* image. * image.
*/ */
if (values[1].data.d_int32 > 0) if (image_count > 0)
{ {
/* An image was captured from the TWAIN /* An image was captured from the TWAIN
* datasource. Do final Interactive * datasource. Do final Interactive
@ -465,12 +455,30 @@ run (const gchar *name,
gimp_set_data (PLUG_IN_NAME, &twainvals, sizeof (TwainValues)); gimp_set_data (PLUG_IN_NAME, &twainvals, sizeof (TwainValues));
} }
num_images = g_list_length (image_list);
images = g_new (GimpImage *, num_images);
for (list = image_list, i = 0;
list;
list = g_list_next (list), i++)
{
images[i] = g_object_ref (list->data);
}
g_list_free (image_list);
/* Set return values */ /* Set return values */
*nreturn_vals = 3; return_vals = gimp_procedure_new_return_values (procedure, status,
NULL);
GIMP_VALUES_SET_INT (return_vals, 1, num_images);
GIMP_VALUES_TAKE_OBJECT_ARRAY (return_vals, 2, GIMP_TYPE_IMAGE, images, num_images);
return return_vals;
} }
else else
{ {
values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR; return gimp_procedure_new_return_values (procedure, GIMP_PDB_EXECUTION_ERROR,
NULL);
} }
} }
@ -913,9 +921,8 @@ endTransferCallback (int completionState,
if (completionState == TWRC_XFERDONE) if (completionState == TWRC_XFERDONE)
{ {
/* We have a completed image transfer */ /* We have a completed image transfer */
values[2].type = GIMP_PDB_INT32ARRAY; image_list = g_list_append (image_list, theClientData->image);
values[2].data.d_int32array[values[1].data.d_int32++] = image_count++;
gimp_image_get_id (theClientData->image);
/* Display the image */ /* Display the image */
LogMessage ("Displaying image %d\n", LogMessage ("Displaying image %d\n",
@ -930,7 +937,7 @@ endTransferCallback (int completionState,
} }
/* Shut down if we have received all of the possible images */ /* Shut down if we have received all of the possible images */
return (values[1].data.d_int32 < MAX_IMAGES); return (image_count < MAX_IMAGES);
} }
/* /*

View File

@ -46,8 +46,8 @@
for 1.8 Specification JMH for 1.8 Specification JMH
\* ======================================================================== */ \* ======================================================================== */
#ifndef TWAIN #ifndef TWAIN_H
#define TWAIN #define TWAIN_H
/* SDH - 02/08/95 - TWUNK */ /* SDH - 02/08/95 - TWUNK */
/* Force 32-bit twain to use same packing of twain structures as existing */ /* Force 32-bit twain to use same packing of twain structures as existing */
@ -1816,4 +1816,4 @@ typedef TW_UINT16 (*DSENTRYPROC)(pTW_IDENTITY,
#else /* WIN32 */ #else /* WIN32 */
#endif /* WIN32 */ #endif /* WIN32 */
#endif /* TWAIN */ #endif /* TWAIN_H */