image.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 1999 - 2005, Digium, Inc.
  5. *
  6. * Mark Spencer <markster@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*! \file
  19. *
  20. * \brief Image Management
  21. *
  22. */
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <sys/time.h>
  27. #include <sys/stat.h>
  28. #include <signal.h>
  29. #include <errno.h>
  30. #include <unistd.h>
  31. #include "asterisk.h"
  32. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  33. #include "asterisk/sched.h"
  34. #include "asterisk/options.h"
  35. #include "asterisk/channel.h"
  36. #include "asterisk/logger.h"
  37. #include "asterisk/file.h"
  38. #include "asterisk/image.h"
  39. #include "asterisk/translate.h"
  40. #include "asterisk/cli.h"
  41. #include "asterisk/lock.h"
  42. static struct ast_imager *list;
  43. AST_MUTEX_DEFINE_STATIC(listlock);
  44. int ast_image_register(struct ast_imager *img)
  45. {
  46. if (option_verbose > 1)
  47. ast_verbose(VERBOSE_PREFIX_2 "Registered format '%s' (%s)\n", img->name, img->desc);
  48. ast_mutex_lock(&listlock);
  49. img->next = list;
  50. list = img;
  51. ast_mutex_unlock(&listlock);
  52. return 0;
  53. }
  54. void ast_image_unregister(struct ast_imager *img)
  55. {
  56. struct ast_imager *i, *prev = NULL;
  57. ast_mutex_lock(&listlock);
  58. i = list;
  59. while(i) {
  60. if (i == img) {
  61. if (prev)
  62. prev->next = i->next;
  63. else
  64. list = i->next;
  65. break;
  66. }
  67. prev = i;
  68. i = i->next;
  69. }
  70. ast_mutex_unlock(&listlock);
  71. if (i && (option_verbose > 1))
  72. ast_verbose(VERBOSE_PREFIX_2 "Unregistered format '%s' (%s)\n", img->name, img->desc);
  73. }
  74. int ast_supports_images(struct ast_channel *chan)
  75. {
  76. if (!chan || !chan->tech)
  77. return 0;
  78. if (!chan->tech->send_image)
  79. return 0;
  80. return 1;
  81. }
  82. static int file_exists(char *filename)
  83. {
  84. int res;
  85. struct stat st;
  86. res = stat(filename, &st);
  87. if (!res)
  88. return st.st_size;
  89. return 0;
  90. }
  91. static void make_filename(char *buf, int len, char *filename, char *preflang, char *ext)
  92. {
  93. if (filename[0] == '/') {
  94. if (preflang && strlen(preflang))
  95. snprintf(buf, len, "%s-%s.%s", filename, preflang, ext);
  96. else
  97. snprintf(buf, len, "%s.%s", filename, ext);
  98. } else {
  99. if (preflang && strlen(preflang))
  100. snprintf(buf, len, "%s/%s/%s-%s.%s", ast_config_AST_VAR_DIR, "images", filename, preflang, ext);
  101. else
  102. snprintf(buf, len, "%s/%s/%s.%s", ast_config_AST_VAR_DIR, "images", filename, ext);
  103. }
  104. }
  105. struct ast_frame *ast_read_image(char *filename, char *preflang, int format)
  106. {
  107. struct ast_imager *i;
  108. char buf[256];
  109. char tmp[80];
  110. char *e;
  111. struct ast_imager *found = NULL;
  112. int fd;
  113. int len=0;
  114. struct ast_frame *f = NULL;
  115. #if 0 /* We need to have some sort of read-only lock */
  116. ast_mutex_lock(&listlock);
  117. #endif
  118. i = list;
  119. while(!found && i) {
  120. if (i->format & format) {
  121. char *stringp=NULL;
  122. strncpy(tmp, i->exts, sizeof(tmp)-1);
  123. stringp=tmp;
  124. e = strsep(&stringp, "|");
  125. while(e) {
  126. make_filename(buf, sizeof(buf), filename, preflang, e);
  127. if ((len = file_exists(buf))) {
  128. found = i;
  129. break;
  130. }
  131. make_filename(buf, sizeof(buf), filename, NULL, e);
  132. if ((len = file_exists(buf))) {
  133. found = i;
  134. break;
  135. }
  136. e = strsep(&stringp, "|");
  137. }
  138. }
  139. i = i->next;
  140. }
  141. if (found) {
  142. fd = open(buf, O_RDONLY);
  143. if (fd > -1) {
  144. if (!found->identify || found->identify(fd)) {
  145. /* Reset file pointer */
  146. lseek(fd, 0, SEEK_SET);
  147. f = found->read_image(fd,len);
  148. } else
  149. ast_log(LOG_WARNING, "%s does not appear to be a %s file\n", buf, i->name);
  150. close(fd);
  151. } else
  152. ast_log(LOG_WARNING, "Unable to open '%s': %s\n", buf, strerror(errno));
  153. } else
  154. ast_log(LOG_WARNING, "Image file '%s' not found\n", filename);
  155. #if 0
  156. ast_mutex_unlock(&listlock);
  157. #endif
  158. return f;
  159. }
  160. int ast_send_image(struct ast_channel *chan, char *filename)
  161. {
  162. struct ast_frame *f;
  163. int res = -1;
  164. if (chan->tech->send_image) {
  165. f = ast_read_image(filename, chan->language, -1);
  166. if (f) {
  167. res = chan->tech->send_image(chan, f);
  168. ast_frfree(f);
  169. }
  170. }
  171. return res;
  172. }
  173. static int show_image_formats(int fd, int argc, char *argv[])
  174. {
  175. #define FORMAT "%10s %10s %50s %10s\n"
  176. #define FORMAT2 "%10s %10s %50s %10s\n"
  177. struct ast_imager *i;
  178. if (argc != 3)
  179. return RESULT_SHOWUSAGE;
  180. ast_cli(fd, FORMAT, "Name", "Extensions", "Description", "Format");
  181. i = list;
  182. while(i) {
  183. ast_cli(fd, FORMAT2, i->name, i->exts, i->desc, ast_getformatname(i->format));
  184. i = i->next;
  185. };
  186. return RESULT_SUCCESS;
  187. }
  188. struct ast_cli_entry show_images =
  189. {
  190. { "show", "image", "formats" },
  191. show_image_formats,
  192. "Displays image formats",
  193. "Usage: show image formats\n"
  194. " displays currently registered image formats (if any)\n"
  195. };
  196. int ast_image_init(void)
  197. {
  198. ast_cli_register(&show_images);
  199. return 0;
  200. }