foreign uses the cache
This commit is contained in:
parent
30ec51699d
commit
5e037e4c68
@ -22,7 +22,7 @@
|
|||||||
- VipsMin stops search early if it can
|
- VipsMin stops search early if it can
|
||||||
- C API supports optional output args
|
- C API supports optional output args
|
||||||
- switch back to int-valued operations
|
- switch back to int-valued operations
|
||||||
- add the operation cache
|
- add the operation cache, various --vips-cache-* flags
|
||||||
- fallback vips_init()
|
- fallback vips_init()
|
||||||
- vips_tracked_malloc() tracks allocation size and can report total mem usage
|
- vips_tracked_malloc() tracks allocation size and can report total mem usage
|
||||||
- cache limits, drop, init, flush plus command-line controls
|
- cache limits, drop, init, flush plus command-line controls
|
||||||
|
15
TODO
15
TODO
@ -1,13 +1,14 @@
|
|||||||
- try:
|
- print_usage could show more about pspecs, eg. for "in" we have:
|
||||||
|
|
||||||
$ vips copy x.jpg x.v
|
VIPS_ARG_IMAGE( class, "in", 1,
|
||||||
|
_( "Input" ),
|
||||||
|
_( "Input image" ),
|
||||||
|
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsCopy, in ) );
|
||||||
|
|
||||||
operation cache is printed twice ... once in atexit?
|
but only display:
|
||||||
|
|
||||||
jpegload is not added
|
in :: VipsImage (input)
|
||||||
|
|
||||||
operation object print is unhelpful, we want a list of args, not a usage
|
|
||||||
message
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ vips_remainder_class_init( VipsRemainderClass *class )
|
|||||||
|
|
||||||
object_class->nickname = "remainder";
|
object_class->nickname = "remainder";
|
||||||
object_class->description =
|
object_class->description =
|
||||||
_( "remainder after integer division for a pair of images" );
|
_( "remainder after integer division of two images" );
|
||||||
object_class->build = vips_remainder_build;
|
object_class->build = vips_remainder_build;
|
||||||
|
|
||||||
vips_arithmetic_set_format_table( aclass, vips_bandfmt_remainder );
|
vips_arithmetic_set_format_table( aclass, vips_bandfmt_remainder );
|
||||||
@ -324,7 +324,7 @@ vips_remainder_const_class_init( VipsRemainderConstClass *class )
|
|||||||
|
|
||||||
object_class->nickname = "remainder_const";
|
object_class->nickname = "remainder_const";
|
||||||
object_class->description =
|
object_class->description =
|
||||||
_( "remainder after integer division for an image "
|
_( "remainder after integer division of an image "
|
||||||
"and a constant" );
|
"and a constant" );
|
||||||
object_class->build = vips_remainder_const_build;
|
object_class->build = vips_remainder_const_build;
|
||||||
|
|
||||||
|
@ -80,6 +80,7 @@ extern char *vips__disc_threshold;
|
|||||||
extern char *vips__cache_max;
|
extern char *vips__cache_max;
|
||||||
extern char *vips__cache_max_mem;
|
extern char *vips__cache_max_mem;
|
||||||
extern char *vips__cache_max_files;
|
extern char *vips__cache_max_files;
|
||||||
|
extern gboolean vips__cache_print;
|
||||||
|
|
||||||
typedef int (*im__fftproc_fn)( VipsImage *, VipsImage *, VipsImage * );
|
typedef int (*im__fftproc_fn)( VipsImage *, VipsImage *, VipsImage * );
|
||||||
|
|
||||||
|
@ -265,6 +265,10 @@ typedef void *(*VipsArgumentMapFn)( VipsObject *, GParamSpec *,
|
|||||||
VipsArgumentClass *, VipsArgumentInstance *, void *a, void *b );
|
VipsArgumentClass *, VipsArgumentInstance *, void *a, void *b );
|
||||||
void *vips_argument_map( VipsObject *object,
|
void *vips_argument_map( VipsObject *object,
|
||||||
VipsArgumentMapFn fn, void *a, void *b );
|
VipsArgumentMapFn fn, void *a, void *b );
|
||||||
|
typedef void *(*VipsArgumentClassMapFn)( VipsObjectClass *, GParamSpec *,
|
||||||
|
VipsArgumentClass *, void *a, void *b );
|
||||||
|
void *vips_argument_class_map( VipsObjectClass *object_class,
|
||||||
|
VipsArgumentClassMapFn fn, void *a, void *b );
|
||||||
int vips_object_get_argument( VipsObject *object, const char *name,
|
int vips_object_get_argument( VipsObject *object, const char *name,
|
||||||
GParamSpec **pspec,
|
GParamSpec **pspec,
|
||||||
VipsArgumentClass **argument_class,
|
VipsArgumentClass **argument_class,
|
||||||
@ -348,6 +352,7 @@ struct _VipsObjectClass {
|
|||||||
int (*build)( VipsObject *object );
|
int (*build)( VipsObject *object );
|
||||||
|
|
||||||
/* Try to print something about the class, handy for help displays.
|
/* Try to print something about the class, handy for help displays.
|
||||||
|
* Keep to one line.
|
||||||
*/
|
*/
|
||||||
void (*print_class)( struct _VipsObjectClass *, VipsBuf * );
|
void (*print_class)( struct _VipsObjectClass *, VipsBuf * );
|
||||||
|
|
||||||
|
@ -69,10 +69,15 @@ typedef struct _VipsOperation {
|
|||||||
typedef struct _VipsOperationClass {
|
typedef struct _VipsOperationClass {
|
||||||
VipsObjectClass parent_class;
|
VipsObjectClass parent_class;
|
||||||
|
|
||||||
|
/* Print the usage message.
|
||||||
|
*/
|
||||||
|
void (*print_usage)( struct _VipsOperationClass *, VipsBuf * );
|
||||||
} VipsOperationClass;
|
} VipsOperationClass;
|
||||||
|
|
||||||
GType vips_operation_get_type( void );
|
GType vips_operation_get_type( void );
|
||||||
|
|
||||||
|
void vips_operation_class_print_usage( VipsOperationClass *operation_class );
|
||||||
|
|
||||||
int vips_operation_call_valist( VipsOperation *operation, va_list ap );
|
int vips_operation_call_valist( VipsOperation *operation, va_list ap );
|
||||||
VipsOperation *vips_operation_new( const char *name );
|
VipsOperation *vips_operation_new( const char *name );
|
||||||
int vips_call( const char *operation_name, ... );
|
int vips_call( const char *operation_name, ... );
|
||||||
|
@ -46,8 +46,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*/
|
|
||||||
#define VIPS_DEBUG
|
#define VIPS_DEBUG
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@ -71,6 +71,7 @@
|
|||||||
char *vips__cache_max = NULL;
|
char *vips__cache_max = NULL;
|
||||||
char *vips__cache_max_mem = NULL;
|
char *vips__cache_max_mem = NULL;
|
||||||
char *vips__cache_max_files = NULL;
|
char *vips__cache_max_files = NULL;
|
||||||
|
gboolean vips__cache_print = FALSE;
|
||||||
|
|
||||||
/* Max number of cached operations.
|
/* Max number of cached operations.
|
||||||
*/
|
*/
|
||||||
@ -409,7 +410,6 @@ vips_cache_init( void )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef VIPS_DEBUG
|
|
||||||
static void
|
static void
|
||||||
vips_cache_print( void )
|
vips_cache_print( void )
|
||||||
{
|
{
|
||||||
@ -419,11 +419,16 @@ vips_cache_print( void )
|
|||||||
|
|
||||||
printf( "Operation cache:\n" );
|
printf( "Operation cache:\n" );
|
||||||
g_hash_table_iter_init( &iter, vips_cache_table );
|
g_hash_table_iter_init( &iter, vips_cache_table );
|
||||||
while( g_hash_table_iter_next( &iter, &key, &value ) )
|
while( g_hash_table_iter_next( &iter, &key, &value ) ) {
|
||||||
vips_object_print( VIPS_OBJECT( key ) );
|
char str[32768];
|
||||||
|
VipsBuf buf = VIPS_BUF_STATIC( str );
|
||||||
|
|
||||||
|
vips_object_to_string( VIPS_OBJECT( key ), &buf );
|
||||||
|
|
||||||
|
printf( "%p - %s\n", key, vips_buf_all( &buf ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /*VIPS_DEBUG*/
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
vips_object_unref_arg( VipsObject *object,
|
vips_object_unref_arg( VipsObject *object,
|
||||||
@ -483,9 +488,8 @@ void
|
|||||||
vips_cache_drop_all( void )
|
vips_cache_drop_all( void )
|
||||||
{
|
{
|
||||||
if( vips_cache_table ) {
|
if( vips_cache_table ) {
|
||||||
#ifdef VIPS_DEBUG
|
if( vips__cache_print )
|
||||||
vips_cache_print();
|
vips_cache_print();
|
||||||
#endif /*VIPS_DEBUG*/
|
|
||||||
|
|
||||||
/* We can't modify the hash in the callback from
|
/* We can't modify the hash in the callback from
|
||||||
* g_hash_table_foreach() and friends. Repeatedly drop the
|
* g_hash_table_foreach() and friends. Repeatedly drop the
|
||||||
@ -501,6 +505,8 @@ vips_cache_drop_all( void )
|
|||||||
|
|
||||||
vips_cache_drop( (VipsOperation *) key );
|
vips_cache_drop( (VipsOperation *) key );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VIPS_FREEF( g_hash_table_unref, vips_cache_table );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -599,6 +605,8 @@ vips_cache_operation_build( VipsOperation **operation )
|
|||||||
{
|
{
|
||||||
VipsOperation *hit;
|
VipsOperation *hit;
|
||||||
|
|
||||||
|
g_assert( VIPS_IS_OPERATION( *operation ) );
|
||||||
|
|
||||||
VIPS_DEBUG_MSG( "vips_cache_operation_build: %p\n", *operation );
|
VIPS_DEBUG_MSG( "vips_cache_operation_build: %p\n", *operation );
|
||||||
|
|
||||||
vips_cache_init();
|
vips_cache_init();
|
||||||
|
@ -395,6 +395,9 @@ static GOptionEntry option_entries[] = {
|
|||||||
{ "vips-cache-max-files", 'l', 0,
|
{ "vips-cache-max-files", 'l', 0,
|
||||||
G_OPTION_ARG_STRING, &vips__cache_max_files,
|
G_OPTION_ARG_STRING, &vips__cache_max_files,
|
||||||
N_( "allow at most N open files" ), "N" },
|
N_( "allow at most N open files" ), "N" },
|
||||||
|
{ "vips-cache-print", 'r', 0,
|
||||||
|
G_OPTION_ARG_NONE, &vips__cache_print,
|
||||||
|
N_( "print operation cache on exit" ), NULL },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ vips_object_build( VipsObject *object )
|
|||||||
void
|
void
|
||||||
vips_object_print_class( VipsObjectClass *class )
|
vips_object_print_class( VipsObjectClass *class )
|
||||||
{
|
{
|
||||||
char str[1000];
|
char str[2048];
|
||||||
VipsBuf buf = VIPS_BUF_STATIC( str );
|
VipsBuf buf = VIPS_BUF_STATIC( str );
|
||||||
|
|
||||||
class->print_class( class, &buf );
|
class->print_class( class, &buf );
|
||||||
@ -204,13 +204,9 @@ vips_object_print( VipsObject *object )
|
|||||||
{
|
{
|
||||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||||
|
|
||||||
/* This is used for printing image headers, so we may need lots of
|
char str[2048];
|
||||||
* space. See header.c.
|
|
||||||
*/
|
|
||||||
char str[32768];
|
|
||||||
VipsBuf buf = VIPS_BUF_STATIC( str );
|
VipsBuf buf = VIPS_BUF_STATIC( str );
|
||||||
|
|
||||||
vips_object_print_class( class );
|
|
||||||
class->print( object, &buf );
|
class->print( object, &buf );
|
||||||
printf( "%s\n", vips_buf_all( &buf ) );
|
printf( "%s\n", vips_buf_all( &buf ) );
|
||||||
}
|
}
|
||||||
@ -324,6 +320,37 @@ vips_argument_map( VipsObject *object,
|
|||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* And loop over a class. Same as ^^, but with no VipsArgumentInstance.
|
||||||
|
*/
|
||||||
|
void *
|
||||||
|
vips_argument_class_map( VipsObjectClass *object_class,
|
||||||
|
VipsArgumentClassMapFn fn, void *a, void *b )
|
||||||
|
{
|
||||||
|
GSList *p;
|
||||||
|
|
||||||
|
for( p = object_class->argument_table_traverse; p; p = p->next ) {
|
||||||
|
VipsArgumentClass *arg_class =
|
||||||
|
(VipsArgumentClass *) p->data;
|
||||||
|
VipsArgument *argument = (VipsArgument *) arg_class;
|
||||||
|
GParamSpec *pspec = argument->pspec;
|
||||||
|
|
||||||
|
/* We have many props on the arg table ... filter out the
|
||||||
|
* ones for this class.
|
||||||
|
*/
|
||||||
|
if( g_object_class_find_property(
|
||||||
|
G_OBJECT_CLASS( object_class ),
|
||||||
|
g_param_spec_get_name( pspec ) ) == pspec ) {
|
||||||
|
void *result;
|
||||||
|
|
||||||
|
if( (result =
|
||||||
|
fn( object_class, pspec, arg_class, a, b )) )
|
||||||
|
return( result );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return( NULL );
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a VipsArgumentInstance for each installed argument property. Ideally
|
/* Create a VipsArgumentInstance for each installed argument property. Ideally
|
||||||
* we'd do this during _init() but g_object_class_find_property() does not seem
|
* we'd do this during _init() but g_object_class_find_property() does not seem
|
||||||
* to work then :-( so we have to delay it until first access. See
|
* to work then :-( so we have to delay it until first access. See
|
||||||
@ -1244,14 +1271,15 @@ vips_object_set_argument_from_string( VipsObject *object,
|
|||||||
VipsObject *new_object;
|
VipsObject *new_object;
|
||||||
VipsImage *out;
|
VipsImage *out;
|
||||||
|
|
||||||
/* Use VipsFile to build images, then pull @out from it and
|
/* Use VipsForeign to build images, then pull @out from it and
|
||||||
* use that to set the value.
|
* use that to set the value.
|
||||||
*/
|
*/
|
||||||
if( !(new_object =
|
if( !(new_object =
|
||||||
vips_object_new_from_string( oclass, value )) )
|
vips_object_new_from_string( oclass, value )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( vips_object_build( new_object ) ) {
|
if( vips_cache_operation_build(
|
||||||
|
(VipsOperation **) &new_object ) ) {
|
||||||
g_object_unref( new_object );
|
g_object_unref( new_object );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
@ -1283,6 +1311,9 @@ vips_object_set_argument_from_string( VipsObject *object,
|
|||||||
vips_object_new_from_string( oclass, value )) )
|
vips_object_new_from_string( oclass, value )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
|
/* Not necessarily a VipsOperation subclass so we don't use
|
||||||
|
* the cache. We could have a separate case for this.
|
||||||
|
*/
|
||||||
if( vips_object_build( new_object ) ) {
|
if( vips_object_build( new_object ) ) {
|
||||||
g_object_unref( new_object );
|
g_object_unref( new_object );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
@ -1430,7 +1461,7 @@ vips_object_get_argument_to_string( VipsObject *object,
|
|||||||
VipsObject *new_object;
|
VipsObject *new_object;
|
||||||
VipsImage *in;
|
VipsImage *in;
|
||||||
|
|
||||||
/* Use VipsFile to make a saver, set 'in' on that and run
|
/* Use VipsForeign to make a saver, set 'in' on that and run
|
||||||
* build to make it write.
|
* build to make it write.
|
||||||
*/
|
*/
|
||||||
if( !(new_object =
|
if( !(new_object =
|
||||||
@ -1441,7 +1472,8 @@ vips_object_get_argument_to_string( VipsObject *object,
|
|||||||
g_object_set( new_object, "in", in, NULL );
|
g_object_set( new_object, "in", in, NULL );
|
||||||
g_object_unref( in );
|
g_object_unref( in );
|
||||||
|
|
||||||
if( vips_object_build( new_object ) ) {
|
if( vips_cache_operation_build(
|
||||||
|
(VipsOperation **) &new_object ) ) {
|
||||||
g_object_unref( new_object );
|
g_object_unref( new_object );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
@ -74,13 +74,12 @@ typedef struct {
|
|||||||
gboolean required; /* show required args or optional */
|
gboolean required; /* show required args or optional */
|
||||||
gboolean oftype; /* "is of type" message */
|
gboolean oftype; /* "is of type" message */
|
||||||
int n; /* Arg number */
|
int n; /* Arg number */
|
||||||
} VipsOperationPrint;
|
} VipsOperationClassPrint;
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
vips_operation_print_arg( VipsObject *object, GParamSpec *pspec,
|
vips_operation_class_print_arg( VipsObjectClass *object_class,
|
||||||
VipsArgumentClass *argument_class,
|
GParamSpec *pspec, VipsArgumentClass *argument_class,
|
||||||
VipsArgumentInstance *argument_instance,
|
VipsBuf *buf, VipsOperationClassPrint *print )
|
||||||
VipsBuf *buf, VipsOperationPrint *print )
|
|
||||||
{
|
{
|
||||||
/* Only show construct args ... others are internal.
|
/* Only show construct args ... others are internal.
|
||||||
*/
|
*/
|
||||||
@ -109,6 +108,46 @@ vips_operation_print_arg( VipsObject *object, GParamSpec *pspec,
|
|||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_operation_print_usage( VipsOperationClass *class, VipsBuf *buf )
|
||||||
|
{
|
||||||
|
VipsObjectClass *object_class = VIPS_OBJECT_CLASS( class );
|
||||||
|
|
||||||
|
VipsOperationClassPrint print;
|
||||||
|
|
||||||
|
/* First pass through args: show the required names.
|
||||||
|
*/
|
||||||
|
vips_buf_appendf( buf, " %s ", object_class->nickname );
|
||||||
|
print.message = NULL;
|
||||||
|
print.required = TRUE;
|
||||||
|
print.oftype = FALSE;
|
||||||
|
print.n = 0;
|
||||||
|
vips_argument_class_map( object_class,
|
||||||
|
(VipsArgumentClassMapFn) vips_operation_class_print_arg,
|
||||||
|
buf, &print );
|
||||||
|
vips_buf_appends( buf, "\n" );
|
||||||
|
|
||||||
|
/* Show required types.
|
||||||
|
*/
|
||||||
|
print.message = "where:";
|
||||||
|
print.required = TRUE;
|
||||||
|
print.oftype = TRUE;
|
||||||
|
print.n = 0;
|
||||||
|
vips_argument_class_map( object_class,
|
||||||
|
(VipsArgumentClassMapFn) vips_operation_class_print_arg,
|
||||||
|
buf, &print );
|
||||||
|
|
||||||
|
/* Show optional args.
|
||||||
|
*/
|
||||||
|
print.message = "optional arguments:";
|
||||||
|
print.required = FALSE;
|
||||||
|
print.oftype = TRUE;
|
||||||
|
print.n = 0;
|
||||||
|
vips_argument_class_map( object_class,
|
||||||
|
(VipsArgumentClassMapFn) vips_operation_class_print_arg,
|
||||||
|
buf, &print );
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef VIPS_DEBUG
|
#ifdef VIPS_DEBUG
|
||||||
static void *
|
static void *
|
||||||
vips_operation_call_argument( VipsObject *object, GParamSpec *pspec,
|
vips_operation_call_argument( VipsObject *object, GParamSpec *pspec,
|
||||||
@ -137,53 +176,16 @@ vips_operation_call_argument( VipsObject *object, GParamSpec *pspec,
|
|||||||
static void
|
static void
|
||||||
vips_operation_print( VipsObject *object, VipsBuf *buf )
|
vips_operation_print( VipsObject *object, VipsBuf *buf )
|
||||||
{
|
{
|
||||||
|
#ifdef VIPS_DEBUG
|
||||||
VipsOperation *operation = VIPS_OPERATION( object );
|
VipsOperation *operation = VIPS_OPERATION( object );
|
||||||
VipsObjectClass *object_class = VIPS_OBJECT_GET_CLASS( object );
|
VipsObjectClass *object_class = VIPS_OBJECT_GET_CLASS( object );
|
||||||
VipsOperationPrint print;
|
|
||||||
|
|
||||||
#ifdef VIPS_DEBUG
|
|
||||||
printf( "%s args:\n", object_class->nickname );
|
printf( "%s args:\n", object_class->nickname );
|
||||||
vips_argument_map( VIPS_OBJECT( operation ),
|
vips_argument_map( VIPS_OBJECT( operation ),
|
||||||
(VipsArgumentMapFn) vips_operation_call_argument, NULL, NULL );
|
(VipsArgumentMapFn) vips_operation_call_argument, NULL, NULL );
|
||||||
#endif /*VIPS_DEBUG*/
|
#endif /*VIPS_DEBUG*/
|
||||||
|
|
||||||
/* First pass through args: show the required names.
|
VIPS_OBJECT_CLASS( vips_operation_parent_class )->print( object, buf );
|
||||||
*/
|
|
||||||
vips_buf_appendf( buf, " %s ", object_class->nickname );
|
|
||||||
print.message = NULL;
|
|
||||||
print.required = TRUE;
|
|
||||||
print.oftype = FALSE;
|
|
||||||
print.n = 0;
|
|
||||||
vips_argument_map( VIPS_OBJECT( operation ),
|
|
||||||
(VipsArgumentMapFn) vips_operation_print_arg, buf, &print );
|
|
||||||
vips_buf_appends( buf, "\n" );
|
|
||||||
|
|
||||||
/* Show required types.
|
|
||||||
*/
|
|
||||||
print.message = "where:";
|
|
||||||
print.required = TRUE;
|
|
||||||
print.oftype = TRUE;
|
|
||||||
print.n = 0;
|
|
||||||
vips_argument_map( VIPS_OBJECT( operation ),
|
|
||||||
(VipsArgumentMapFn) vips_operation_print_arg, buf, &print );
|
|
||||||
|
|
||||||
/* Show optional args.
|
|
||||||
*/
|
|
||||||
print.message = "optional arguments:";
|
|
||||||
print.required = FALSE;
|
|
||||||
print.oftype = TRUE;
|
|
||||||
print.n = 0;
|
|
||||||
vips_argument_map( VIPS_OBJECT( operation ),
|
|
||||||
(VipsArgumentMapFn) vips_operation_print_arg, buf, &print );
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
vips_operation_build( VipsObject *object )
|
|
||||||
{
|
|
||||||
if( VIPS_OBJECT_CLASS( vips_operation_parent_class )->build( object ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -196,9 +198,10 @@ vips_operation_class_init( VipsOperationClass *class )
|
|||||||
gobject_class->dispose = vips_operation_dispose;
|
gobject_class->dispose = vips_operation_dispose;
|
||||||
|
|
||||||
vobject_class->nickname = "operation";
|
vobject_class->nickname = "operation";
|
||||||
vobject_class->description = _( "VIPS operations" );
|
vobject_class->description = _( "operations" );
|
||||||
vobject_class->print = vips_operation_print;
|
vobject_class->print = vips_operation_print;
|
||||||
vobject_class->build = vips_operation_build;
|
|
||||||
|
class->print_usage = vips_operation_print_usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -208,6 +211,17 @@ vips_operation_init( VipsOperation *operation )
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vips_operation_class_print_usage( VipsOperationClass *operation_class )
|
||||||
|
{
|
||||||
|
char str[2048];
|
||||||
|
VipsBuf buf = VIPS_BUF_STATIC( str );
|
||||||
|
|
||||||
|
operation_class->print_usage( operation_class, &buf );
|
||||||
|
printf( "%s", _( "usage:" ) );
|
||||||
|
printf( "\n%s", vips_buf_all( &buf ) );
|
||||||
|
}
|
||||||
|
|
||||||
VipsOperation *
|
VipsOperation *
|
||||||
vips_operation_new( const char *name )
|
vips_operation_new( const char *name )
|
||||||
{
|
{
|
||||||
@ -896,6 +910,9 @@ vips_call_argv( VipsOperation *operation, int argc, char **argv )
|
|||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We can't use the operation cache, we need to be able to change the
|
||||||
|
* operation pointer. The cache probably wouldn't help anyway.
|
||||||
|
*/
|
||||||
if( vips_object_build( VIPS_OBJECT( operation ) ) )
|
if( vips_object_build( VIPS_OBJECT( operation ) ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
|
@ -1073,7 +1073,8 @@ main( int argc, char **argv )
|
|||||||
|
|
||||||
if( vips_call_argv( operation, argc - 1, argv + 1 ) ) {
|
if( vips_call_argv( operation, argc - 1, argv + 1 ) ) {
|
||||||
if( argc == 1 )
|
if( argc == 1 )
|
||||||
vips_object_print( VIPS_OBJECT( operation ) );
|
vips_operation_class_print_usage(
|
||||||
|
VIPS_OPERATION_GET_CLASS( operation ) );
|
||||||
|
|
||||||
vips_object_unref_outputs( VIPS_OBJECT( operation ) );
|
vips_object_unref_outputs( VIPS_OBJECT( operation ) );
|
||||||
g_object_unref( operation );
|
g_object_unref( operation );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user