Version 0.1.11 from FTP
[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 <pthread.h>
17 #include <string.h>
18 #include <sys/time.h>
19 #include <sys/stat.h>
20 #include <signal.h>
21 #include <errno.h>
22 #include <unistd.h>
23 #include <asterisk/sched.h>
24 #include <asterisk/options.h>
25 #include <asterisk/channel.h>
26 #include <asterisk/channel_pvt.h>
27 #include <asterisk/logger.h>
28 #include <asterisk/file.h>
29 #include <asterisk/image.h>
30 #include <asterisk/translate.h>
31 #include <asterisk/cli.h>
32 #include "asterisk.h"
33
34 static struct ast_imager *list;
35 static pthread_mutex_t listlock = PTHREAD_MUTEX_INITIALIZER;
36
37 int ast_image_register(struct ast_imager *img)
38 {
39         if (option_verbose > 1)
40                 ast_verbose(VERBOSE_PREFIX_2 "Registered format '%s' (%s)\n", img->name, img->desc);
41         ast_pthread_mutex_lock(&listlock);
42         img->next = list;
43         list = img;
44         ast_pthread_mutex_unlock(&listlock);
45         return 0;
46 }
47
48 void ast_image_unregister(struct ast_imager *img)
49 {
50         struct ast_imager *i, *prev = NULL;
51         ast_pthread_mutex_lock(&listlock);
52         i = list;
53         while(i) {
54                 if (i == img) {
55                         if (prev) 
56                                 prev->next = i->next;
57                         else
58                                 list = i->next;
59                         break;
60                 }
61                 prev = i;
62                 i = i->next;
63         }
64         ast_pthread_mutex_unlock(&listlock);
65         if (i && (option_verbose > 1))
66                 ast_verbose(VERBOSE_PREFIX_2 "Registered format '%s' (%s)\n", img->name, img->desc);
67 }
68
69 int ast_supports_images(struct ast_channel *chan)
70 {
71         if (!chan || !chan->pvt)
72                 return 0;
73         if (!chan->pvt->send_image)
74                 return 0;
75         return 1;
76 }
77
78 static int file_exists(char *filename)
79 {
80         int res;
81         struct stat st;
82         res = stat(filename, &st);
83         if (!res)
84                 return st.st_size;
85         return 0;
86 }
87
88 static void make_filename(char *buf, int len, char *filename, char *preflang, char *ext)
89 {
90         if (filename[0] == '/') {
91                 if (preflang && strlen(preflang))
92                         snprintf(buf, len, "%s-%s.%s", filename, preflang, ext);
93                 else
94                         snprintf(buf, len, "%s.%s", filename, ext);
95         } else {
96                 if (preflang && strlen(preflang))
97                         snprintf(buf, len, "%s/%s-%s.%s", AST_IMAGES, filename, preflang, ext);
98                 else
99                         snprintf(buf, len, "%s/%s.%s", AST_IMAGES, filename, ext);
100         }
101 }
102
103 struct ast_frame *ast_read_image(char *filename, char *preflang, int format)
104 {
105         struct ast_imager *i;
106         char buf[256];
107         char tmp[80];
108         char *e;
109         struct ast_imager *found = NULL;
110         int fd;
111         int len=0;
112         struct ast_frame *f = NULL;
113 #if 0 /* We need to have some sort of read-only lock */
114         ast_pthread_mutex_lock(&listlock);
115 #endif  
116         i = list;
117         while(!found && i) {
118                 if (i->format & format) {
119                         strncpy(tmp, i->exts, sizeof(tmp)-1);
120                         e = strtok(tmp, "|");
121                         while(e) {
122                                 make_filename(buf, sizeof(buf), filename, preflang, e);
123                                 if ((len = file_exists(buf))) {
124                                         found = i;
125                                         break;
126                                 }
127                                 make_filename(buf, sizeof(buf), filename, NULL, e);
128                                 if ((len = file_exists(buf))) {
129                                         found = i;
130                                         break;
131                                 }
132                                 e = strtok(NULL, "|");
133                         }
134                 }
135                 i = i->next;
136         }
137         if (found) {
138                 fd = open(buf, O_RDONLY);
139                 if (fd > -1) {
140                         if (!found->identify || found->identify(fd)) {
141                                 /* Reset file pointer */
142                                 lseek(fd, 0, SEEK_SET);
143                                 f = found->read_image(fd,len); 
144                         } else
145                                 ast_log(LOG_WARNING, "%s does not appear to be a %s file\n", buf, i->name);
146                         close(fd);
147                 } else
148                         ast_log(LOG_WARNING, "Unable to open '%s': %s\n", buf, strerror(errno));
149         } else
150                 ast_log(LOG_WARNING, "Image file '%s' not found\n", filename);
151 #if 0
152         ast_pthread_mutex_unlock(&listlock);
153 #endif  
154         return f;
155 }
156
157
158 int ast_send_image(struct ast_channel *chan, char *filename)
159 {
160         struct ast_frame *f;
161         int res = -1;
162         if (chan->pvt->send_image) {
163                 f = ast_read_image(filename, chan->language, -1);
164                 if (f) {
165                         res = chan->pvt->send_image(chan, f);
166                         ast_frfree(f);
167                 }
168         }
169         return res;
170 }
171
172 static int show_image_formats(int fd, int argc, char *argv[])
173 {
174 #define FORMAT "%10s %10s %50s %10s\n"
175 #define FORMAT2 "%10s %10s %50s %10d\n"
176         struct ast_imager *i;
177         if (argc != 3)
178                 return RESULT_SHOWUSAGE;
179         ast_cli(fd, FORMAT, "Name", "Extensions", "Description", "Format");
180         i = list;
181         while(i) {
182                 ast_cli(fd, FORMAT2, i->name, i->exts, i->desc, i->format);
183                 i = i->next;
184         };
185         return RESULT_SUCCESS;
186 }
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
197
198 int ast_image_init(void)
199 {
200         ast_cli_register(&show_images);
201         return 0;
202 }
203