f044bfdcb84cc49db3dc6ca6b43f07c84eb0dad7
[debian/amanda] / perl / Amanda / Device.swg
1 /*
2  * Copyright (c) 2007, 2008, 2009, 2010 Zmanda, Inc.  All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 as published
6  * by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11  * for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16  *
17  * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
18  * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
19  */
20
21 %module "Amanda::Device"
22 %include "amglue/amglue.swg"
23 %include "exception.i"
24 %import "Amanda/Header.swg";
25
26 %include "Amanda/Device.pod"
27
28 %{
29 #include "device.h"
30 #include "property.h"
31 #include "fileheader.h"
32 #include "glib-util.h"
33 %}
34
35 %init %{
36     /* Initialize the Device API on load */
37     device_api_init();
38 %}
39
40 %{
41
42 /* Utility functions for typemaps, below */
43
44 /* return a new, mortal SV corresponding to the given GValue
45  *
46  * @param value: the value to convert
47  * @returns: a new, mortal SV
48  */
49 static SV *
50 set_sv_from_gvalue(GValue *value)
51 {
52     GType fundamental = G_TYPE_FUNDAMENTAL(G_VALUE_TYPE(value));
53     SV *sv = NULL;
54
55     /* complex reference types */
56     switch (fundamental) {
57         case G_TYPE_LONG:
58             return sv_2mortal(amglue_newSVi64(g_value_get_long(value)));
59
60         case G_TYPE_ULONG:
61             return sv_2mortal(amglue_newSVu64(g_value_get_ulong(value)));
62
63         case G_TYPE_INT64:
64             return sv_2mortal(amglue_newSVi64(g_value_get_int64(value)));
65
66         case G_TYPE_UINT64:
67             return sv_2mortal(amglue_newSVu64(g_value_get_uint64(value)));
68
69         case G_TYPE_BOXED: {
70             GType boxed_type = G_VALUE_TYPE(value);
71             QualifiedSize qs;
72             HV *hv;
73
74             if (boxed_type == QUALIFIED_SIZE_TYPE) {
75                 qs = *(QualifiedSize*)(g_value_get_boxed(value));
76
77                 /* build a hash */
78                 hv = (HV *)sv_2mortal((SV *)newHV());
79                 hv_store(hv, "accuracy", 8, newSViv(qs.accuracy), 0);
80                 hv_store(hv, "bytes", 5, amglue_newSVi64(qs.bytes), 0);
81
82                 sv = newRV((SV *)hv);
83                 return newRV((SV *)hv);
84             } else {
85                 warn("Unsupported boxed property type #%d", (int)boxed_type);
86
87                 sv = sv_newmortal();
88                 sv_setsv(sv, &PL_sv_undef);
89                 return sv;
90             }
91         }
92     }
93
94     /* simple types that can be constructed with sv_set*v */
95     sv = sv_newmortal();
96     switch (fundamental) {
97         case G_TYPE_CHAR:
98             sv_setiv(sv, g_value_get_char(value));
99             break;
100
101         case G_TYPE_UCHAR:
102             sv_setuv(sv, g_value_get_uchar(value));
103             break;
104
105         case G_TYPE_BOOLEAN:
106             sv_setiv(sv, g_value_get_boolean(value));
107             break;
108
109         case G_TYPE_INT:
110             sv_setiv(sv, g_value_get_int(value));
111             break;
112
113         case G_TYPE_UINT:
114             sv_setuv(sv, g_value_get_uint(value));
115             break;
116
117         case G_TYPE_FLOAT:
118             sv_setnv(sv, g_value_get_float(value));
119             break;
120
121         case G_TYPE_DOUBLE:
122             sv_setnv(sv, g_value_get_double(value));
123             break;
124
125         case G_TYPE_STRING:
126             sv_setpv(sv, g_value_get_string(value));
127             break;
128
129         case G_TYPE_ENUM:
130             sv_setiv(sv, g_value_get_enum(value));
131             break;
132
133         case G_TYPE_FLAGS:
134             sv_setiv(sv, g_value_get_flags(value));
135             break;
136
137         /* Unsupported */
138         default:
139         case G_TYPE_POINTER:
140         case G_TYPE_INTERFACE:
141         case G_TYPE_OBJECT:
142         case G_TYPE_PARAM:
143             warn("Unsupported fundamental property type #%d", (int)fundamental);
144             sv_setsv(sv, &PL_sv_undef);
145             break;
146     }
147
148     return sv;
149 }
150
151 /* Given an SV and an initialized GValue, set the GValue to the value
152  * represented by the SV.  The GValue's type must already be set.
153  *
154  * For basic corresponding types (string -> string, integer -> integer),
155  * the translation is straightforward.  However, if the GValue is not a
156  * string, but the SV has a string value, then g_value_set_from_string will
157  * be used to parse the string.
158  *
159  * @param sv: SV to convert
160  * @param value: (input/output) destination
161  * @returns: TRUE on success
162  */
163 static gboolean
164 set_gvalue_from_sv(SV *sv, GValue *value)
165 {
166     GType fundamental = G_TYPE_FUNDAMENTAL(G_VALUE_TYPE(value));
167
168     /* if we got a string, use g_value_set_from_string to parse any funny
169      * values or suffixes */
170     if (SvPOK(sv)) {
171         if (g_value_set_from_string(value, SvPV_nolen(sv)))
172             return TRUE;
173     }
174
175     /* otherwise, handle numeric types with SvIV, SvNV, or the amglue_* functions */
176     switch (fundamental) {
177         case G_TYPE_BOOLEAN:
178             g_value_set_boolean(value, SvIV(sv));
179             return TRUE;
180
181         case G_TYPE_CHAR:
182             g_value_set_char(value, amglue_SvI8(sv));
183             return TRUE;
184
185         case G_TYPE_UCHAR:
186             g_value_set_uchar(value, amglue_SvU8(sv));
187             return TRUE;
188
189         case G_TYPE_INT:
190             g_value_set_int(value, amglue_SvI32(sv));
191             return TRUE;
192
193         case G_TYPE_UINT:
194             g_value_set_uint(value, amglue_SvU32(sv));
195             return TRUE;
196
197         case G_TYPE_LONG:
198             g_value_set_int64(value, amglue_SvI64(sv));
199             return TRUE;
200
201         case G_TYPE_ULONG:
202             g_value_set_uint64(value, amglue_SvU64(sv));
203             return TRUE;
204
205         case G_TYPE_INT64:
206             g_value_set_int64(value, amglue_SvI64(sv));
207             return TRUE;
208
209         case G_TYPE_UINT64:
210             g_value_set_uint64(value, amglue_SvU64(sv));
211             return TRUE;
212
213         case G_TYPE_FLOAT:
214             g_value_set_float(value, SvNV(sv));
215             return TRUE;
216
217         case G_TYPE_DOUBLE:
218             g_value_set_double(value, SvNV(sv));
219             return TRUE;
220
221         case G_TYPE_ENUM:
222             g_value_set_enum(value, SvIV(sv));
223             return TRUE;
224
225         case G_TYPE_FLAGS:
226             g_value_set_flags(value, SvIV(sv));
227             return TRUE;
228
229         default:
230             /* for anything else, let perl stringify it for us and try parsing it */
231             return g_value_set_from_string(value, SvPV_nolen(sv));
232     }
233 }
234
235 %}
236
237 /*
238  * DirectTCPConnection object
239  */
240
241 typedef struct DirectTCPConnection {
242     %extend {
243         ~DirectTCPConnection() {
244             g_object_unref(self);
245         };
246
247         %newobject close;
248         char *close() {
249             return directtcp_connection_close(self);
250         }
251     };
252 } DirectTCPConnection;
253
254 /*
255  * Device struct, %extend-ed into a Perl class
256  */
257
258 typedef struct queue_fd_t {
259     /* Instance variables -- all readonly */
260     %immutable;
261     int fd;
262     char *errmsg;
263
264     %mutable;
265
266     /* methods */
267     %extend {
268         /* constructor */
269         queue_fd_t(int fd) {
270             return queue_fd_new(fd, NULL);
271         }
272
273         /* destructor */
274         ~queue_fd_t() {
275             amfree(self->errmsg);
276             g_free(self);
277         }
278     }
279 } queue_fd_t;
280
281 %name(unaliased_name) extern char *device_unaliased_name(char *);
282
283 typedef struct Device {
284
285     /* methods */
286     %extend {
287         /* constructor */
288         Device(char *device_name) {
289             return device_open(device_name);
290         }
291
292         ~Device() {
293             g_object_unref(self);
294         }
295
296         gboolean
297         configure(gboolean use_global_config) {
298             return device_configure(self, use_global_config);
299         }
300
301         char *
302         error() {
303             return device_error(self);
304         }
305
306         char *
307         status_error() {
308             return device_status_error(self);
309         }
310
311         char *
312         error_or_status() {
313             return device_error_or_status(self);
314         }
315
316         DeviceStatusFlags
317         read_label() {
318             return device_read_label(self);
319         }
320
321         gboolean
322         start(DeviceAccessMode mode, char *label, char *timestamp) {
323             return device_start(self, mode, label, timestamp);
324         }
325
326         gboolean
327         finish() {
328             return device_finish(self);
329         }
330
331         gboolean
332         start_file(dumpfile_t *jobInfo) {
333             return device_start_file(self, jobInfo);
334         }
335
336         gboolean
337         write_block(guint size, gpointer data) {
338             return device_write_block(self, size, data);
339         }
340
341         gboolean
342         write_from_fd(queue_fd_t *queue_fd) {
343             return device_write_from_fd(self, queue_fd);
344         }
345
346         gboolean
347         finish_file() {
348             return device_finish_file(self);
349         }
350
351         dumpfile_t*
352         seek_file(guint file) {
353             return device_seek_file(self, file);
354         }
355
356         gboolean
357         seek_block(guint64 block) {
358             return device_seek_block(self, block);
359         }
360
361         int
362         read_block(gpointer buffer, int *size) {
363             return device_read_block(self, buffer, size);
364         }
365
366         gboolean read_to_fd(queue_fd_t *queue_fd) {
367             return device_read_to_fd(self, queue_fd);
368         }
369
370         gboolean
371         erase() {
372             return device_erase(self);
373         }
374
375         gboolean
376         eject() {
377             return device_eject(self);
378         }
379
380         gboolean
381         directtcp_supported() {
382             return device_directtcp_supported(self);
383         }
384
385         void
386         listen(gboolean for_writing, DirectTCPAddr **addrs) {
387             /* ensure that the addresses are empty if there was an error */
388             if (!device_listen(self, for_writing, addrs))
389                 *addrs = NULL;
390         }
391
392         %newobject accept; /* connection is already ref'd, so we own it */
393         DirectTCPConnection *
394         accept() {
395             DirectTCPConnection *conn = NULL;
396             gboolean rv;
397
398             rv = device_accept(self, &conn, NULL, NULL);
399             if (!rv && conn) {
400                 /* conn is ref'd for our convenience, but we don't want it */
401                 g_object_unref(conn);
402                 conn = NULL;
403             }
404             return conn;
405         }
406
407         gboolean
408         use_connection(DirectTCPConnection *conn) {
409             return device_use_connection(self, conn);
410         }
411
412         %typemap(in,numinputs=0) guint64 *actual_size (guint64 sz) {
413             sz = 0;
414             $1 = &sz;
415         }
416         %typemap(argout) guint64 *actual_size {
417             SP += argvi; PUTBACK;
418             $result = sv_2mortal(amglue_newSVu64(*$1));
419             SPAGAIN; SP -= argvi; argvi++;
420         }
421         gboolean
422         write_from_connection(guint64 size, guint64 *actual_size) {
423             return device_write_from_connection(self, size, actual_size);
424         }
425
426         gboolean
427         read_to_connection(guint64 size, guint64 *actual_size) {
428             return device_read_to_connection(self, size, actual_size);
429         }
430
431         %typemap(out) const GSList * {
432             GSList *iter;
433
434             /* Count the DeviceProperties */
435             EXTEND(SP, g_slist_length($1)); /* make room for return values */
436
437             /* Note that we set $result several times. the nature of
438              * SWIG's wrapping is such that incrementing argvi points
439              * $result to the next location in perl's argument stack.
440              */
441
442             for (iter = $1; iter; iter = g_slist_next(iter)) {
443                 DeviceProperty *prop = iter->data;
444                 HV *hash = newHV();
445                 SV *rv = newRV_noinc((SV *)hash);
446
447                 hv_store(hash, "name", 4,
448                         newSVpv(prop->base->name, 0), 0);
449                 hv_store(hash, "description", 11,
450                         newSVpv(prop->base->description, 0), 0);
451                 hv_store(hash, "access", 6,
452                         newSViv(prop->access), 0);
453                 $result = sv_2mortal(rv);
454                 argvi++;
455             }
456         }
457         const GSList * property_list(void) {
458             return device_property_get_list(self);
459         }
460
461         %typemap(out) const GSList *; /* remove typemap */
462
463         /* A typemap to convert a property name to a DevicePropertyBase. */
464         %typemap(in) DevicePropertyBase * {
465             char *pname = NULL;
466
467             if (SvPOK($input))
468                 pname = SvPV_nolen($input);
469
470             if (pname) $1 = (DevicePropertyBase *)device_property_get_by_name(pname);
471             if (!pname || !$1) {
472                 SWIG_exception_fail(SWIG_ValueError, "Invalid property name");
473             }
474         }
475
476         /* A typemap to convert the GValue in property_get to a return value.  The
477          * (in) typemap sets up storage for the parameters, while the (argout) converts
478          * them to a perl SV. */
479         %typemap(in,numinputs=0) (GValue *out_val, PropertySurety *surety,
480                                   PropertySource *source, gboolean *val_found)
481                             (GValue val,
482                              PropertySurety surety,
483                              PropertySource source,
484                              gboolean found) {
485             memset(&val, 0, sizeof(val));
486             $1 = &val;
487             if (GIMME_V == G_ARRAY) {
488                 $2 = &surety;
489                 $3 = &source;
490             }
491             $4 = &found;
492         }
493         %typemap(argout) (GValue *out_val, PropertySurety *surety,
494                           PropertySource *source, gboolean *val_found) {
495             /* if the result is valid */
496             if (*$4) {
497                 /* move data from $1 to $result, somehow, being careful to
498                  * save the perl stack while doing so */
499                 SP += argvi; PUTBACK;
500                 $result = set_sv_from_gvalue($1);
501                 SPAGAIN; SP -= argvi; argvi++;
502
503                 /* free any memory for the GValue */
504                 g_value_unset($1);
505
506                 if (GIMME_V == G_ARRAY) {
507                     $result = newSViv(*$2);
508                     argvi++;
509                     $result = newSViv(*$3);
510                     argvi++;
511                 }
512             }
513             /* otherwise, return nothing */
514         }
515
516         void
517         property_get(DevicePropertyBase *pbase, GValue *out_val, PropertySurety *surety,
518                      PropertySource *source, gboolean *val_found) {
519             *val_found = device_property_get_ex(self, pbase->ID, out_val, surety, source);
520         }
521
522         /* delete typemaps */
523         %typemap(in) (GValue *out_val, gboolean *val_found);
524         %typemap(argout) (GValue *out_val, gboolean *val_found);
525
526         /* We cheat a little bit here and just pass the native Perl type in to
527          * the function.  This is the easiest way to make sure we know the property
528          * information (in particular, its type) before trying to convert the SV.  */
529         %typemap(in) SV *sv "$1 = $input;"
530
531         gboolean
532         property_set(DevicePropertyBase *pbase, SV *sv) {
533             GValue gval;
534             memset(&gval, 0, sizeof(gval));
535             g_value_init(&gval, pbase->type);
536             if (!set_gvalue_from_sv(sv, &gval))
537                 goto fail;
538
539             if (!device_property_set(self, pbase->ID, &gval))
540                 goto fail;
541
542             g_value_unset(&gval);
543             return TRUE;
544         fail:
545             g_value_unset(&gval);
546             return FALSE;
547         }
548
549         gboolean
550         property_set_ex(DevicePropertyBase *pbase, SV *sv,
551                         PropertySurety surety, PropertySource source) {
552             GValue gval;
553             memset(&gval, 0, sizeof(gval));
554             g_value_init(&gval, pbase->type);
555             if (!set_gvalue_from_sv(sv, &gval))
556                 goto fail;
557
558             if (!device_property_set_ex(self, pbase->ID, &gval, surety, source))
559                 goto fail;
560
561             g_value_unset(&gval);
562             return TRUE;
563         fail:
564             g_value_unset(&gval);
565             return FALSE;
566         }
567
568         gboolean recycle_file(guint filenum) {
569             return device_recycle_file(self, filenum);
570         }
571
572         /* accessor functions */
573
574         int file(void) { return self->file; }
575         guint64 block(void) { return self->block; }
576         gboolean in_file(void) { return self->in_file; }
577         char * device_name(void) { return self->device_name; }
578         DeviceAccessMode access_mode(void) { return self->access_mode; }
579         gboolean is_eof(void) { return self->is_eof; }
580         gboolean is_eom(void) { return self->is_eom; }
581         char * volume_label(void) { return self->volume_label; }
582         char * volume_time(void) { return self->volume_time; }
583         DeviceStatusFlags status(void) { return self->status; }
584         gsize min_block_size(void) { return self->min_block_size; }
585         gsize max_block_size(void) { return self->max_block_size; }
586         gsize block_size(void) { return self->block_size; }
587         dumpfile_t *volume_header(void) { return self->volume_header; }
588     };
589
590 } Device;
591
592 /* An alternate constructor for RAIT devices */
593 %typemap(in) GSList *child_devices {
594     AV *av;
595     int i, len;
596
597     if (!SvROK($input) || SvTYPE(SvRV($input)) != SVt_PVAV) {
598         SWIG_exception(SWIG_TypeError, "Expected an arrayref");
599     }
600     av = (AV *)SvRV($input);
601
602     $1 = NULL;
603     len = av_len(av);
604     for (i = 0; i <= len; i++) {
605         SV **elt = av_fetch(av, i, 0);
606         Device *d;
607
608         if (elt && !SvOK(*elt)) {
609             $1 = g_slist_append($1, NULL); /* 'undef' => NULL */
610         } else if (!elt || SWIG_ConvertPtr(*elt, (void **)&d, $descriptor(Device *), 0) == -1) {
611             SWIG_exception(SWIG_TypeError, "array member is not a Device");
612         } else {
613             $1 = g_slist_append($1, d);
614         }
615     }
616 }
617 %typemap(freearg) GSList *child_devices {
618     g_slist_free($1);
619 }
620 %newobject rait_device_open_from_children;
621 Device *rait_device_open_from_children(GSList *child_devices);
622 %perlcode %{
623 sub new_rait_from_children {
624     my $class = shift; # strip the $class from the arguments
625     return rait_device_open_from_children([@_]);
626 }
627 %}
628
629 /*
630  * Constants
631  */
632
633 amglue_add_flag_tag_fns(DeviceAccessMode);
634 amglue_add_constant_short(ACCESS_NULL, "NULL", DeviceAccessMode);
635 amglue_add_constant_short(ACCESS_READ, "READ", DeviceAccessMode);
636 amglue_add_constant_short(ACCESS_WRITE, "WRITE", DeviceAccessMode);
637 amglue_add_constant_short(ACCESS_APPEND, "APPEND", DeviceAccessMode);
638
639 /* (this is really a macro, but SWIG will Do The Right Thing */
640 gboolean IS_WRITABLE_ACCESS_MODE(DeviceAccessMode mode);
641 amglue_export_tag(DeviceAccessMode, IS_WRITABLE_ACCESS_MODE);
642 amglue_copy_to_tag(DeviceAccessMode, constants);
643
644 amglue_add_flag_tag_fns(DeviceStatusFlags);
645 amglue_add_constant_short(DEVICE_STATUS_SUCCESS, "SUCCESS", DeviceStatusFlags);
646 amglue_add_constant_short(DEVICE_STATUS_DEVICE_ERROR, "DEVICE_ERROR", DeviceStatusFlags);
647 amglue_add_constant_short(DEVICE_STATUS_DEVICE_BUSY, "DEVICE_BUSY", DeviceStatusFlags);
648 amglue_add_constant_short(DEVICE_STATUS_VOLUME_MISSING, "VOLUME_MISSING", DeviceStatusFlags);
649 amglue_add_constant_short(DEVICE_STATUS_VOLUME_UNLABELED, "VOLUME_UNLABELED", DeviceStatusFlags);
650 amglue_add_constant_short(DEVICE_STATUS_VOLUME_ERROR, "VOLUME_ERROR", DeviceStatusFlags);
651 amglue_add_constant_noshort(DEVICE_STATUS_FLAGS_MAX, DeviceStatusFlags);
652 amglue_copy_to_tag(DeviceStatusFlags, constants);
653
654 amglue_add_flag_tag_fns(PropertyPhaseFlags);
655 amglue_add_constant_short(PROPERTY_PHASE_BEFORE_START, "BEFORE_START", PropertyPhaseFlags);
656 amglue_add_constant_short(PROPERTY_PHASE_BETWEEN_FILE_WRITE, "BETWEEN_FILE_WRITE", PropertyPhaseFlags);
657 amglue_add_constant_short(PROPERTY_PHASE_INSIDE_FILE_WRITE, "INSIDE_FILE_WRITE", PropertyPhaseFlags);
658 amglue_add_constant_short(PROPERTY_PHASE_BETWEEN_FILE_READ, "BETWEEN_FILE_READ", PropertyPhaseFlags);
659 amglue_add_constant_short(PROPERTY_PHASE_INSIDE_FILE_READ, "INSIDE_FILE_READ", PropertyPhaseFlags);
660 amglue_add_constant_noshort(PROPERTY_PHASE_MAX, PropertyPhaseFlags);
661 amglue_add_constant_noshort(PROPERTY_PHASE_MASK, PropertyPhaseFlags);
662 amglue_add_constant_noshort(PROPERTY_PHASE_SHIFT, PropertyPhaseFlags);
663 amglue_copy_to_tag(PropertyPhaseFlags, constants);
664
665 amglue_add_flag_tag_fns(PropertyAccessFlags);
666 amglue_add_constant_short(PROPERTY_ACCESS_GET_BEFORE_START,
667                     "GET_BEFORE_START", PropertyAccessFlags);
668 amglue_add_constant_short(PROPERTY_ACCESS_GET_BETWEEN_FILE_WRITE,
669                     "GET_BETWEEN_FILE_WRITE", PropertyAccessFlags);
670 amglue_add_constant_short(PROPERTY_ACCESS_GET_INSIDE_FILE_WRITE,
671                     "GET_INSIDE_FILE_WRITE", PropertyAccessFlags);
672 amglue_add_constant_short(PROPERTY_ACCESS_GET_BETWEEN_FILE_READ,
673                     "GET_BETWEEN_FILE_READ", PropertyAccessFlags);
674 amglue_add_constant_short(PROPERTY_ACCESS_GET_INSIDE_FILE_READ,
675                     "GET_INSIDE_FILE_READ", PropertyAccessFlags);
676 amglue_add_constant_short(PROPERTY_ACCESS_SET_BEFORE_START,
677                     "SET_BEFORE_START", PropertyAccessFlags);
678 amglue_add_constant_short(PROPERTY_ACCESS_SET_BETWEEN_FILE_WRITE,
679                     "SET_BETWEEN_FILE_WRITE", PropertyAccessFlags);
680 amglue_add_constant_short(PROPERTY_ACCESS_SET_INSIDE_FILE_WRITE,
681                     "SET_INSIDE_FILE_WRITE", PropertyAccessFlags);
682 amglue_add_constant_short(PROPERTY_ACCESS_SET_BETWEEN_FILE_READ,
683                     "SET_BETWEEN_FILE_READ", PropertyAccessFlags);
684 amglue_add_constant_short(PROPERTY_ACCESS_SET_INSIDE_FILE_READ,
685                     "SET_INSIDE_FILE_READ", PropertyAccessFlags);
686 amglue_add_constant_noshort(PROPERTY_ACCESS_GET_MASK, PropertyAccessFlags);
687 amglue_add_constant_noshort(PROPERTY_ACCESS_SET_MASK, PropertyAccessFlags);
688 amglue_copy_to_tag(PropertyAccessFlags, constants);
689
690 amglue_add_enum_tag_fns(ConcurrencyParadigm);
691 amglue_add_constant_short(CONCURRENCY_PARADIGM_EXCLUSIVE, "EXCLUSIVE", ConcurrencyParadigm);
692 amglue_add_constant_short(CONCURRENCY_PARADIGM_SHARED_READ, "SHARED_READ", ConcurrencyParadigm);
693 amglue_add_constant_short(CONCURRENCY_PARADIGM_RANDOM_ACCESS, "RANDOM_ACCESS", ConcurrencyParadigm);
694 amglue_copy_to_tag(ConcurrencyParadigm, constants);
695
696 amglue_add_enum_tag_fns(StreamingRequirement);
697 amglue_add_constant_short(STREAMING_REQUIREMENT_NONE, "NONE", StreamingRequirement);
698 amglue_add_constant_short(STREAMING_REQUIREMENT_DESIRED, "DESIRED", StreamingRequirement);
699 amglue_add_constant_short(STREAMING_REQUIREMENT_REQUIRED, "REQUIRED", StreamingRequirement);
700 amglue_copy_to_tag(StreamingRequirement, constants);
701
702 amglue_add_enum_tag_fns(MediaAccessMode);
703 amglue_add_constant_short(MEDIA_ACCESS_MODE_READ_ONLY, "READ_ONLY", MediaAccessMode);
704 amglue_add_constant_short(MEDIA_ACCESS_MODE_WORM, "WORM", MediaAccessMode);
705 amglue_add_constant_short(MEDIA_ACCESS_MODE_READ_WRITE, "READ_WRITE", MediaAccessMode);
706 amglue_add_constant_short(MEDIA_ACCESS_MODE_WRITE_ONLY, "WRITE_ONLY", MediaAccessMode);
707 amglue_copy_to_tag(MediaAccessMode, constants);
708
709 amglue_add_enum_tag_fns(SizeAccuracy);
710 amglue_add_constant_short(SIZE_ACCURACY_UNKNOWN, "UNKNOWN", SizeAccuracy);
711 amglue_add_constant_short(SIZE_ACCURACY_ESTIMATE, "ESTIMATE", SizeAccuracy);
712 amglue_add_constant_short(SIZE_ACCURACY_REAL, "REAL", SizeAccuracy);
713 amglue_copy_to_tag(SizeAccuracy, constants);
714
715 amglue_add_flag_tag_fns(PropertySurety);
716 amglue_add_constant_short(PROPERTY_SURETY_BAD, "SURETY_BAD", PropertySurety);
717 amglue_add_constant_short(PROPERTY_SURETY_GOOD, "SURETY_GOOD", PropertySurety);
718 amglue_copy_to_tag(PropertySurety, constants);
719
720 amglue_add_flag_tag_fns(PropertySource);
721 amglue_add_constant_short(PROPERTY_SOURCE_DEFAULT, "SOURCE_DEFAULT", PropertySource);
722 amglue_add_constant_short(PROPERTY_SOURCE_DETECTED, "SOURCE_DETECTED", PropertySource);
723 amglue_add_constant_short(PROPERTY_SOURCE_USER, "SOURCE_USER", PropertySource);
724 amglue_copy_to_tag(PropertySource, constants);
725
726 %perlcode %{
727
728 # SWIG produces a sub-package for the Device "class", in this case named
729 # Amanda::Device::Device.  For user convenience, we allow Amanda::Device->new(..) to
730 # do the same thing.  This is a wrapper function, and not just a typeglob assignment,
731 # because we want to get the right blessing.
732 sub new {
733     my $pkg = shift;
734     Amanda::Device::Device->new(@_);
735 }
736 %}