![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
image.c
Go to the documentation of this file.
00001 /* 00002 * Asterisk -- An open source telephony toolkit. 00003 * 00004 * Copyright (C) 1999 - 2006, Digium, Inc. 00005 * 00006 * Mark Spencer <markster@digium.com> 00007 * 00008 * See http://www.asterisk.org for more information about 00009 * the Asterisk project. Please do not directly contact 00010 * any of the maintainers of this project for assistance; 00011 * the project provides a web site, mailing lists and IRC 00012 * channels for your use. 00013 * 00014 * This program is free software, distributed under the terms of 00015 * the GNU General Public License Version 2. See the LICENSE file 00016 * at the top of the source tree. 00017 */ 00018 00019 /*! \file 00020 * 00021 * \brief Image Management 00022 * 00023 * \author Mark Spencer <markster@digium.com> 00024 */ 00025 00026 #include "asterisk.h" 00027 00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 52352 $") 00029 00030 #include <stdio.h> 00031 #include <stdlib.h> 00032 #include <string.h> 00033 #include <sys/time.h> 00034 #include <sys/stat.h> 00035 #include <signal.h> 00036 #include <errno.h> 00037 #include <unistd.h> 00038 00039 #include "asterisk/sched.h" 00040 #include "asterisk/options.h" 00041 #include "asterisk/channel.h" 00042 #include "asterisk/logger.h" 00043 #include "asterisk/file.h" 00044 #include "asterisk/image.h" 00045 #include "asterisk/translate.h" 00046 #include "asterisk/cli.h" 00047 #include "asterisk/lock.h" 00048 00049 /* XXX Why don't we just use the formats struct for this? */ 00050 static AST_RWLIST_HEAD_STATIC(imagers, ast_imager); 00051 00052 int ast_image_register(struct ast_imager *img) 00053 { 00054 if (option_verbose > 1) 00055 ast_verbose(VERBOSE_PREFIX_2 "Registered format '%s' (%s)\n", img->name, img->desc); 00056 AST_RWLIST_WRLOCK(&imagers); 00057 AST_RWLIST_INSERT_HEAD(&imagers, img, list); 00058 AST_RWLIST_UNLOCK(&imagers); 00059 return 0; 00060 } 00061 00062 void ast_image_unregister(struct ast_imager *img) 00063 { 00064 struct ast_imager *i; 00065 00066 AST_RWLIST_WRLOCK(&imagers); 00067 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&imagers, i, list) { 00068 if (i == img) { 00069 AST_RWLIST_REMOVE_CURRENT(&imagers, list); 00070 break; 00071 } 00072 } 00073 AST_RWLIST_TRAVERSE_SAFE_END 00074 AST_RWLIST_UNLOCK(&imagers); 00075 if (i && (option_verbose > 1)) 00076 ast_verbose(VERBOSE_PREFIX_2 "Unregistered format '%s' (%s)\n", img->name, img->desc); 00077 } 00078 00079 int ast_supports_images(struct ast_channel *chan) 00080 { 00081 if (!chan || !chan->tech) 00082 return 0; 00083 if (!chan->tech->send_image) 00084 return 0; 00085 return 1; 00086 } 00087 00088 static int file_exists(char *filename) 00089 { 00090 int res; 00091 struct stat st; 00092 res = stat(filename, &st); 00093 if (!res) 00094 return st.st_size; 00095 return 0; 00096 } 00097 00098 static void make_filename(char *buf, int len, char *filename, const char *preflang, char *ext) 00099 { 00100 if (filename[0] == '/') { 00101 if (!ast_strlen_zero(preflang)) 00102 snprintf(buf, len, "%s-%s.%s", filename, preflang, ext); 00103 else 00104 snprintf(buf, len, "%s.%s", filename, ext); 00105 } else { 00106 if (!ast_strlen_zero(preflang)) 00107 snprintf(buf, len, "%s/%s/%s-%s.%s", ast_config_AST_DATA_DIR, "images", filename, preflang, ext); 00108 else 00109 snprintf(buf, len, "%s/%s/%s.%s", ast_config_AST_DATA_DIR, "images", filename, ext); 00110 } 00111 } 00112 00113 struct ast_frame *ast_read_image(char *filename, const char *preflang, int format) 00114 { 00115 struct ast_imager *i; 00116 char buf[256]; 00117 char tmp[80]; 00118 char *e; 00119 struct ast_imager *found = NULL; 00120 int fd; 00121 int len=0; 00122 struct ast_frame *f = NULL; 00123 00124 AST_RWLIST_RDLOCK(&imagers); 00125 AST_RWLIST_TRAVERSE(&imagers, i, list) { 00126 if (i->format & format) { 00127 char *stringp=NULL; 00128 ast_copy_string(tmp, i->exts, sizeof(tmp)); 00129 stringp=tmp; 00130 e = strsep(&stringp, "|"); 00131 while (e) { 00132 make_filename(buf, sizeof(buf), filename, preflang, e); 00133 if ((len = file_exists(buf))) { 00134 found = i; 00135 break; 00136 } 00137 make_filename(buf, sizeof(buf), filename, NULL, e); 00138 if ((len = file_exists(buf))) { 00139 found = i; 00140 break; 00141 } 00142 e = strsep(&stringp, "|"); 00143 } 00144 } 00145 if (found) 00146 break; 00147 } 00148 00149 if (found) { 00150 fd = open(buf, O_RDONLY); 00151 if (fd > -1) { 00152 if (!found->identify || found->identify(fd)) { 00153 /* Reset file pointer */ 00154 lseek(fd, 0, SEEK_SET); 00155 f = found->read_image(fd,len); 00156 } else 00157 ast_log(LOG_WARNING, "%s does not appear to be a %s file\n", buf, found->name); 00158 close(fd); 00159 } else 00160 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", buf, strerror(errno)); 00161 } else 00162 ast_log(LOG_WARNING, "Image file '%s' not found\n", filename); 00163 00164 AST_RWLIST_UNLOCK(&imagers); 00165 00166 return f; 00167 } 00168 00169 int ast_send_image(struct ast_channel *chan, char *filename) 00170 { 00171 struct ast_frame *f; 00172 int res = -1; 00173 if (chan->tech->send_image) { 00174 f = ast_read_image(filename, chan->language, -1); 00175 if (f) { 00176 res = chan->tech->send_image(chan, f); 00177 ast_frfree(f); 00178 } 00179 } 00180 return res; 00181 } 00182 00183 static int show_image_formats(int fd, int argc, char *argv[]) 00184 { 00185 #define FORMAT "%10s %10s %50s %10s\n" 00186 #define FORMAT2 "%10s %10s %50s %10s\n" 00187 struct ast_imager *i; 00188 if (argc != 4) 00189 return RESULT_SHOWUSAGE; 00190 ast_cli(fd, FORMAT, "Name", "Extensions", "Description", "Format"); 00191 AST_RWLIST_RDLOCK(&imagers); 00192 AST_RWLIST_TRAVERSE(&imagers, i, list) { 00193 ast_cli(fd, FORMAT2, i->name, i->exts, i->desc, ast_getformatname(i->format)); 00194 } 00195 AST_RWLIST_UNLOCK(&imagers); 00196 return RESULT_SUCCESS; 00197 } 00198 00199 struct ast_cli_entry cli_image[] = { 00200 { { "core", "show", "image", "formats" }, 00201 show_image_formats, "Displays image formats", 00202 "Usage: core show image formats\n" 00203 " displays currently registered image formats (if any)\n" }, 00204 }; 00205 00206 int ast_image_init(void) 00207 { 00208 ast_cli_register_multiple(cli_image, sizeof(cli_image) / sizeof(struct ast_cli_entry)); 00209 return 0; 00210 }