Version 0.1.10 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->pvt->send_image)
72                 return 0;
73         return 1;
74 }
75
76 static int file_exists(char *filename)
77 {
78         int res;
79         struct stat st;
80         res = stat(filename, &st);
81         if (!res)
82                 return st.st_size;
83         return 0;
84 }
85
86 static void make_filename(char *buf, int len, char *filename, char *preflang, char *ext)
87 {
88         if (filename[0] == '/') {
89                 if (preflang && strlen(preflang))
90                         snprintf(buf, len, "%s-%s.%s", filename, preflang, ext);
91                 else
92                         snprintf(buf, len, "%s.%s", filename, ext);
93         } else {
94                 if (preflang && strlen(preflang))
95                         snprintf(buf, len, "%s/%s-%s.%s", AST_IMAGES, filename, preflang, ext);
96                 else
97                         snprintf(buf, len, "%s/%s.%s", AST_IMAGES, filename, ext);
98         }
99 }
100
101 struct ast_frame *ast_read_image(char *filename, char *preflang, int format)
102 {
103         struct ast_imager *i;
104         char buf[256];
105         char tmp[80];
106         char *e;
107         struct ast_imager *found = NULL;
108         int fd;
109         int len=0;
110         struct ast_frame *f = NULL;
111 #if 0 /* We need to have some sort of read-only lock */
112         ast_pthread_mutex_lock(&listlock);
113 #endif  
114         i = list;
115         while(!found && i) {
116                 if (i->format & format) {
117                         strncpy(tmp, i->exts, sizeof(tmp)-1);
118                         e = strtok(tmp, "|");
119                         while(e) {
120                                 make_filename(buf, sizeof(buf), filename, preflang, e);
121                                 if ((len = file_exists(buf))) {
122                                         found = i;
123                                         break;
124                                 }
125                                 make_filename(buf, sizeof(buf), filename, NULL, e);
126                                 if ((len = file_exists(buf))) {
127                                         found = i;
128                                         break;
129                                 }
130                                 e = strtok(NULL, "|");
131                         }
132                 }
133                 i = i->next;
134         }
135         if (found) {
136                 fd = open(buf, O_RDONLY);
137                 if (fd > -1) {
138                         if (!found->identify || found->identify(fd)) {
139                                 /* Reset file pointer */
140                                 lseek(fd, 0, SEEK_SET);
141                                 f = found->read_image(fd,len); 
142                         } else
143                                 ast_log(LOG_WARNING, "%s does not appear to be a %s file\n", buf, i->name);
144                         close(fd);
145                 } else
146                         ast_log(LOG_WARNING, "Unable to open '%s': %s\n", buf, strerror(errno));
147         } else
148                 ast_log(LOG_WARNING, "Image file '%s' not found\n", filename);
149 #if 0
150         ast_pthread_mutex_unlock(&listlock);
151 #endif  
152         return f;
153 }
154
155
156 int ast_send_image(struct ast_channel *chan, char *filename)
157 {
158         struct ast_frame *f;
159         int res = -1;
160         if (chan->pvt->send_image) {
161                 f = ast_read_image(filename, chan->language, -1);
162                 if (f) {
163                         res = chan->pvt->send_image(chan, f);
164                         ast_frfree(f);
165                 }
166         }
167         return res;
168 }
169
170 static int show_image_formats(int fd, int argc, char *argv[])
171 {
172 #define FORMAT "%10s %10s %50s %10s\n"
173 #define FORMAT2 "%10s %10s %50s %10d\n"
174         struct ast_imager *i;
175         if (argc != 3)
176                 return RESULT_SHOWUSAGE;
177         ast_cli(fd, FORMAT, "Name", "Extensions", "Description", "Format");
178         i = list;
179         while(i) {
180                 ast_cli(fd, FORMAT2, i->name, i->exts, i->desc, i->format);
181                 i = i->next;
182         };
183         return RESULT_SUCCESS;
184 }
185
186 struct ast_cli_entry show_images =
187 {
188         { "show", "image", "formats" },
189         show_image_formats,
190         "Displays image formats",
191 "Usage: show image formats\n"
192 "       displays currently registered image formats (if any)\n"
193 };
194
195
196 int ast_image_init(void)
197 {
198         ast_cli_register(&show_images);
199         return 0;
200 }
201