1 /* wmwebcam - modified vidcat - read the README file for more info */
6 * Copyright (C) 1998 - 2000 Rasca, Berlin
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include <sys/types.h>
30 #include <sys/ioctl.h>
34 #include <linux/types.h>
35 #include <linux/videodev.h>
41 #include <X11/extensions/shape.h>
43 #include "wmwebcam-mask.xbm"
47 //////////////////////// CHANGE THESE IF NECESSARY ///////////////////////////
49 #define DEF_WIDTH 352 // changing these requires adjustements
50 #define DEF_HEIGHT 288 // to the source, use default if possible
52 #define SENDINGDELAY 60 // default delay between saving jpeg
53 // images and scriptrunning (in seconds)
55 #define OUTPUTFILE "/tmp/wmwebcam.jpg" // default output file
56 #define CUSTOMSCRIPT "wmwebcam.pl" // default custom script
57 #define QUAL_DEFAULT 100 // default jpeg outputquality
59 //////////////////////////////////////////////////////////////////////////////
61 char *basename (const char *s
);
67 MiniRGB ui
; /* 64x64 main window buffer */
68 MiniRGB draw
; /* buffer with images etc */
70 void new_window(char *name
, char *mask_data
)
80 screen
= DefaultScreen(display
);
81 root
= DefaultRootWindow(display
);
83 sizehints
.flags
= USSize
;
85 sizehints
.height
= 64;
87 fg
= BlackPixel(display
, screen
);
88 bg
= WhitePixel(display
, screen
);
90 win
= XCreateSimpleWindow(display
, root
,
91 0, 0, sizehints
.width
,
92 sizehints
.height
, 1, fg
, bg
);
94 XCreateSimpleWindow(display
, win
, 0, 0,
95 sizehints
.width
, sizehints
.height
, 1, fg
, bg
);
97 XSetWMNormalHints(display
, win
, &sizehints
);
98 classhint
.res_name
= name
;
99 classhint
.res_class
= name
;
100 XSetClassHint(display
, win
, &classhint
);
102 XSelectInput(display
, win
,
103 ExposureMask
| ButtonPressMask
| ButtonReleaseMask
|
104 StructureNotifyMask
);
105 XSelectInput(display
, iconwin
,
106 ExposureMask
| ButtonPressMask
| ButtonReleaseMask
|
107 StructureNotifyMask
);
109 XStoreName(display
, win
, name
);
110 XSetIconName(display
, win
, name
);
112 gcval
.foreground
= fg
;
113 gcval
.background
= bg
;
114 gcval
.graphics_exposures
= False
;
116 XCreateGC(display
, win
,
117 GCForeground
| GCBackground
| GCGraphicsExposures
,
120 mask
= XCreateBitmapFromData(display
, win
, mask_data
, 128, 64);
122 XShapeCombineMask(display
, win
, ShapeBounding
, 0, 0,
124 XShapeCombineMask(display
, iconwin
, ShapeBounding
, 0,
127 wmhints
.initial_state
= WithdrawnState
;
128 wmhints
.flags
= StateHint
;
129 wmhints
.icon_window
= iconwin
;
130 wmhints
.icon_x
= sizehints
.x
;
131 wmhints
.icon_y
= sizehints
.y
;
132 wmhints
.window_group
= win
;
134 StateHint
| IconWindowHint
| IconPositionHint
| WindowGroupHint
;
135 XSetWMHints(display
, win
, &wmhints
);
137 XMapWindow(display
, win
);
140 void redraw_window(void)
142 minirgb_draw(win
, gc
, 0, 0, 64, 64, &ui
);
143 minirgb_draw(iconwin
, gc
, 0, 0, 64, 64, &ui
);
146 #define copyXPMArea(x, y, w, h, dx, dy) minirgb_copy(&draw, &ui, x, y, w, h, dx, dy)
150 get_image (int dev
, int width
, int height
,int *size
)
152 struct video_capability vid_caps
;
153 struct video_mbuf vid_buf
;
154 struct video_mmap vid_mmap
;
158 if (ioctl (dev
, VIDIOCGCAP
, &vid_caps
) == -1) {
159 perror ("ioctl (VIDIOCGCAP)");
163 if (ioctl (dev
, VIDIOCGMBUF
, &vid_buf
) == -1) {
164 struct video_window vid_win
;
166 if (ioctl (dev
, VIDIOCGWIN
, &vid_win
) != -1) {
167 vid_win
.width
= width
;
168 vid_win
.height
= height
;
169 if (ioctl (dev
, VIDIOCSWIN
, &vid_win
) == -1)
173 map
= malloc (width
* height
* 3);
174 len
= read (dev
, map
, width
* height
* 3);
175 if (len
<= 0) { free (map
); return (NULL
); }
180 map
= mmap (0, vid_buf
.size
, PROT_READ
|PROT_WRITE
,MAP_SHARED
,dev
,0);
181 if ((unsigned char *)-1 == (unsigned char *)map
) {
186 vid_mmap
.format
= VIDEO_PALETTE_RGB24
;
188 vid_mmap
.width
= width
;
189 vid_mmap
.height
= height
;
190 if (ioctl (dev
, VIDIOCMCAPTURE
, &vid_mmap
) == -1) {
191 perror ("VIDIOCMCAPTURE");
192 munmap (map
, vid_buf
.size
);
195 if (ioctl (dev
, VIDIOCSYNC
, &vid_mmap
) == -1) {
196 perror ("VIDIOCSYNC");
197 munmap (map
, vid_buf
.size
);
200 *size
= vid_buf
.size
;
205 put_image_jpeg (char *image
, int width
, int height
, int quality
)
209 int y
, x
, line_width
;
211 struct jpeg_compress_struct cjpeg
;
212 struct jpeg_error_mgr jerr
;
215 output
= fopen("/tmp/wmwebcam.jpg","w");
219 line
= malloc (width
* 3);
222 cjpeg
.err
= jpeg_std_error(&jerr
);
223 jpeg_create_compress (&cjpeg
);
224 cjpeg
.image_width
= width
;
225 cjpeg
.image_height
= height
;
226 cjpeg
.input_components
= 3;
227 cjpeg
.in_color_space
= JCS_RGB
;
228 jpeg_set_defaults (&cjpeg
);
230 jpeg_set_quality (&cjpeg
, quality
, TRUE
);
231 cjpeg
.dct_method
= JDCT_FASTEST
;
232 jpeg_stdio_dest (&cjpeg
, output
);
234 jpeg_start_compress (&cjpeg
, TRUE
);
237 line_width
= width
* 3;
238 for ( y
= 0; y
< height
; y
++) {
239 for (x
= 0; x
< line_width
; x
+=3) {
240 line
[x
] = image
[x
+2];
241 line
[x
+1] = image
[x
+1];
242 line
[x
+2] = image
[x
];
244 jpeg_write_scanlines (&cjpeg
, row_ptr
, 1);
247 jpeg_finish_compress (&cjpeg
);
248 jpeg_destroy_compress (&cjpeg
);
254 put_image (char *image
, int width
, int height
)
258 unsigned char *p
= (unsigned char *)image
;
259 unsigned char *buf
= (unsigned char *)image
;
261 for (y
= 0; y
< 288; y
++ ) {
263 for (x
= 0; x
< 348; x
++ ) {
264 r
= buf
[0]; g
= buf
[1]; b
= buf
[2]; buf
+= 3;
268 *p
++ = b
; *p
++ = g
; *p
++ = r
;
273 memcpy(draw
.mem
, image
, 352*288*3);
277 main (int argc
, char *argv
[])
280 char *image
, *device
= VIDEO_DEV
;
282 int delay
= SENDINGDELAY
;
283 int width
= DEF_WIDTH
, height
= DEF_HEIGHT
, size
, dev
= -1;
285 int quality
= QUAL_DEFAULT
;
287 display
= XOpenDisplay(NULL
);
289 fprintf(stderr
, "Unable to open default display\n");
293 if (minirgb_init(display
)) {
294 fprintf(stderr
, "minirgb init failed!\n");
298 new_window("wmwebcam", wmwebcam_mask_bits
);
299 minirgb_new(&ui
, 64, 64);
300 minirgb_new(&draw
, 352, 288);
301 copyXPMArea(0, 0, 64, 64, 0, 0);
305 dev
= open (device
, O_RDWR
);
308 fprintf (stderr
, "Can't open device %s\n", VIDEO_DEV
);
316 image
= get_image (dev
, width
, height
, &size
);
317 if (!size
) close (dev
);
321 if (delay
== SENDINGDELAY
) { put_image_jpeg(image
, width
, height
, quality
); }
323 put_image(image
, width
, height
);
325 copyXPMArea(1, 1, 54, 47, 5, 5);
327 while (XPending(display
)) {
328 XNextEvent(display
, &Event
);
329 switch (Event
.type
) {
334 XCloseDisplay(display
);
342 munmap (image
, size
);
348 // close device first before starting to send the image
350 if (delay
== SENDINGDELAY
) { system (CUSTOMSCRIPT
); delay
= 0; }
356 fprintf (stderr
, "Error: Can't get image\n"); exit(0);