image.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 1999 - 2006, 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. * \author Mark Spencer <markster@digium.com>
  23. */
  24. /*** MODULEINFO
  25. <support_level>core</support_level>
  26. ***/
  27. #include "asterisk.h"
  28. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  29. #include <sys/time.h>
  30. #include <sys/stat.h>
  31. #include <signal.h>
  32. #include "asterisk/paths.h" /* use ast_config_AST_DATA_DIR */
  33. #include "asterisk/sched.h"
  34. #include "asterisk/channel.h"
  35. #include "asterisk/file.h"
  36. #include "asterisk/image.h"
  37. #include "asterisk/translate.h"
  38. #include "asterisk/cli.h"
  39. #include "asterisk/lock.h"
  40. /* XXX Why don't we just use the formats struct for this? */
  41. static AST_RWLIST_HEAD_STATIC(imagers, ast_imager);
  42. int ast_image_register(struct ast_imager *img)
  43. {
  44. AST_RWLIST_WRLOCK(&imagers);
  45. AST_RWLIST_INSERT_HEAD(&imagers, img, list);
  46. AST_RWLIST_UNLOCK(&imagers);
  47. ast_verb(2, "Registered format '%s' (%s)\n", img->name, img->desc);
  48. return 0;
  49. }
  50. void ast_image_unregister(struct ast_imager *img)
  51. {
  52. AST_RWLIST_WRLOCK(&imagers);
  53. img = AST_RWLIST_REMOVE(&imagers, img, list);
  54. AST_RWLIST_UNLOCK(&imagers);
  55. if (img)
  56. ast_verb(2, "Unregistered format '%s' (%s)\n", img->name, img->desc);
  57. }
  58. int ast_supports_images(struct ast_channel *chan)
  59. {
  60. if (!chan || !ast_channel_tech(chan))
  61. return 0;
  62. if (!ast_channel_tech(chan)->send_image)
  63. return 0;
  64. return 1;
  65. }
  66. static int file_exists(char *filename)
  67. {
  68. int res;
  69. struct stat st;
  70. res = stat(filename, &st);
  71. if (!res)
  72. return st.st_size;
  73. return 0;
  74. }
  75. static void make_filename(char *buf, int len, const char *filename, const char *preflang, char *ext)
  76. {
  77. if (filename[0] == '/') {
  78. if (!ast_strlen_zero(preflang))
  79. snprintf(buf, len, "%s-%s.%s", filename, preflang, ext);
  80. else
  81. snprintf(buf, len, "%s.%s", filename, ext);
  82. } else {
  83. if (!ast_strlen_zero(preflang))
  84. snprintf(buf, len, "%s/%s/%s-%s.%s", ast_config_AST_DATA_DIR, "images", filename, preflang, ext);
  85. else
  86. snprintf(buf, len, "%s/%s/%s.%s", ast_config_AST_DATA_DIR, "images", filename, ext);
  87. }
  88. }
  89. struct ast_frame *ast_read_image(const char *filename, const char *preflang, struct ast_format *format)
  90. {
  91. struct ast_imager *i;
  92. char buf[256];
  93. char tmp[80];
  94. char *e;
  95. struct ast_imager *found = NULL;
  96. int fd;
  97. int len=0;
  98. struct ast_frame *f = NULL;
  99. AST_RWLIST_RDLOCK(&imagers);
  100. AST_RWLIST_TRAVERSE(&imagers, i, list) {
  101. /* if NULL image format, just pick the first one, otherwise match it. */
  102. if (!format || (ast_format_cmp(i->format, format) == AST_FORMAT_CMP_EQUAL)) {
  103. char *stringp=NULL;
  104. ast_copy_string(tmp, i->exts, sizeof(tmp));
  105. stringp = tmp;
  106. e = strsep(&stringp, "|");
  107. while (e) {
  108. make_filename(buf, sizeof(buf), filename, preflang, e);
  109. if ((len = file_exists(buf))) {
  110. found = i;
  111. break;
  112. }
  113. make_filename(buf, sizeof(buf), filename, NULL, e);
  114. if ((len = file_exists(buf))) {
  115. found = i;
  116. break;
  117. }
  118. e = strsep(&stringp, "|");
  119. }
  120. }
  121. if (found)
  122. break;
  123. }
  124. if (found) {
  125. fd = open(buf, O_RDONLY);
  126. if (fd > -1) {
  127. if (!found->identify || found->identify(fd)) {
  128. /* Reset file pointer */
  129. lseek(fd, 0, SEEK_SET);
  130. f = found->read_image(fd, len);
  131. } else
  132. ast_log(LOG_WARNING, "%s does not appear to be a %s file\n", buf, found->name);
  133. close(fd);
  134. } else
  135. ast_log(LOG_WARNING, "Unable to open '%s': %s\n", buf, strerror(errno));
  136. } else
  137. ast_log(LOG_WARNING, "Image file '%s' not found\n", filename);
  138. AST_RWLIST_UNLOCK(&imagers);
  139. return f;
  140. }
  141. int ast_send_image(struct ast_channel *chan, const char *filename)
  142. {
  143. struct ast_frame *f;
  144. int res = -1;
  145. if (ast_channel_tech(chan)->send_image) {
  146. f = ast_read_image(filename, ast_channel_language(chan), NULL);
  147. if (f) {
  148. res = ast_channel_tech(chan)->send_image(chan, f);
  149. ast_frfree(f);
  150. }
  151. }
  152. return res;
  153. }
  154. static char *handle_core_show_image_formats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  155. {
  156. #define FORMAT "%10s %10s %50s %10s\n"
  157. #define FORMAT2 "%10s %10s %50s %10s\n"
  158. struct ast_imager *i;
  159. int count_fmt = 0;
  160. switch (cmd) {
  161. case CLI_INIT:
  162. e->command = "core show image formats";
  163. e->usage =
  164. "Usage: core show image formats\n"
  165. " Displays currently registered image formats (if any).\n";
  166. return NULL;
  167. case CLI_GENERATE:
  168. return NULL;
  169. }
  170. if (a->argc != 4)
  171. return CLI_SHOWUSAGE;
  172. ast_cli(a->fd, FORMAT, "Name", "Extensions", "Description", "Format");
  173. ast_cli(a->fd, FORMAT, "----", "----------", "-----------", "------");
  174. AST_RWLIST_RDLOCK(&imagers);
  175. AST_RWLIST_TRAVERSE(&imagers, i, list) {
  176. ast_cli(a->fd, FORMAT2, i->name, i->exts, i->desc, ast_format_get_name(i->format));
  177. count_fmt++;
  178. }
  179. AST_RWLIST_UNLOCK(&imagers);
  180. ast_cli(a->fd, "\n%d image format%s registered.\n", count_fmt, count_fmt == 1 ? "" : "s");
  181. return CLI_SUCCESS;
  182. }
  183. static struct ast_cli_entry cli_image[] = {
  184. AST_CLI_DEFINE(handle_core_show_image_formats, "Displays image formats")
  185. };
  186. static void image_shutdown(void)
  187. {
  188. ast_cli_unregister_multiple(cli_image, ARRAY_LEN(cli_image));
  189. }
  190. int ast_image_init(void)
  191. {
  192. ast_cli_register_multiple(cli_image, ARRAY_LEN(cli_image));
  193. ast_register_cleanup(image_shutdown);
  194. return 0;
  195. }