~ubuntu-branches/ubuntu/jaunty/xvidcap/jaunty-proposed

« back to all changes in this revision

Viewing changes to src/capture.c

  • Committer: Bazaar Package Importer
  • Author(s): Christian Marillat
  • Date: 2004-08-29 10:53:42 UTC
  • Revision ID: james.westby@ubuntu.com-20040829105342-qgmnry37eadfkoxx
Tags: upstream-1.1.3
ImportĀ upstreamĀ versionĀ 1.1.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * capture.c, vi: tabstop=4
 
3
 * capture module, controled by timer functions
 
4
 *
 
5
 * Copyright (C) 1997-98 Rasca, Berlin
 
6
 * Copyright (C) 2003,04 Karl H. Beckers, Frankfurt
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or modify
 
9
 * it under the terms of the GNU General Public License as published by
 
10
 * the Free Software Foundation; either version 2 of the License, or
 
11
 * (at your option) any later version.
 
12
 *
 
13
 * This program is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 * GNU General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU General Public License
 
19
 * along with this program; if not, write to the Free Software
 
20
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
21
 *
 
22
 *
 
23
 * This file contains routines used for capturing individual frames.
 
24
 * Theese routines are called from the record button callback in
 
25
 * the GUI and call themselves again till they are stopped by a stop
 
26
 * button event handler, a timeout, exceeding the maximum number of
 
27
 * frames (see the various VC_... states)
 
28
 *
 
29
 */
 
30
 
 
31
#include "../config.h"  /* autoconf output */
 
32
 
 
33
#include <stdio.h>
 
34
#ifdef HAVE_STDINT_H
 
35
#include <stdint.h>
 
36
#endif //HAVE_STDINT_H
 
37
#include <limits.h>
 
38
#include <sys/time.h>
 
39
#include <time.h>
 
40
#include <unistd.h>
 
41
#ifdef SOLARIS
 
42
#include <X11/X.h>
 
43
#include <X11/Xlib.h>
 
44
#endif //SOLARIS
 
45
#include <X11/Intrinsic.h>
 
46
#include <X11/StringDefs.h>
 
47
#include <X11/XWDFile.h>
 
48
#include <X11/Xproto.h>
 
49
#include <X11/Xlibint.h>
 
50
#include <X11/cursorfont.h>
 
51
#ifdef HAVE_SHMAT
 
52
#include <sys/ipc.h>
 
53
#include <sys/shm.h>
 
54
#include <X11/extensions/XShm.h>
 
55
#endif //HAVE_SHMAT
 
56
#ifdef HasDGA
 
57
#include <X11/extensions/xf86dga.h>
 
58
#endif //HasDGA
 
59
#ifdef HasVideo4Linux
 
60
#include <fcntl.h>
 
61
#include <sys/mman.h>
 
62
#include <sys/ioctl.h>
 
63
#include "video.h"
 
64
#endif //HasVideo4Linux
 
65
 
 
66
#include "capture.h"
 
67
#include "job.h"
 
68
#include "control.h"
 
69
#include "main.h"
 
70
 
 
71
 
 
72
uint16_t mousePointerBlack[] = { 0, 49152, 40960, 36864, 34816, 33792, 33280, 33024, 32896, 32832,
 
73
33728, 37376, 43264, 51456, 1152, 1152, 576, 576, 448, 0 };
 
74
uint16_t mousePointerWhite[] = { 0, 0, 16384, 24576, 28672, 30720, 31744, 32256, 32512, 32640, 31744,
 
75
27648, 17920, 1536, 768, 768, 384, 384, 0, 0 };
 
76
 
 
77
 
 
78
static void getCurrentPointer(int *x, int *y, Job *mjob) {
 
79
    Window mrootwindow, childwindow;
 
80
    int dummy, num_atoms;
 
81
    Atom *m_atom;
 
82
    Display *dpy;
 
83
    Screen *scr;
 
84
    
 
85
    if ( ! (mjob->flags & FLG_NOGUI ) ) {
 
86
        scr = mjob->win_attr.screen;
 
87
        dpy = DisplayOfScreen(scr);
 
88
    } else {
 
89
        dpy = XOpenDisplay(NULL);
 
90
    }
 
91
    mrootwindow = DefaultRootWindow(dpy);
 
92
    
 
93
    if (XQueryPointer(dpy, mrootwindow, &mrootwindow, &childwindow,
 
94
    x, y, &dummy, &dummy, &dummy)) {
 
95
        if (mjob->flags & FLG_RUN_VERBOSE) {
 
96
            int bla, ev_base, er_base, major, minor;
 
97
            Bool xTest;
 
98
            Cursor xCursor;
 
99
            
 
100
//            printf("Mouse pointer at x/y : %i/%i\n", *x, *y);
 
101
//            printf("Relative mouse pointer at x/y : %i/%i\n", (*x - mjob->area->x), (*y - mjob->area->y));
 
102
            
 
103
            //                  printf("root window pointer: %p - child window pointer: %p\n", &mrootwindow, &childwindow);
 
104
            /*                  m_atom = XListProperties(dpy, childwindow, &num_atoms);
 
105
             for (bla = 0; bla < num_atoms; bla++) {
 
106
             printf("atom %i name: %s\n", bla, XGetAtomName(dpy,
 
107
             m_atom[bla]));
 
108
             } */
 
109
            
 
110
            /*                  xTest = XTestQueryExtension( dpy, &ev_base, &er_base, &major, &minor);
 
111
             if ( xTest = True ) {
 
112
             int n;
 
113
            
 
114
             for (n = 0; n < (XC_num_glyphs - 1); n++) {
 
115
             xTest = 0;
 
116
            
 
117
             xCursor = XCreateFontCursor( dpy, n);
 
118
             xTest = XTestCompareCursorWithWindow( dpy, childwindow, xCursor );
 
119
             if (xTest = True ) printf("xTest: %i - glyph: %i\n", (int) xTest, n);
 
120
             }
 
121
             } else {
 
122
             printf("XTEST extension not supported\n");
 
123
             } */
 
124
            
 
125
        }
 
126
    } else {
 
127
        printf("couldn't find mouse pointer for disp: %p , rootwindow: %p\n", dpy,
 
128
        RootWindow(dpy, DefaultScreen(dpy)));
 
129
        *x = -1;
 
130
        *y = -1;
 
131
    }
 
132
    
 
133
    if ( mjob->flags & FLG_NOGUI ) {
 
134
        XCloseDisplay(dpy);
 
135
    }
 
136
}
 
137
 
 
138
 
 
139
 
 
140
static void paintMousePointer(int *x, int *y, Job *mjob, XImage *image) {
 
141
    if ( (*x - mjob->area->x) >= 0 && *x < (mjob->area->width + mjob->area->x) &&
 
142
    (*y - mjob->area->y) >= 0 && *y < (mjob->area->height + mjob->area->y) ) {
 
143
        int line;
 
144
        uint8_t *im_data = image->data;
 
145
        
 
146
        im_data += (image->bytes_per_line * (*y - mjob->area->y)); // shift to right line
 
147
        im_data += (image->bits_per_pixel / 8 * (*x - mjob->area->x)); // shift to right pixel
 
148
        
 
149
        switch(image->bits_per_pixel) {
 
150
            case 32: {
 
151
                uint32_t *cursor;
 
152
                int width;
 
153
                uint16_t bm_b, bm_w, mask;
 
154
                
 
155
                for (line = 0; line < 20; line++ ) {
 
156
                    if (mjob->mouseWanted == 1) {
 
157
                        bm_b = mousePointerBlack[line];
 
158
                        bm_w = mousePointerWhite[line];
 
159
                    } else {
 
160
                        bm_b = mousePointerWhite[line];
 
161
                        bm_w = mousePointerBlack[line];
 
162
                    }
 
163
                    mask = ( 0x0001 << 15 );
 
164
                    
 
165
                    for (cursor = (uint32_t*) im_data, width = 0;
 
166
                    ((width + *x) < (mjob->area->width + mjob->area->x)&&width < 16);
 
167
                    cursor++, width++) {
 
168
                        //                                                      Boolean pointer_b_bit, pointer_w_bit;
 
169
                        
 
170
                        //                                                      pointer_b_bit = ( ( bm_b & mask ) > 0 );
 
171
                        //                                                      pointer_w_bit = ( ( bm_w & mask ) > 0 );
 
172
                        //                                                      printf("%i ", pointer_b_bit, pointer_w_bit );
 
173
                        
 
174
                        if ( ( bm_b & mask ) > 0 ) {
 
175
                            *cursor &= ((~ image->red_mask) & (~ image->green_mask) & (~
 
176
                            image->blue_mask ));
 
177
                        } else if ( ( bm_w & mask ) > 0 ) {
 
178
                            *cursor |= (image->red_mask | image->green_mask | image->blue_mask );
 
179
                        }
 
180
                        mask >>= 1;
 
181
                        
 
182
                    }
 
183
                    //                                          printf("\n");
 
184
                    
 
185
                    im_data += image->bytes_per_line;
 
186
                }
 
187
            }
 
188
            break;
 
189
            case 24: // not sure this can occur at all ..........
 
190
                printf("input image bits_per_pixel %i not implemented with mouse pointer capture ... aborting!\n",
 
191
                image->bits_per_pixel);
 
192
                printf("Please file a bug at http://www.sourceforge.net/projects/xvidcap/\n");
 
193
                exit(1);
 
194
                break;
 
195
            case 16: {
 
196
                uint16_t *cursor;
 
197
                int width;
 
198
                uint16_t bm_b, bm_w, mask;
 
199
                
 
200
                for (line = 0; line < 16; line++ ) {
 
201
                    if (mjob->mouseWanted == 1) {
 
202
                        bm_b = mousePointerBlack[line];
 
203
                        bm_w = mousePointerWhite[line];
 
204
                    } else {
 
205
                        bm_b = mousePointerWhite[line];
 
206
                        bm_w = mousePointerBlack[line];
 
207
                    }
 
208
                    mask = ( 0x0001 << 15 );
 
209
                    
 
210
                    for (cursor = (uint16_t*) im_data, width = 0;
 
211
                    ((width + *x) < (mjob->area->width + mjob->area->x)&&width < 6);
 
212
                    cursor++, width++) {
 
213
                        //                                                      Boolean pointer_b_bit, pointer_w_bit;
 
214
                        
 
215
                        //                                                      pointer_b_bit = ( ( bm_b & mask ) > 0 );
 
216
                        //                                                      pointer_w_bit = ( ( bm_w & mask ) > 0 );
 
217
                        //                                                      printf("%i ", pointer_b_bit, pointer_w_bit );
 
218
                        
 
219
                        if ( ( bm_b & mask ) > 0 ) {
 
220
                            *cursor &= ((~ image->red_mask) & (~ image->green_mask) & (~
 
221
                            image->blue_mask ));
 
222
                        } else if ( ( bm_w & mask ) > 0 ) {
 
223
                            *cursor |= (image->red_mask | image->green_mask | image->blue_mask );
 
224
                        }
 
225
                        mask >>= 1;
 
226
                        
 
227
                    }
 
228
                    //                                          printf("\n");
 
229
                    
 
230
                    im_data += image->bytes_per_line;
 
231
                }
 
232
            }
 
233
            break;
 
234
            case 8: {
 
235
                uint8_t *cursor;
 
236
                int width;
 
237
                uint16_t bm_b, bm_w, mask;
 
238
                
 
239
                for (line = 0; line < 16; line++ ) {
 
240
                    if (mjob->mouseWanted == 1) {
 
241
                        bm_b = mousePointerBlack[line];
 
242
                        bm_w = mousePointerWhite[line];
 
243
                    } else {
 
244
                        bm_b = mousePointerWhite[line];
 
245
                        bm_w = mousePointerBlack[line];
 
246
                    }
 
247
                    mask = ( 0x0001 << 15 );
 
248
                    
 
249
                    for (cursor = im_data, width = 0;
 
250
                    ((width + *x) < (mjob->area->width + mjob->area->x)&&width < 6);
 
251
                    cursor++, width++) {
 
252
                        //                                                      Boolean pointer_b_bit, pointer_w_bit;
 
253
                        
 
254
                        //                                                      pointer_b_bit = ( ( bm_b & mask ) > 0 );
 
255
                        //                                                      pointer_w_bit = ( ( bm_w & mask ) > 0 );
 
256
                        //                                                      printf("%i ", pointer_b_bit, pointer_w_bit );
 
257
                        
 
258
                        if ( ( bm_b & mask ) > 0 ) {
 
259
                            *cursor = 0;
 
260
                        } else if ( ( bm_w & mask ) > 0 ) {
 
261
                            *cursor = 1;
 
262
                        }
 
263
                        mask >>= 1;
 
264
                        
 
265
                    }
 
266
                    //                                          printf("\n");
 
267
                    
 
268
                    im_data += image->bytes_per_line;
 
269
                }
 
270
            }
 
271
            break;
 
272
            default:
 
273
                printf("input image bits_per_pixel %i not supported with mouse pointer capture ... aborting!\n",
 
274
                image->bits_per_pixel);
 
275
                exit(1);
 
276
                
 
277
        }
 
278
        
 
279
    }
 
280
    
 
281
}
 
282
 
 
283
 
 
284
 
 
285
/*
 
286
 * just read new data in the image structure, the image
 
287
 * structure inclusive the data area must be allocated before
 
288
 */
 
289
static Boolean
 
290
XGetZPixmap(Display *dpy, Drawable d, XImage *image, int x, int y) {
 
291
    xGetImageReply rep;
 
292
    register xGetImageReq *req;
 
293
    long nbytes;
 
294
    
 
295
    if (!image)
 
296
        return (False);
 
297
    LockDisplay(dpy);
 
298
    GetReq(GetImage, req);
 
299
    /*
 
300
     * first set up the standard stuff in the request
 
301
     */
 
302
    req->drawable = d;
 
303
    req->x = x;
 
304
    req->y = y;
 
305
    req->width = image->width;
 
306
    req->height = image->height;
 
307
    req->planeMask = AllPlanes;
 
308
    req->format = ZPixmap;
 
309
    
 
310
    if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0 ||
 
311
    rep.length == 0) {
 
312
        UnlockDisplay(dpy);
 
313
        SyncHandle();
 
314
        return (False);
 
315
    }
 
316
    
 
317
    nbytes = (long)rep.length << 2;
 
318
    _XReadPad(dpy, image->data, nbytes);
 
319
    
 
320
    UnlockDisplay(dpy);
 
321
    SyncHandle();
 
322
    return (True);
 
323
}
 
324
 
 
325
/*
 
326
 * timer callback for capturing
 
327
 */
 
328
Boolean
 
329
TCbCaptureX11(XtPointer xtp, XtIntervalId *id) {
 
330
    Job *job = (Job *) xtp;
 
331
    static char file[PATH_MAX+1];
 
332
    static XImage *image = NULL;
 
333
    static void *fp = NULL;
 
334
    long time, time1;
 
335
    struct timeval curr_time;
 
336
    static Display *dpy;
 
337
    Screen *scr;
 
338
    
 
339
    #ifdef DEBUG2
 
340
    printf("TCbCapture() pic_no=%d - state=%i\n", job->pic_no, job->state);
 
341
    #endif
 
342
    if ((job->state & VC_PAUSE) && !(job->state & VC_STEP)) {
 
343
        XVC_AddTimeout(job->time_per_frame, job->capture, job);
 
344
        
 
345
    } else if (job->state & VC_REC) {
 
346
        if (job->max_frames && (
 
347
        (job->pic_no - job->start_no )> job->max_frames - 1)) {
 
348
            if (job->flags & FLG_RUN_VERBOSE)
 
349
                printf("Stopped! pic_no=%d max_frames=%d\n",
 
350
                job->pic_no, job->max_frames);
 
351
            if (!(job->flags & FLG_RUN_VERBOSE))
 
352
                XVC_ChangeGUILabel(job->pic_no);
 
353
 
 
354
            if (job->flags & FLG_AUTO_CONTINUE) job->state |= VC_CONTINUE;
 
355
            goto CLEAN_X11;
 
356
        }
 
357
        job->state &= ~VC_STEP;
 
358
        gettimeofday(&curr_time, NULL);
 
359
        time = curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000;
 
360
        
 
361
        if ((!(job->flags & FLG_MULTI_IMAGE)) ||
 
362
        ((job->flags & FLG_MULTI_IMAGE) && (job->state & VC_START))) {
 
363
            if ((job->flags & FLG_MULTI_IMAGE) != 0) {
 
364
                sprintf(file, job->file, job->movie_no);
 
365
            } else {
 
366
                sprintf(file, job->file, job->pic_no);
 
367
            }
 
368
            fp = (*job->open)(file, job->open_flags);
 
369
            if (!fp) {
 
370
                perror(file);
 
371
                job->state = VC_STOP;
 
372
                return;
 
373
            }
 
374
        }
 
375
        if (job->state & VC_START) {
 
376
            /*
 
377
             * the first time this procedure is started
 
378
             * we must create a new image ..
 
379
             *
 
380
             */
 
381
            int x, y;
 
382
            
 
383
            if ( ! (job->flags & FLG_NOGUI ) ) {
 
384
                scr = job->win_attr.screen;
 
385
                dpy = DisplayOfScreen(scr);
 
386
            } else {
 
387
                dpy = XOpenDisplay(NULL);
 
388
            }
 
389
            
 
390
            if (job->mouseWanted > 0) {
 
391
                getCurrentPointer(&x, &y, job);
 
392
            }
 
393
            
 
394
            image = XGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)),
 
395
            job->area->x, job->area->y,
 
396
            job->area->width, job->area->height, AllPlanes, ZPixmap);
 
397
            if (!image) {
 
398
                printf("Can't get image: %dx%d+%d+%d\n", job->area->width,
 
399
                job->area->height, job->area->x, job->area->y);
 
400
                job->state = VC_STOP;
 
401
            } else {
 
402
                if (job->mouseWanted > 0) {
 
403
                    paintMousePointer(&x, &y, job, image);
 
404
                }
 
405
                (*job->save) (fp, image, job);
 
406
                job->state &= ~VC_START;
 
407
            }
 
408
        } else {
 
409
            int x, y;
 
410
            
 
411
            /* just read new data in the image structure
 
412
             */
 
413
            if (job->mouseWanted > 0) {
 
414
                getCurrentPointer(&x, &y, job);
 
415
            }
 
416
            
 
417
            if (XGetZPixmap(dpy,
 
418
            RootWindow(dpy, DefaultScreen(dpy)),
 
419
            image, job->area->x, job->area->y)) {
 
420
                if (job->mouseWanted > 0) {
 
421
                    paintMousePointer(&x, &y, job, image);
 
422
                }
 
423
                (*job->save) (fp, image, job);
 
424
            } else {
 
425
                printf("XGetZPixmap returned 'False'!\n");
 
426
            }
 
427
        }
 
428
        if (!(job->flags & FLG_MULTI_IMAGE))
 
429
            (*job->close) (fp);
 
430
        
 
431
        /* substract the time we needed for creating and saving
 
432
         * the frame to the file
 
433
         */
 
434
        gettimeofday(&curr_time, NULL);
 
435
        time1 = (curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000) - time;
 
436
        // update monitor widget, here time is the time the capture took
 
437
        // time == 0 resets led_meter
 
438
        if (! time1) time1 = 1;
 
439
        XVC_FrameMonitor(job, time1);
 
440
//      printf("time: %i time_per_frame: %i\n", time1, job->time_per_frame);
 
441
        // calculate the remaining time we have till capture of next frame
 
442
        time1 = job->time_per_frame - time1;
 
443
        
 
444
        if ( time1 > 0 ) {
 
445
            // get time again because updating frame drop meter took some time
 
446
            gettimeofday(&curr_time, NULL);
 
447
            time = (curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000) - time;
 
448
            time = job->time_per_frame - time;
 
449
        } else {
 
450
            time = time1;
 
451
        }
 
452
        if (time < 0) {
 
453
            if (job->flags & FLG_RUN_VERBOSE)
 
454
                printf("missing %ld milli secs (%d needed per frame), pic no %d\n",
 
455
                time, job->time_per_frame, job->pic_no);
 
456
        }
 
457
        if ( time < 2 ) time = 2;
 
458
 
 
459
        XVC_AddTimeout(time, job->capture, job);
 
460
 
 
461
        job->pic_no += job->step;
 
462
        if (time >= 2 )
 
463
            XVC_ChangeGUILabel(job->pic_no);
 
464
 
 
465
    } else {
 
466
        int orig_state;
 
467
        
 
468
        /* clean up */
 
469
        CLEAN_X11:
 
470
            orig_state = job->state; // store state here
 
471
            
 
472
            /* may be the last update failed .. so do it here before stop
 
473
             */
 
474
            XVC_ChangeGUILabel(job->pic_no);
 
475
            XVC_FrameMonitor(job, 0);
 
476
            
 
477
            job->state = VC_STOP;
 
478
            if (image) {
 
479
                XDestroyImage(image);
 
480
                image = NULL;
 
481
            }
 
482
            /* set the sensitive stuff for the control panel
 
483
             * if we don't autocontinue */
 
484
            if ((orig_state & VC_CONTINUE) == 0) 
 
485
                XVC_StopCapture(job);
 
486
            
 
487
            /* clean up the save routines in xtoXXX.c
 
488
             */
 
489
            if (job->clean)
 
490
                (*job->clean) (job);
 
491
            if (job->flags & FLG_MULTI_IMAGE)
 
492
                if (fp)
 
493
                    (*job->close) (fp);
 
494
            fp = NULL;
 
495
            
 
496
            if ((orig_state & VC_CONTINUE) == 0) {
 
497
            /* after this we're ready to start recording again */
 
498
                job->state |= VC_READY;
 
499
            } else {
 
500
                job->movie_no += 1;
 
501
                job->pic_no = job->start_no;
 
502
                job->state &= ~VC_STOP;
 
503
                job->state |= VC_START;
 
504
                job->state |= VC_REC;
 
505
                XVC_StartCapture(job);
 
506
                return;
 
507
            }
 
508
 
 
509
            if ( job->flags & FLG_NOGUI ) {
 
510
                XCloseDisplay(dpy);
 
511
                exit(0);
 
512
            }
 
513
            
 
514
    }
 
515
    
 
516
    return FALSE;
 
517
}
 
518
 
 
519
 
 
520
#ifdef HAVE_SHMAT
 
521
/*
 
522
 * timer callback for capturing with shared memory
 
523
 */
 
524
Boolean
 
525
TCbCaptureSHM(XtPointer xtp, XtIntervalId *id) {
 
526
    Job *job = (Job *) xtp;
 
527
    static char file[PATH_MAX+1];
 
528
    static XImage *image = NULL;
 
529
    static XShmSegmentInfo shminfo;
 
530
    static void *fp = NULL;
 
531
    Visual *visual = job->win_attr.visual;
 
532
    unsigned int depth = job->win_attr.depth;
 
533
    long time, time1;
 
534
    struct timeval curr_time;
 
535
    static Display *dpy;
 
536
    Screen *scr;
 
537
    
 
538
    #ifdef DEBUG2
 
539
    printf("TCbCaptureSHM() pic_no=%d flags=%d state=%i\n", job->pic_no, job->flags, job->state);
 
540
    printf("VC_REC %i - VC_STOP %i\n", ( job->state & VC_REC ), (job->state & VC_STOP ) );
 
541
    #endif
 
542
    if ((job->state & VC_PAUSE) && !(job->state & VC_STEP)) {
 
543
        XVC_AddTimeout(job->time_per_frame, job->capture, job);
 
544
        
 
545
    } else if (job->state & VC_REC) {
 
546
        // trace mouse pointer ...
 
547
        int x, y;
 
548
        
 
549
        if (job->max_frames && (
 
550
        (job->pic_no - job->start_no )> job->max_frames - 1)) {
 
551
            if (job->flags & FLG_RUN_VERBOSE)
 
552
                printf("Stopped! pic_no=%d max_frames=%d\n",
 
553
                job->pic_no, job->max_frames);
 
554
            if (!(job->flags & FLG_RUN_VERBOSE))
 
555
                XVC_ChangeGUILabel(job->pic_no);
 
556
 
 
557
            if (job->flags & FLG_AUTO_CONTINUE) job->state |= VC_CONTINUE;
 
558
            goto CLEAN_SHM;
 
559
        }
 
560
        job->state &= ~VC_STEP;
 
561
        gettimeofday(&curr_time, NULL);
 
562
        time = curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000;
 
563
        
 
564
        if ((!(job->flags & FLG_MULTI_IMAGE)) ||
 
565
        ((job->flags & FLG_MULTI_IMAGE) && (job->state & VC_START))) {
 
566
            
 
567
            if (job->flags & FLG_MULTI_IMAGE)
 
568
                sprintf(file, job->file, job->movie_no);
 
569
            else
 
570
                sprintf(file, job->file, job->pic_no);
 
571
            fp = (*job->open)(file, job->open_flags);
 
572
            if (!fp) {
 
573
                perror(file);
 
574
                job->state = VC_STOP;
 
575
                return;
 
576
            }
 
577
        }
 
578
        if (job->state & VC_START) {
 
579
            /*
 
580
             * the first time this procedure is called so
 
581
             * we must create a new ximage ..
 
582
             */
 
583
            if ( ! (job->flags & FLG_NOGUI ) ) {
 
584
                scr = job->win_attr.screen;
 
585
                dpy = DisplayOfScreen(scr);
 
586
            } else {
 
587
                dpy = XOpenDisplay(NULL);
 
588
                scr = DefaultScreenOfDisplay(dpy);
 
589
            }
 
590
            
 
591
            if (job->mouseWanted > 0) {
 
592
                getCurrentPointer(&x, &y, job);
 
593
            }
 
594
            
 
595
            image = XShmCreateImage(dpy, visual, depth, ZPixmap, NULL,
 
596
            &shminfo, job->area->width, job->area->height);
 
597
            if (!image) {
 
598
                printf("Can't get image: %dx%d+%d+%d\n", job->area->width,
 
599
                job->area->height, job->area->x, job->area->y);
 
600
                job->state = VC_STOP;
 
601
                //                CbStop(NULL, NULL, NULL);
 
602
                return;
 
603
            }
 
604
            shminfo.shmid = shmget(IPC_PRIVATE,
 
605
            image->bytes_per_line * image->height, IPC_CREAT|0777);
 
606
            if (shminfo.shmid == -1) {
 
607
                printf("Fatal: Can't get shared memory!\n");
 
608
                exit(1);
 
609
            }
 
610
            shminfo.shmaddr = image->data = shmat(shminfo.shmid, 0, 0);
 
611
            shminfo.readOnly = False;
 
612
            
 
613
            if (XShmAttach(dpy, &shminfo) == 0) {
 
614
                printf("Fatal: Failed to attach shared memory!\n");
 
615
                /* needs some better error subroutine :) */
 
616
                exit(1);
 
617
            }
 
618
            
 
619
            if (job->mouseWanted > 0) {
 
620
                paintMousePointer(&x, &y, job, image);
 
621
            }
 
622
            
 
623
        }
 
624
        /* just read new data in the image structure
 
625
         */
 
626
        if (job->mouseWanted) {
 
627
            getCurrentPointer(&x, &y, job);
 
628
        }
 
629
        
 
630
        if (XShmGetImage(dpy,
 
631
        RootWindow(dpy, DefaultScreen(dpy)),
 
632
        image, job->area->x, job->area->y, AllPlanes)) {
 
633
            if (job->mouseWanted) {
 
634
                paintMousePointer(&x, &y, job, image);
 
635
            }
 
636
            
 
637
            (*job->save) (fp, image, job);
 
638
            job->state &= ~VC_START;
 
639
        } else {
 
640
            printf("XShmGetImage() returned 'False'!\n");
 
641
        }
 
642
        if (!(job->flags & FLG_MULTI_IMAGE))
 
643
            (*job->close) (fp);
 
644
        else if (job->flags & FLG_SYNC) {
 
645
            if (job->open == (void *(*)(char *, char*))fopen)
 
646
                fdatasync(fileno(fp));
 
647
        }
 
648
        
 
649
        /* substract the time we needed for creating and saving
 
650
         * the frame to the file
 
651
         */
 
652
        gettimeofday(&curr_time, NULL);
 
653
        time1 = (curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000) - time;
 
654
        // update monitor widget, here time is the time the capture took
 
655
        // time == 0 resets led_meter
 
656
        if (! time1) time1 = 1;
 
657
        XVC_FrameMonitor(job, time1);
 
658
//      printf("time: %i time_per_frame: %i\n", time1, job->time_per_frame);
 
659
        // calculate the remaining time we have till capture of next frame
 
660
        time1 = job->time_per_frame - time1;
 
661
        
 
662
        if ( time1 > 0 ) {
 
663
            // get time again because updating frame drop meter took some time
 
664
            gettimeofday(&curr_time, NULL);
 
665
            time = (curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000) - time;
 
666
            time = job->time_per_frame - time;
 
667
        } else {
 
668
            time = time1;
 
669
        }
 
670
        if (time < 0) {
 
671
            if (job->flags & FLG_RUN_VERBOSE)
 
672
                printf("missing %ld milli secs (%d needed per frame), pic no %d\n",
 
673
                time, job->time_per_frame, job->pic_no);
 
674
        }
 
675
        if ( time < 2 ) time = 2;
 
676
 
 
677
        XVC_AddTimeout(time, job->capture, job);
 
678
 
 
679
        job->pic_no += job->step;
 
680
        if (time >= 2 )
 
681
            XVC_ChangeGUILabel(job->pic_no);
 
682
 
 
683
    } else {
 
684
        int orig_state;
 
685
 
 
686
        /* clean up */
 
687
        CLEAN_SHM:
 
688
            orig_state = job->state; // store state here
 
689
 
 
690
            // maybe the last update didn't succeed
 
691
            XVC_ChangeGUILabel(job->pic_no);
 
692
            XVC_FrameMonitor(job, 0);
 
693
            
 
694
            job->state = VC_STOP;
 
695
            if (image) {
 
696
                XShmDetach(dpy, &shminfo);
 
697
                image->data = NULL;
 
698
                XDestroyImage(image);
 
699
                image = NULL;
 
700
                shmdt(shminfo.shmaddr);
 
701
                shmctl(shminfo.shmid, IPC_RMID, 0);
 
702
            }
 
703
 
 
704
            /* set the sensitive stuff for the control panel
 
705
             * if we don't autocontinue */
 
706
            if ((orig_state & VC_CONTINUE) == 0) 
 
707
                XVC_StopCapture(job);
 
708
            
 
709
            if (job->clean) {
 
710
                (*job->clean) (job);
 
711
            }
 
712
            if (job->flags & FLG_MULTI_IMAGE)
 
713
                if (fp)
 
714
                    (*job->close) (fp);
 
715
            fp = NULL;
 
716
            
 
717
            if ((orig_state & VC_CONTINUE) == 0) {
 
718
            /* after this we're ready to start recording again */
 
719
                job->state |= VC_READY;
 
720
            } else {
 
721
                job->movie_no += 1;
 
722
                job->pic_no = job->start_no;
 
723
                job->state &= ~VC_STOP;
 
724
                job->state |= VC_START;
 
725
                job->state |= VC_REC;
 
726
                XVC_StartCapture(job);
 
727
                return;
 
728
            }
 
729
             
 
730
            if ( job->flags & FLG_NOGUI ) {
 
731
                XCloseDisplay(dpy);
 
732
                exit(0);
 
733
            }
 
734
            
 
735
    }
 
736
    
 
737
    return FALSE;
 
738
}
 
739
 
 
740
#endif /* HAVE_SHMAT */
 
741
 
 
742
#ifdef HasVideo4Linux
 
743
/*
 
744
 * timer callback for capturing direct from bttv driver (only linux)
 
745
 */
 
746
#ifndef linux
 
747
#error only for linux
 
748
#endif
 
749
/* from bttv.h */
 
750
 
 
751
Boolean
 
752
TCbCaptureV4L(XtPointer xtp, XtIntervalId id *) {
 
753
    Job *job = (Job *) xtp;
 
754
    static char file[PATH_MAX+1];
 
755
    static XImage *image = NULL;
 
756
    static void *fp = NULL;
 
757
    static VIDEO *video = 0;
 
758
    static int size;
 
759
    static struct video_mmap    vi_mmap;
 
760
    static struct video_mbuf    vi_memb;
 
761
    static struct video_picture vi_pict;
 
762
    long time, time1;
 
763
    struct timeval curr_time;
 
764
    Display *dpy;
 
765
    Screen *scr;
 
766
    
 
767
    if ( ! (job->flags & FLG_NOGUI ) ) {
 
768
        scr = job->win_attr.screen;
 
769
        dpy = DisplayOfScreen(scr);
 
770
    } else {
 
771
        dpy = XOpenDisplay(NULL);
 
772
    }
 
773
    
 
774
    #ifdef DEBUG2
 
775
    printf("TCbCaptureV4L() pic_no=%d\n", job->pic_no);
 
776
    #endif
 
777
    if ((job->state & VC_PAUSE) && !(job->state & VC_STEP)) {
 
778
        XVC_AddTimeout(job->time_per_frame, job->capture, job);
 
779
        
 
780
    } else if (job->state & VC_REC) {
 
781
        if (job->max_frames && (
 
782
        (job->pic_no - job->start_no )> job->max_frames - 1)) {
 
783
            if (job->flags & FLG_RUN_VERBOSE)
 
784
                printf("Stopped! pic_no=%d max_frames=%d\n",
 
785
                job->pic_no, job->max_frames);
 
786
            if (!(job->flags & FLG_RUN_VERBOSE))
 
787
                XVC_ChangeGUILabel(job->pic_no);
 
788
            
 
789
            if (job->flags & FLG_AUTO_CONTINUE) job->state |= VC_CONTINUE;
 
790
            goto CLEAN_V4L;
 
791
        }
 
792
        job->state &= ~VC_STEP;
 
793
        gettimeofday(&curr_time, NULL);
 
794
        time = curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000;
 
795
        
 
796
        if ((!(job->flags & FLG_MULTI_IMAGE)) ||
 
797
        ((job->flags & FLG_MULTI_IMAGE) && (job->state & VC_START))) {
 
798
            if (job->flags & FLG_MULTI_IMAGE)
 
799
                sprintf(file, job->file, job->movie_no);
 
800
            else
 
801
                sprintf(file, job->file, job->pic_no);
 
802
            fp = (*job->open)(file, job->open_flags);
 
803
            if (!fp) {
 
804
                perror(file);
 
805
                job->state = VC_STOP;
 
806
                return;
 
807
            }
 
808
        }
 
809
        if (job->state & VC_START) {
 
810
            /*
 
811
             * the first time this procedure is started
 
812
             * we must prepare some stuff ..
 
813
             */
 
814
            if (!job->bpp) /* use depth of the default window */
 
815
                job->bpp = job->win_attr.depth;
 
816
            
 
817
            sync(); /* remove if your bttv driver runs stable .. */
 
818
            video = video_open(job->video_dev, O_RDWR);
 
819
            if (!video) {
 
820
                perror(job->video_dev);
 
821
                goto CLEAN_V4L;
 
822
            }
 
823
            vi_pict.depth = 0;
 
824
            /* read default values for hue, etc.. */
 
825
            ioctl(video->fd, VIDIOCGPICT, &vi_pict);
 
826
            
 
827
            printf("%d->%d %d\n", job->bpp, vi_pict.depth, vi_pict.palette);
 
828
            switch (job->bpp) {
 
829
                case 24:
 
830
                    vi_mmap.format = vi_pict.palette = VIDEO_PALETTE_RGB24;
 
831
                    break;
 
832
                case 16:
 
833
                    vi_mmap.format = vi_pict.palette = VIDEO_PALETTE_RGB565;
 
834
                    break;
 
835
                case 15:
 
836
                    vi_mmap.format = vi_pict.palette = VIDEO_PALETTE_RGB555;
 
837
                    break;
 
838
                default:
 
839
                    printf("Fatal: unsupported bpp (%d)\n", job->bpp);
 
840
                    exit(3);
 
841
                    break;
 
842
            }
 
843
            ioctl(video->fd, VIDIOCSPICT, &vi_pict);
 
844
            printf("%d->%d %d\n", job->bpp, vi_pict.depth, vi_pict.palette);
 
845
            
 
846
            
 
847
            vi_memb.size = 0;
 
848
            ioctl(video->fd, VIDIOCGMBUF, &vi_memb);
 
849
            printf("%d %d %d\n", vi_memb.size, vi_memb.frames, vi_memb.offsets);
 
850
            
 
851
            image = (XImage *)XtMalloc(sizeof(XImage));
 
852
            if (!image) {
 
853
                printf("Can't get image: %dx%d+%d+%d\n", job->area->width,
 
854
                job->area->height, job->area->x, job->area->y);
 
855
                goto CLEAN_V4L;
 
856
            }
 
857
            switch (job->bpp) {
 
858
                case 24:
 
859
                    image->red_mask = 0xFF0000;
 
860
                    image->green_mask = 0x00FF00;
 
861
                    image->blue_mask = 0x0000FF;
 
862
                    break;
 
863
                case 16:
 
864
                    image->red_mask = 0x00F800;
 
865
                    image->green_mask = 0x0007E0;
 
866
                    image->blue_mask = 0x00001F;
 
867
                    break;
 
868
                case 15:
 
869
                    image->red_mask = 0x00F800;
 
870
                    image->green_mask = 0x0007E0;
 
871
                    image->blue_mask = 0x00001F;
 
872
                    break;
 
873
                default:
 
874
                    printf("Fatal: unsupported bpp (%d)\n", job->bpp);
 
875
                    exit(3);
 
876
                    break;
 
877
            }
 
878
            image->width = job->area->width;
 
879
            image->height= job->area->height;
 
880
            image->bits_per_pixel = job->bpp;
 
881
            image->bytes_per_line = job->bpp/8 * image->width;
 
882
            image->byte_order = MSBFirst;
 
883
            size = image->width * image->height * job->bpp;
 
884
            video->size = vi_memb.size;
 
885
            video_mmap(video, 1);
 
886
            if (video->mmap == NULL) {
 
887
                perror("mmap()");
 
888
                goto CLEAN_V4L;
 
889
            }
 
890
            
 
891
            vi_mmap.width = image->width;
 
892
            vi_mmap.height= image->height;
 
893
            vi_mmap.frame = 0;
 
894
            image->data = video->mmap;
 
895
        }
 
896
        /* just read new data in the image structure
 
897
         */
 
898
        if (ioctl(video->fd, VIDIOCMCAPTURE, &vi_mmap) < 0) {
 
899
            perror("ioctl(capture)");
 
900
            /* if (vb.frame) vb.frame = 0; else vb.frame = 1; */
 
901
            goto CLEAN_V4L;
 
902
        }
 
903
        printf("syncing ..\n");
 
904
        if (ioctl(video->fd, VIDIOCSYNC, vi_mmap.frame) < 0) {
 
905
            perror("ioctl(sync)");
 
906
        }
 
907
        printf("synced()\n");
 
908
        
 
909
        (*job->save) (fp, image, job);
 
910
        job->state &= ~VC_START;
 
911
        
 
912
        if (!(job->flags & FLG_MULTI_IMAGE))
 
913
            (*job->close) (fp);
 
914
        
 
915
        /* substract the time we needed for creating and saving
 
916
         * the frame to the file
 
917
         */
 
918
        gettimeofday(&curr_time, NULL);
 
919
        time1 = (curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000) - time;
 
920
        // update monitor widget, here time is the time the capture took
 
921
        // time == 0 resets led_meter
 
922
        if (! time1) time1 = 1;
 
923
        XVC_FrameMonitor(job, time1);
 
924
//      printf("time: %i time_per_frame: %i\n", time1, job->time_per_frame);
 
925
        // calculate the remaining time we have till capture of next frame
 
926
        time1 = job->time_per_frame - time1;
 
927
        
 
928
        if ( time1 > 0 ) {
 
929
            // get time again because updating frame drop meter took some time
 
930
            gettimeofday(&curr_time, NULL);
 
931
            time = (curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000) - time;
 
932
            time = job->time_per_frame - time;
 
933
        } else {
 
934
            time = time1;
 
935
        }
 
936
        if (time < 0) {
 
937
            if (job->flags & FLG_RUN_VERBOSE)
 
938
                printf("missing %ld milli secs (%d needed per frame), pic no %d\n",
 
939
                time, job->time_per_frame, job->pic_no);
 
940
        }
 
941
        if ( time < 2 ) time = 2;
 
942
 
 
943
        XVC_AddTimeout(time, job->capture, job);
 
944
 
 
945
        job->pic_no += job->step;
 
946
        if (time >= 2 )
 
947
            XVC_ChangeGUILabel(job->pic_no);
 
948
 
 
949
    } else {
 
950
        int orig_state;
 
951
 
 
952
        /* clean up */
 
953
        CLEAN_V4L:
 
954
            orig_state = job->state; // store state here
 
955
 
 
956
            // maybe the last update didn't succeed
 
957
            XVC_ChangeGUILabel(job->pic_no);
 
958
            XVC_FrameMonitor(job, 0);
 
959
            
 
960
            job->state = VC_STOP;
 
961
            if (image) {
 
962
                XtFree((char*)image);
 
963
                image = NULL;
 
964
            }
 
965
            if (video) {
 
966
                video_mmap(video, 0);
 
967
                video_close(video);
 
968
                video = NULL;
 
969
            }
 
970
 
 
971
            /* set the sensitive stuff for the control panel
 
972
             * if we don't autocontinue */
 
973
            if ((orig_state & VC_CONTINUE) == 0) 
 
974
                XVC_StopCapture(job);
 
975
            
 
976
            /* clean up the save routines in xtoXXX.c
 
977
             */
 
978
            if (job->clean)
 
979
                (*job->clean) (job);
 
980
            if (job->flags & FLG_MULTI_IMAGE)
 
981
                if (fp)
 
982
                    (*job->close) (fp);
 
983
            fp = NULL;
 
984
 
 
985
            if ((orig_state & VC_CONTINUE) == 0) {
 
986
            /* after this we're ready to start recording again */
 
987
                job->state |= VC_READY;
 
988
            } else {
 
989
                job->movie_no += 1;
 
990
                job->pic_no = job->start_no;
 
991
                job->state &= ~VC_STOP;
 
992
                job->state |= VC_START;
 
993
                job->state |= VC_REC;
 
994
                XVC_StartCapture(job);
 
995
                return;
 
996
            }
 
997
            
 
998
    }
 
999
 
 
1000
    /* after this we're ready to start recording again */
 
1001
    job->state |= VC_READY;
 
1002
             
 
1003
    if ( job->flags & FLG_NOGUI && ( ! is_filename_mutable(job->file) ) ) {
 
1004
        XCloseDisplay(dpy);
 
1005
    }
 
1006
    
 
1007
    return FALSE;
 
1008
}
 
1009
#endif /* HasVideo4Linux */
 
1010
 
 
1011
#ifdef HasDGA
 
1012
/*
 
1013
 * direct graphic access
 
1014
 * this doesn't work until now and may be removed in future..!?
 
1015
 *
 
1016
 * IT HAS ALSO NOT BEEN REWRITTEN FOR GTK GUI SUPPORT
 
1017
 */
 
1018
Boolean
 
1019
TCbCaptureDGA(XtPointer xtp, XtIntervalId id *) {
 
1020
    Job *job = (Job *) xtp;
 
1021
    static char file[PATH_MAX+1];
 
1022
    static XImage *image = NULL;
 
1023
    static void *fp;
 
1024
    static int size;
 
1025
    static Display *dpy;
 
1026
    long time;
 
1027
    struct timeval curr_time;
 
1028
    
 
1029
    #ifdef DEBUG2
 
1030
    printf("TCbCaptureDGA() pic_no=%d state=%d\n", job->pic_no, job->state);
 
1031
    #endif
 
1032
    if ((job->state & VC_PAUSE) && !(job->state & VC_STEP)) {
 
1033
        XtAppAddTimeOut(XtWidgetToApplicationContext(job->toplevel),
 
1034
        job->time_per_frame, (XtTimerCallbackProc)job->capture, job);
 
1035
        
 
1036
    } else if (job->state & VC_REC) {
 
1037
        if (job->max_frames && (
 
1038
        (job->pic_no - job->start_no )> job->max_frames - 1)) {
 
1039
            if (job->flags & FLG_RUN_VERBOSE)
 
1040
                printf("Stopped! pic_no=%d max_frames=%d\n",
 
1041
                job->pic_no, job->max_frames);
 
1042
            if (!(job->flags & FLG_RUN_VERBOSE))
 
1043
                ChangeLabel(job->pic_no);
 
1044
            goto CLEAN_DGA;
 
1045
        }
 
1046
        job->state &= ~VC_STEP;
 
1047
        gettimeofday(&curr_time, NULL);
 
1048
        time = curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000;
 
1049
        
 
1050
        if ((!(job->flags & FLG_MULTI_IMAGE)) ||
 
1051
        ((job->flags & FLG_MULTI_IMAGE) && (job->state & VC_START))) {
 
1052
            if (job->flags & FLG_MULTI_IMAGE)
 
1053
                sprintf(file, job->file, job->movie_no);
 
1054
            else
 
1055
                sprintf(file, job->file, job->pic_no);
 
1056
            fp = (*job->open)(file, job->open_flags);
 
1057
            if (!fp) {
 
1058
                perror(file);
 
1059
                job->state = VC_STOP;
 
1060
                return;
 
1061
            }
 
1062
        }
 
1063
        if (job->state & VC_START) {
 
1064
            /*
 
1065
             * the first time this procedure is started
 
1066
             * we must create a new image structure ..
 
1067
             */
 
1068
            dpy = XtDisplay(job->toplevel);
 
1069
            image = (XImage *)XtMalloc(sizeof(XImage));
 
1070
            if (!image) {
 
1071
                printf("Can't get image: %dx%d+%d+%d\n", job->area->width,
 
1072
                job->area->height, job->area->x, job->area->y);
 
1073
                goto CLEAN_DGA;
 
1074
            }
 
1075
            image->width = job->area->width;
 
1076
            image->height= job->area->height;
 
1077
            image->bits_per_pixel = 3 * 8;
 
1078
            image->bytes_per_line = 3 * image->width;
 
1079
            image->byte_order = MSBFirst;
 
1080
            size = image->width * image->height;
 
1081
            { int width, bank, ram;
 
1082
              char *base;
 
1083
              XF86DGAGetVideo(dpy, XDefaultScreen(dpy), (char **) &base,
 
1084
              &width, &bank, &ram);
 
1085
              image->data = base;
 
1086
            }
 
1087
            XF86DGADirectVideo(dpy, XDefaultScreen(dpy), XF86DGADirectGraphics);
 
1088
            (*job->save) (fp, image, job);
 
1089
            XF86DGADirectVideo(dpy, XDefaultScreen(dpy), 0);
 
1090
            job->state &= ~VC_START;
 
1091
        } else {
 
1092
            /* just read new data in the image structure
 
1093
             */
 
1094
            XF86DGADirectVideo(dpy, XDefaultScreen(dpy), XF86DGADirectGraphics);
 
1095
            (*job->save) (fp, image, job);
 
1096
            XF86DGADirectVideo(dpy, XDefaultScreen(dpy), 0);
 
1097
        }
 
1098
        if (!(job->flags & FLG_MULTI_IMAGE))
 
1099
            (*job->close) (fp);
 
1100
        
 
1101
        /* substract the time we needed for creating and saving
 
1102
         * the frame to the file
 
1103
         */
 
1104
        gettimeofday(&curr_time, NULL);
 
1105
        time = (curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000) - time;
 
1106
        time = job->time_per_frame - time;
 
1107
        if (time < 0) {
 
1108
            if (job->flags & FLG_RUN_VERBOSE)
 
1109
                printf("missing %ld milli secs (%d needed per frame), pic no %d\n",
 
1110
                time, job->time_per_frame, job->pic_no);
 
1111
            time = 0;
 
1112
        }
 
1113
        XtAppAddTimeOut(XtWidgetToApplicationContext(job->toplevel),
 
1114
        time, (XtTimerCallbackProc)job->capture, job);
 
1115
        job->pic_no += job->step;
 
1116
        /* update the label if we have time to do this */
 
1117
        if (time)
 
1118
            ChangeLabel(job->pic_no);
 
1119
    } else {
 
1120
        /* clean up */
 
1121
        CLEAN_DGA:
 
1122
            /* may be the last update failed .. so do it here before stop
 
1123
             */
 
1124
            ChangeLabel(job->pic_no);
 
1125
            job->state = VC_STOP;
 
1126
            if (image) {
 
1127
                XtFree((char*)image);
 
1128
                image = NULL;
 
1129
            }
 
1130
            XF86DGADirectVideo(dpy, XDefaultScreen(dpy), 0);
 
1131
            /* set the sensitive stuff for the control panel
 
1132
             */
 
1133
            CbStop(NULL, NULL, NULL);
 
1134
            
 
1135
            /* clean up the save routines in xtoXXX.c
 
1136
             */
 
1137
            if (job->clean)
 
1138
                (*job->clean) (job);
 
1139
            if (job->flags & FLG_MULTI_IMAGE)
 
1140
                if (fp)
 
1141
                    (*job->close) (fp);
 
1142
            fp = NULL;
 
1143
            
 
1144
            return FALSE;
 
1145
    }
 
1146
    return TRUE;
 
1147
}
 
1148
#endif /* HasDGA */