00001 /* 00002 * Template for export modules 00003 */ 00004 00005 /* $Id: exp-templ.c,v 1.7 2004/12/13 07:17:08 mschimek Exp $ */ 00006 00007 #ifdef HAVE_CONFIG_H 00008 # include "config.h" 00009 #endif 00010 00011 #include <stdio.h> 00012 #include <stdlib.h> 00013 #include <string.h> 00014 #include <errno.h> 00015 #include <limits.h> 00016 00017 #include "export.h" 00018 00019 typedef struct tmpl_instance 00020 { 00021 /* Common to all export modules */ 00022 vbi_export export; 00023 00024 /* Our private stuff */ 00025 00026 /* Options */ 00027 int flip; 00028 int day; 00029 int prime; 00030 double quality; 00031 char * comment; 00032 int weekday; 00033 00034 int counter; 00035 } tmpl_instance; 00036 00037 /* Safer than tmpl_instance *tmpl = (tmpl_instance *)(vbi_export *) e */ 00038 #define TMPL(e) PARENT(e, tmpl_instance, export); 00039 00040 static vbi_export * 00041 tmpl_new(void) 00042 { 00043 tmpl_instance *tmpl; 00044 00045 if (!(tmpl = calloc(1, sizeof(*tmpl)))) 00046 return NULL; 00047 00048 /* 00049 * The caller will initialize tmpl->export.class for us 00050 * and reset all options to their defaults, we only 00051 * have to initialize our private stuff. 00052 */ 00053 00054 tmpl->counter = 0; 00055 00056 return &tmpl->export; 00057 } 00058 00059 static void 00060 tmpl_delete(vbi_export *e) 00061 { 00062 tmpl_instance *tmpl = TMPL(e); 00063 00064 /* Uninitialize our private stuff and options */ 00065 00066 if (tmpl->comment) 00067 free(tmpl->comment); 00068 00069 free(tmpl); 00070 } 00071 00072 /* convenience */ 00073 #define elements(array) (sizeof(array) / sizeof(array[0])) 00074 00075 /* N_(), _() are NLS functions, see info gettext. */ 00076 static const char * 00077 string_menu_items[] = { 00078 N_("Sunday"), N_("Monday"), N_("Tuesday"), 00079 N_("Wednesday"), N_("Thursday"), N_("Friday"), N_("Saturday") 00080 }; 00081 00082 static int 00083 int_menu_items[] = { 00084 1, 3, 5, 7, 11, 13, 17, 19 00085 }; 00086 00087 static vbi_option_info 00088 tmpl_options[] = { 00089 VBI_OPTION_BOOL_INITIALIZER 00090 /* 00091 * Option keywords must be unique within their module 00092 * and shall contain only "AZaz09_" (be filesystem safe that is). 00093 * Note "network", "creator" and "reveal" are reserved generic 00094 * options, filtered by the export api functions. 00095 */ 00096 ("flip", N_("Boolean option"), 00097 FALSE, N_("This is a boolean option")), 00098 VBI_OPTION_INT_RANGE_INITIALIZER 00099 ("day", N_("Select a month day"), 00100 /* default, min, max, step, has no tooltip */ 00101 13, 1, 31, 1, NULL), 00102 VBI_OPTION_INT_MENU_INITIALIZER 00103 ("prime", N_("Select a prime"), 00104 0, int_menu_items, elements(int_menu_items), 00105 N_("Default is the first, '1'")), 00106 VBI_OPTION_REAL_RANGE_INITIALIZER 00107 ("quality", N_("Compression quality"), 00108 100, 1, 100, 0.01, NULL), 00109 /* VBI_OPTION_REAL_MENU_INITIALIZER like int */ 00110 VBI_OPTION_STRING_INITIALIZER 00111 ("comment", N_("Add a comment"), 00112 "default comment", N_("Another tooltip")), 00113 VBI_OPTION_MENU_INITIALIZER 00114 ("weekday", N_("Select a weekday"), 00115 2, string_menu_items, 7, N_("Default is Tuesday")) 00116 }; 00117 00118 /* 00119 * Enumerate our options (optional if we have no options). 00120 * Instead of using a table one could also dynamically create 00121 * vbi_option_info's in tmpl_instance. 00122 */ 00123 static vbi_option_info * 00124 option_enum(vbi_export *e, int index) 00125 { 00126 /* Enumeration 0 ... n */ 00127 if (index < 0 || index >= (int) elements(tmpl_options)) 00128 return NULL; 00129 00130 return tmpl_options + index; 00131 } 00132 00133 #define KEYWORD(str) (strcmp(keyword, str) == 0) 00134 00135 /* 00136 * Get an option (optional if we have no options). 00137 */ 00138 static vbi_bool 00139 option_get(vbi_export *e, const char *keyword, vbi_option_value *value) 00140 { 00141 tmpl_instance *tmpl = TMPL(e); 00142 00143 if (KEYWORD("flip")) { 00144 value->num = tmpl->flip; 00145 } else if (KEYWORD("day")) { 00146 value->num = tmpl->day; 00147 } else if (KEYWORD("prime")) { 00148 value->num = tmpl->prime; 00149 } else if (KEYWORD("quality")) { 00150 value->dbl = tmpl->quality; 00151 } else if (KEYWORD("comment")) { 00152 if (!(value->str = vbi_export_strdup(e, NULL, 00153 tmpl->comment ? tmpl->comment : ""))) 00154 return FALSE; 00155 } else if (KEYWORD("weekday")) { 00156 value->num = tmpl->weekday; 00157 } else { 00158 vbi_export_unknown_option(e, keyword); 00159 return FALSE; 00160 } 00161 00162 return TRUE; /* success */ 00163 } 00164 00165 /* 00166 * Set an option (optional if we have no options). 00167 */ 00168 static vbi_bool 00169 option_set(vbi_export *e, const char *keyword, va_list args) 00170 { 00171 tmpl_instance *tmpl = TMPL(e); 00172 00173 if (KEYWORD("flip")) { 00174 tmpl->flip = !!va_arg(args, int); 00175 } else if (KEYWORD("day")) { 00176 int day = va_arg(args, int); 00177 00178 /* or clamp */ 00179 if (day < 1 || day > 31) { 00180 vbi_export_invalid_option(e, keyword, day); 00181 return FALSE; 00182 } 00183 00184 tmpl->day = day; 00185 00186 } else if (KEYWORD("prime")) { 00187 unsigned int i; 00188 unsigned int d, dmin = UINT_MAX; 00189 int value = va_arg(args, int); 00190 00191 /* or return an error */ 00192 for (i = 0; i < elements(int_menu_items); i++) 00193 if ((d = abs(int_menu_items[i] - value)) < dmin) { 00194 tmpl->prime = int_menu_items[i]; 00195 dmin = d; 00196 } 00197 00198 } else if (KEYWORD("quality")) { 00199 double quality = va_arg(args, double); 00200 00201 /* or return an error */ 00202 if (quality < 1) 00203 quality = 1; 00204 else if (quality > 100) 00205 quality = 100; 00206 00207 tmpl->quality = quality; 00208 } else if (KEYWORD("comment")) { 00209 char *comment = va_arg(args, char *); 00210 00211 /* Note the option remains unchanged in case of error */ 00212 if (!vbi_export_strdup(e, &tmpl->comment, comment)) 00213 return FALSE; 00214 } else if (KEYWORD("weekday")) { 00215 int day = va_arg(args, int); 00216 00217 /* or return an error */ 00218 tmpl->weekday = day % 7; 00219 } else { 00220 vbi_export_unknown_option(e, keyword); 00221 return FALSE; 00222 } 00223 00224 return TRUE; /* success */ 00225 } 00226 00227 /* 00228 * The output function, mandatory. 00229 */ 00230 static vbi_bool 00231 export(vbi_export *e, FILE *fp, vbi_page *pg) 00232 { 00233 tmpl_instance *tmpl = TMPL(e); 00234 00235 /* 00236 * Write pg to fp, that's all. 00237 */ 00238 00239 tmpl->counter++; /* just for fun */ 00240 00241 /* 00242 * Should any of the module functions return unsuccessful 00243 * they better post a description of the problem. 00244 * Parameters like printf, no linefeeds '\n' please. 00245 */ 00246 /* 00247 vbi_export_error_printf(_("Writing failed: %s"), strerror(errno)); 00248 */ 00249 00250 return FALSE; /* no success (since we didn't write anything) */ 00251 } 00252 00253 /* 00254 * Let's describe us. 00255 * You can leave away assignments unless mandatory. 00256 */ 00257 static vbi_export_info 00258 info_tmpl = { 00259 /* The mandatory keyword must be unique and shall 00260 contain only "AZaz09_" */ 00261 .keyword = "templ", 00262 /* When omitted this module can still be used by 00263 libzvbi clients but won't be listed in a UI. */ 00264 .label = N_("Template"), 00265 .tooltip = N_("This is just an export template"), 00266 00267 .mime_type = "misc/example", 00268 .extension = "tmpl", 00269 }; 00270 00271 vbi_export_class 00272 vbi_export_class_tmpl = { 00273 ._public = &info_tmpl, 00274 00275 /* Functions to allocate and free a tmpl_class vbi_export instance. 00276 When you omit these, libzvbi will allocate a bare struct vbi_export */ 00277 ._new = tmpl_new, 00278 ._delete = tmpl_delete, 00279 00280 /* Functions to enumerate, read and write options */ 00281 .option_enum = option_enum, 00282 .option_get = option_get, 00283 .option_set = option_set, 00284 00285 /* Function to export a page, mandatory */ 00286 .export = export 00287 }; 00288 00289 /* 00290 * This is a constructor calling vbi_register_export_module(). 00291 * (Commented out since we don't want to register the example module.) 00292 */ 00293 #if 0 00294 VBI_AUTOREG_EXPORT_MODULE(vbi_export_class_tmpl) 00295 #endif