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