author | mickeyl <mickeyl> | 2003-04-20 17:36:20 (UTC) |
---|---|---|
committer | mickeyl <mickeyl> | 2003-04-20 17:36:20 (UTC) |
commit | 606f5d9cd2ecba4df175bc722621e4e4df3bc516 (patch) (unidiff) | |
tree | f9da7a8bdbac0e576014fc1ca7fa5f6a2066b67a | |
parent | c02c43c91251e8d71048b27855fc1900e430272d (diff) | |
download | opie-606f5d9cd2ecba4df175bc722621e4e4df3bc516.zip opie-606f5d9cd2ecba4df175bc722621e4e4df3bc516.tar.gz opie-606f5d9cd2ecba4df175bc722621e4e4df3bc516.tar.bz2 |
too much work for that damn video feature... some progress, but it's still not right
-rw-r--r-- | noncore/multimedia/camera/avi.c | 235 | ||||
-rw-r--r-- | noncore/multimedia/camera/avi.h | 142 | ||||
-rw-r--r-- | noncore/multimedia/camera/camera.pro | 6 | ||||
-rw-r--r-- | noncore/multimedia/camera/mainwindow.cpp | 162 | ||||
-rw-r--r-- | noncore/multimedia/camera/mainwindow.h | 9 | ||||
-rw-r--r-- | noncore/multimedia/camera/zcameraio.cpp | 11 |
6 files changed, 530 insertions, 35 deletions
diff --git a/noncore/multimedia/camera/avi.c b/noncore/multimedia/camera/avi.c new file mode 100644 index 0000000..0c757c9 --- a/dev/null +++ b/noncore/multimedia/camera/avi.c | |||
@@ -0,0 +1,235 @@ | |||
1 | /********************************************************************** | ||
2 | ** Copyright (C) 2003 Michael 'Mickey' Lauer. All rights reserved. | ||
3 | ** Based on work from Andrew Tridgell and the jpegtoavi project | ||
4 | ** | ||
5 | ** This file is part of Opie Environment. | ||
6 | ** | ||
7 | ** This file may be distributed and/or modified under the terms of the | ||
8 | ** GNU General Public License version 2 as published by the Free Software | ||
9 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
10 | ** packaging of this file. | ||
11 | ** | ||
12 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | ||
13 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
14 | ** | ||
15 | **********************************************************************/ | ||
16 | |||
17 | #include "avi.h" | ||
18 | |||
19 | #include <string.h> | ||
20 | #include <stdio.h> | ||
21 | |||
22 | int nframes; | ||
23 | int totalsize; | ||
24 | unsigned int* sizes; | ||
25 | |||
26 | void fprint_quartet(int fd, unsigned int i) | ||
27 | { | ||
28 | char data[4]; | ||
29 | |||
30 | data[0] = (char) i%0x100; | ||
31 | i /= 0x100; | ||
32 | data[1] = (char) i%0x100; | ||
33 | i /= 0x100; | ||
34 | data[2] = (char) i%0x100; | ||
35 | i /= 0x100; | ||
36 | data[3] = (char) i%0x100; | ||
37 | |||
38 | write( fd, &data, 4 ); | ||
39 | } | ||
40 | |||
41 | // start writing an AVI file | ||
42 | |||
43 | void avi_start(int fd, int frames) | ||
44 | { | ||
45 | int ofs = sizeof(struct riff_head)+ | ||
46 | sizeof(struct list_head)+ | ||
47 | sizeof(struct avi_head)+ | ||
48 | sizeof(struct list_head)+ | ||
49 | sizeof(struct stream_head)+ | ||
50 | sizeof(struct frame_head)+ | ||
51 | sizeof(struct list_head)+ | ||
52 | sizeof(struct dmlh_head)+ | ||
53 | sizeof(struct list_head); | ||
54 | |||
55 | printf( "avi_start: frames = %d\n", frames ); | ||
56 | |||
57 | lseek(fd, ofs, SEEK_SET); | ||
58 | |||
59 | nframes = 0; | ||
60 | totalsize = 0; | ||
61 | |||
62 | sizes = (unsigned int*) calloc( sizeof(unsigned int), frames ); // hold size of each frame | ||
63 | } | ||
64 | |||
65 | // add a jpeg frame to an AVI file | ||
66 | void avi_add(int fd, u8 *buf, int size) | ||
67 | { | ||
68 | struct db_head db = {"00db", 0}; | ||
69 | |||
70 | printf( "avi_add: nframes = %d, totalsize = %d, size = %d\n", nframes, totalsize, size ); | ||
71 | |||
72 | // overwrite JFIF type with AVI1 | ||
73 | buf[6]='A'; | ||
74 | buf[7]='V'; | ||
75 | buf[8]='I'; | ||
76 | buf[9]='1'; | ||
77 | |||
78 | while( size%4 ) size++; // align 0 modulo 4*/ | ||
79 | db.size = size; | ||
80 | |||
81 | write( fd, &db, sizeof(db) ); | ||
82 | write( fd, buf, size ); | ||
83 | |||
84 | sizes[nframes] = size; | ||
85 | |||
86 | nframes++; | ||
87 | totalsize += size; // total frame size | ||
88 | } | ||
89 | |||
90 | // finish writing the AVI file - filling in the header | ||
91 | void avi_end(int fd, int width, int height, int fps) | ||
92 | { | ||
93 | struct idx1_head idx = {"idx1", 16*nframes }; | ||
94 | struct db_head db = {"00db", 0}; | ||
95 | struct riff_head rh = { "RIFF", 0, "AVI "}; | ||
96 | struct list_head lh1 = {"LIST", 0, "hdrl"}; | ||
97 | struct avi_head ah; | ||
98 | struct list_head lh2 = {"LIST", 0, "strl"}; | ||
99 | struct stream_head sh; | ||
100 | struct frame_head fh; | ||
101 | struct list_head lh3 = {"LIST", 0, "odml" }; | ||
102 | struct dmlh_head dh = {"dmlh", 4, nframes }; | ||
103 | struct list_head lh4 = {"LIST", 0, "movi"}; | ||
104 | int i; | ||
105 | unsigned int offset = 4; | ||
106 | |||
107 | printf( "avi_end: nframes = %d, fps = %d\n", nframes, fps ); | ||
108 | |||
109 | // write index | ||
110 | |||
111 | write(fd, &idx, sizeof(idx)); | ||
112 | |||
113 | for ( i = 0; i < nframes; i++ ) | ||
114 | { | ||
115 | write(fd, &db, 4 ); // only need the 00db | ||
116 | fprint_quartet( fd, 18 ); // ??? | ||
117 | fprint_quartet( fd, offset ); | ||
118 | fprint_quartet( fd, sizes[i] ); | ||
119 | offset += sizes[i]; | ||
120 | } | ||
121 | |||
122 | free( sizes ); | ||
123 | |||
124 | bzero( &ah, sizeof(ah) ); | ||
125 | strcpy(ah.avih, "avih"); | ||
126 | ah.time = 1000000 / fps; | ||
127 | ah.maxbytespersec = 1000000.0*(totalsize/nframes)/ah.time; | ||
128 | ah.numstreams = 1; | ||
129 | ah.flags = AVIF_HASINDEX; | ||
130 | ah.width = width; | ||
131 | ah.height = height; | ||
132 | |||
133 | bzero(&sh, sizeof(sh)); | ||
134 | strcpy(sh.strh, "strh"); | ||
135 | strcpy(sh.vids, "vids"); | ||
136 | strcpy(sh.codec, "MJPG"); | ||
137 | sh.scale = ah.time; | ||
138 | sh.rate = 1000000; | ||
139 | sh.length = nframes; | ||
140 | |||
141 | bzero(&fh, sizeof(fh)); | ||
142 | strcpy(fh.strf, "strf"); | ||
143 | fh.width = width; | ||
144 | fh.height = height; | ||
145 | fh.planes = 1; | ||
146 | fh.bitcount = 24; | ||
147 | strcpy(fh.codec,"MJPG"); | ||
148 | fh.unpackedsize = 3*width*height; | ||
149 | |||
150 | rh.size = sizeof(lh1)+sizeof(ah)+sizeof(lh2)+sizeof(sh)+ | ||
151 | sizeof(fh)+sizeof(lh3)+sizeof(dh)+sizeof(lh4)+ | ||
152 | nframes*sizeof(struct db_head)+ | ||
153 | totalsize + sizeof(struct idx1_head)+ (16*nframes) +4; // FIXME:16 bytes per nframe // the '4' - what for??? | ||
154 | |||
155 | lh1.size = 4+sizeof(ah)+sizeof(lh2)+sizeof(sh)+sizeof(fh)+sizeof(lh3)+sizeof(dh); | ||
156 | ah.size = sizeof(ah)-8; | ||
157 | lh2.size = 4+sizeof(sh)+sizeof(fh)+sizeof(lh3)+sizeof(dh); //4+sizeof(sh)+sizeof(fh); | ||
158 | sh.size = sizeof(sh)-8; | ||
159 | fh.size = sizeof(fh)-8; | ||
160 | fh.size2 = fh.size; | ||
161 | lh3.size = 4+sizeof(dh); | ||
162 | lh4.size = 4+ nframes*sizeof(struct db_head)+ totalsize; | ||
163 | |||
164 | lseek(fd, 0, SEEK_SET); | ||
165 | |||
166 | write(fd, &rh, sizeof(rh)); | ||
167 | write(fd, &lh1, sizeof(lh1)); | ||
168 | write(fd, &ah, sizeof(ah)); | ||
169 | write(fd, &lh2, sizeof(lh2)); | ||
170 | write(fd, &sh, sizeof(sh)); | ||
171 | write(fd, &fh, sizeof(fh)); | ||
172 | write(fd, &lh3, sizeof(lh3)); | ||
173 | write(fd, &dh, sizeof(dh)); | ||
174 | write(fd, &lh4, sizeof(lh4)); | ||
175 | } | ||
176 | |||
177 | |||
178 | /* NOTE: This is not a general purpose routine - it is meant to only | ||
179 | cope with AVIs saved using the other functions in this file | ||
180 | void avi_explode(char *fname) | ||
181 | { | ||
182 | struct riff_head rh; | ||
183 | struct list_head lh1; | ||
184 | struct avi_head ah; | ||
185 | struct list_head lh2; | ||
186 | struct stream_head sh; | ||
187 | struct frame_head fh; | ||
188 | struct list_head lh3; | ||
189 | int hsize, qsize; | ||
190 | u16 *htables = jpeg_huffman_tables(&hsize); | ||
191 | u16 *qtables = jpeg_quantisation_tables(&qsize, image_quality); | ||
192 | int fd, i; | ||
193 | |||
194 | fd = open(fname,O_RDONLY); | ||
195 | if (fd == -1) { | ||
196 | perror(fname); | ||
197 | return; | ||
198 | } | ||
199 | |||
200 | read(fd, &rh, sizeof(rh)); | ||
201 | read(fd, &lh1, sizeof(lh1)); | ||
202 | read(fd, &ah, sizeof(ah)); | ||
203 | read(fd, &lh2, sizeof(lh2)); | ||
204 | read(fd, &sh, sizeof(sh)); | ||
205 | read(fd, &fh, sizeof(fh)); | ||
206 | read(fd, &lh3, sizeof(lh3)); | ||
207 | |||
208 | for (i=0; ; i++) { | ||
209 | u8 buf[500*1024]; | ||
210 | struct db_head db; | ||
211 | char fname[100]; | ||
212 | int fd2; | ||
213 | |||
214 | if (read(fd, &db, sizeof(db)) != sizeof(db) || | ||
215 | read(fd, buf, db.size) != db.size) break; | ||
216 | |||
217 | snprintf(fname, sizeof(fname)-1,"frame.%d", i); | ||
218 | |||
219 | fd2 = open(fname,O_WRONLY|O_CREAT, 0644); | ||
220 | if (fd2 == -1) { | ||
221 | perror(fname); | ||
222 | continue; | ||
223 | } | ||
224 | write(fd2, buf, 2); | ||
225 | write(fd2, qtables, qsize); | ||
226 | write(fd2, htables, hsize); | ||
227 | write(fd2, buf+2, db.size-2); | ||
228 | close(fd2); | ||
229 | } | ||
230 | close(fd); | ||
231 | printf("exploded %d frames\n", i); | ||
232 | } | ||
233 | |||
234 | */ | ||
235 | |||
diff --git a/noncore/multimedia/camera/avi.h b/noncore/multimedia/camera/avi.h new file mode 100644 index 0000000..fbdc14a --- a/dev/null +++ b/noncore/multimedia/camera/avi.h | |||
@@ -0,0 +1,142 @@ | |||
1 | /********************************************************************** | ||
2 | ** Copyright (C) 2003 Michael 'Mickey' Lauer. All rights reserved. | ||
3 | ** Based on work from Andrew Tridgell and the jpegtoavi project | ||
4 | ** | ||
5 | ** This file is part of Opie Environment. | ||
6 | ** | ||
7 | ** This file may be distributed and/or modified under the terms of the | ||
8 | ** GNU General Public License version 2 as published by the Free Software | ||
9 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
10 | ** packaging of this file. | ||
11 | ** | ||
12 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | ||
13 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
14 | ** | ||
15 | **********************************************************************/ | ||
16 | |||
17 | #ifndef AVI_H | ||
18 | #define AVI_H | ||
19 | |||
20 | #include <unistd.h> | ||
21 | #include <stdio.h> | ||
22 | #include <sys/types.h> | ||
23 | |||
24 | #ifdef __cplusplus | ||
25 | extern "C" { | ||
26 | #endif | ||
27 | |||
28 | typedef unsigned char u8; | ||
29 | typedef unsigned short u16; | ||
30 | typedef unsigned u32; | ||
31 | |||
32 | // header flags | ||
33 | |||
34 | const u32 AVIF_HASINDEX=0x00000010; /* index at end of file */ | ||
35 | const u32 AVIF_MUSTUSEINDEX=0x00000020; | ||
36 | const u32 AVIF_ISINTERLEAVED=0x00000100; | ||
37 | const u32 AVIF_TRUSTCKTYPE=0x00000800; | ||
38 | const u32 AVIF_WASCAPTUREFILE=0x00010000; | ||
39 | const u32 AVIF_COPYRIGHTED=0x00020000; | ||
40 | |||
41 | // function prototypes | ||
42 | |||
43 | void avi_start(int fd, int frame); | ||
44 | void avi_add(int fd, u8 *buf, int size); | ||
45 | void avi_end(int fd, int width, int height, int fps); | ||
46 | void fprint_quartet(int fd, unsigned int i); | ||
47 | |||
48 | // the following structures are ordered as they appear in a typical AVI | ||
49 | |||
50 | struct riff_head { | ||
51 | char riff[4]; // chunk type = "RIFF" | ||
52 | u32 size; // chunk size | ||
53 | char avistr[4]; // avi magic = "AVI " | ||
54 | }; | ||
55 | |||
56 | // the avih chunk contains a number of list chunks | ||
57 | |||
58 | struct avi_head { | ||
59 | char avih[4]; // chunk type = "avih" | ||
60 | u32 size; // chunk size | ||
61 | u32 time; // microsec per frame == 1e6 / fps | ||
62 | u32 maxbytespersec; // = 1e6*(total size/frames)/per_usec) | ||
63 | u32 pad; // pad = 0 | ||
64 | u32 flags; // e.g. AVIF_HASINDEX | ||
65 | u32 nframes; // total number of frames | ||
66 | u32 initialframes; // = 0 | ||
67 | u32 numstreams; // = 1 for now (later = 2 because of audio) | ||
68 | u32 suggested_bufsize; // = 0 (no suggestion) | ||
69 | u32 width; // width | ||
70 | u32 height; // height | ||
71 | u32 reserved[4]; // reserved for future use = 0 | ||
72 | }; | ||
73 | |||
74 | |||
75 | // the LIST chunk contains a number (==#numstreams) of stream chunks | ||
76 | |||
77 | struct list_head { | ||
78 | char list[4]; // chunk type = "LIST" | ||
79 | u32 size; | ||
80 | char type[4]; | ||
81 | }; | ||
82 | |||
83 | |||
84 | struct dmlh_head { | ||
85 | char dmlh[4]; // chunk type dmlh | ||
86 | u32 size; // 4 | ||
87 | u32 nframes; // number of frames | ||
88 | }; | ||
89 | |||
90 | |||
91 | struct stream_head { | ||
92 | char strh[4]; // chunk type = "strh" | ||
93 | u32 size; // chunk size | ||
94 | char vids[4]; // stream type = "vids" | ||
95 | char codec[4]; // codec name (for us, = "MJPG") | ||
96 | u32 flags; // contains AVIT_F* flags | ||
97 | u16 priority; // = 0 | ||
98 | u16 language; // = 0 | ||
99 | u32 initialframes; // = 0 | ||
100 | u32 scale; // = usec per frame | ||
101 | u32 rate; // 1e6 | ||
102 | u32 start; // = 0 | ||
103 | u32 length; // number of frames | ||
104 | u32 suggested_bufsize; // = 0 | ||
105 | u32 quality; // = 0 ? | ||
106 | u32 samplesize; // = 0 ? | ||
107 | }; | ||
108 | |||
109 | |||
110 | struct db_head { | ||
111 | char db[4]; // "00db" | ||
112 | u32 size; | ||
113 | }; | ||
114 | |||
115 | // a frame chunk contains one JPEG image | ||
116 | |||
117 | struct frame_head { | ||
118 | char strf[4]; // chunk type = "strf" | ||
119 | u32 size; // sizeof chunk (big endian) ? | ||
120 | u32 size2; // sizeof chunk (little endian) ? | ||
121 | u32 width; | ||
122 | u32 height; | ||
123 | u16 planes; // 1 bitplane | ||
124 | u16 bitcount; // 24 bpl | ||
125 | char codec[4]; // MJPG (for us) | ||
126 | u32 unpackedsize; // = 3*w*h | ||
127 | u32 r1; // reserved | ||
128 | u32 r2; // reserved | ||
129 | u32 clr_used; // reserved | ||
130 | u32 clr_important; // reserved | ||
131 | }; | ||
132 | |||
133 | struct idx1_head { | ||
134 | char idx1[4]; // chunk type = "idx1" | ||
135 | u32 size; // chunk size | ||
136 | }; | ||
137 | |||
138 | #ifdef __cplusplus | ||
139 | } | ||
140 | #endif | ||
141 | |||
142 | #endif | ||
diff --git a/noncore/multimedia/camera/camera.pro b/noncore/multimedia/camera/camera.pro index 8aedcea..c0e6ca8 100644 --- a/noncore/multimedia/camera/camera.pro +++ b/noncore/multimedia/camera/camera.pro | |||
@@ -1,25 +1,27 @@ | |||
1 | MOC_DIR = ./moc | 1 | MOC_DIR = ./moc |
2 | OBJECTS_DIR = ./obj | 2 | OBJECTS_DIR = ./obj |
3 | DESTDIR = $(OPIEDIR)/bin | 3 | DESTDIR = $(OPIEDIR)/bin |
4 | TEMPLATE = app | 4 | TEMPLATE = app |
5 | CONFIG = qt warn_on debug | 5 | CONFIG = qt warn_on debug |
6 | 6 | ||
7 | HEADERS = imageio.h \ | 7 | HEADERS = avi.h \ |
8 | imageio.h \ | ||
8 | zcameraio.h \ | 9 | zcameraio.h \ |
9 | previewwidget.h \ | 10 | previewwidget.h \ |
10 | mainwindow.h | 11 | mainwindow.h |
11 | 12 | ||
12 | SOURCES = imageio.cpp \ | 13 | SOURCES = avi.c \ |
14 | imageio.cpp \ | ||
13 | zcameraio.cpp \ | 15 | zcameraio.cpp \ |
14 | previewwidget.cpp \ | 16 | previewwidget.cpp \ |
15 | mainwindow.cpp \ | 17 | mainwindow.cpp \ |
16 | main.cpp | 18 | main.cpp |
17 | 19 | ||
18 | INCLUDEPATH += $(OPIEDIR)/include | 20 | INCLUDEPATH += $(OPIEDIR)/include |
19 | DEPENDPATH += $(OPIEDIR)/include | 21 | DEPENDPATH += $(OPIEDIR)/include |
20 | LIBS += -lqpe -lopie -lopiecore2 | 22 | LIBS += -lqpe -lopie -lopiecore2 |
21 | INTERFACES = | 23 | INTERFACES = |
22 | TARGET = opiecam | 24 | TARGET = opiecam |
23 | 25 | ||
24 | include ( $(OPIEDIR)/include.pro ) | 26 | include ( $(OPIEDIR)/include.pro ) |
25 | 27 | ||
diff --git a/noncore/multimedia/camera/mainwindow.cpp b/noncore/multimedia/camera/mainwindow.cpp index 6141fd1..e27a50e 100644 --- a/noncore/multimedia/camera/mainwindow.cpp +++ b/noncore/multimedia/camera/mainwindow.cpp | |||
@@ -1,435 +1,551 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2002 Michael 'Mickey' Lauer. All rights reserved. | 2 | ** Copyright (C) 2002 Michael 'Mickey' Lauer. All rights reserved. |
3 | ** | 3 | ** |
4 | ** This file is part of Opie Environment. | 4 | ** This file is part of Opie Environment. |
5 | ** | 5 | ** |
6 | ** This file may be distributed and/or modified under the terms of the | 6 | ** This file may be distributed and/or modified under the terms of the |
7 | ** GNU General Public License version 2 as published by the Free Software | 7 | ** GNU General Public License version 2 as published by the Free Software |
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | 8 | ** Foundation and appearing in the file LICENSE.GPL included in the |
9 | ** packaging of this file. | 9 | ** packaging of this file. |
10 | ** | 10 | ** |
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
13 | ** | 13 | ** |
14 | **********************************************************************/ | 14 | **********************************************************************/ |
15 | 15 | ||
16 | #include "mainwindow.h" | 16 | #include "mainwindow.h" |
17 | #include "previewwidget.h" | 17 | #include "previewwidget.h" |
18 | #include "zcameraio.h" | 18 | #include "zcameraio.h" |
19 | #include "imageio.h" | 19 | #include "imageio.h" |
20 | #include "avi.h" | ||
20 | 21 | ||
21 | #include <qapplication.h> | 22 | #include <qapplication.h> |
22 | #include <qaction.h> | 23 | #include <qaction.h> |
23 | #include <qvbox.h> | 24 | #include <qvbox.h> |
24 | #include <qcombobox.h> | 25 | #include <qcombobox.h> |
25 | #include <qcursor.h> | 26 | #include <qcursor.h> |
26 | #include <qdatastream.h> | 27 | #include <qdatastream.h> |
27 | #include <qfile.h> | 28 | #include <qfile.h> |
28 | #include <qimage.h> | 29 | #include <qimage.h> |
29 | #include <qlabel.h> | 30 | #include <qlabel.h> |
30 | #include <qpopupmenu.h> | 31 | #include <qpopupmenu.h> |
31 | #include <qprogressbar.h> | 32 | #include <qprogressbar.h> |
32 | #include <qpushbutton.h> | 33 | #include <qpushbutton.h> |
33 | #include <qmessagebox.h> | 34 | #include <qmessagebox.h> |
34 | #include <qlayout.h> | 35 | #include <qlayout.h> |
35 | #include <qdirectpainter_qws.h> | 36 | #include <qdirectpainter_qws.h> |
36 | #include <qpe/global.h> | 37 | #include <qpe/global.h> |
37 | #include <qpe/resource.h> | 38 | #include <qpe/resource.h> |
38 | #include <qpe/qcopenvelope_qws.h> | 39 | #include <qpe/qcopenvelope_qws.h> |
39 | #include <opie/ofiledialog.h> | 40 | #include <opie/ofiledialog.h> |
40 | #include <opie/odevice.h> | 41 | #include <opie/odevice.h> |
41 | using namespace Opie; | 42 | using namespace Opie; |
42 | #include <opie2/odebug.h> | 43 | #include <opie2/odebug.h> |
43 | 44 | ||
44 | #include <assert.h> | 45 | #include <assert.h> |
45 | #include <sys/types.h> | 46 | #include <sys/types.h> |
46 | #include <sys/stat.h> | 47 | #include <sys/stat.h> |
47 | #include <fcntl.h> | 48 | #include <fcntl.h> |
48 | #include <string.h> | 49 | #include <string.h> |
49 | #include <errno.h> | 50 | #include <errno.h> |
50 | #include <unistd.h> | 51 | #include <unistd.h> |
51 | 52 | ||
52 | #define CAPTUREFILE "/tmp/capture.dat" | 53 | #define CAPTUREFILE "/tmp/capture.dat" |
54 | #define OUTPUTFILE "/tmp/output.avi" | ||
53 | 55 | ||
54 | CameraMainWindow::CameraMainWindow( QWidget * parent, const char * name, WFlags f ) | 56 | CameraMainWindow::CameraMainWindow( QWidget * parent, const char * name, WFlags f ) |
55 | :QMainWindow( parent, name, f ), _capturing( false ), _pics( 0 ) | 57 | :QMainWindow( parent, name, f ), |
58 | _rotation( 270 ), // FIXME: get this from current settings (ODevice?) | ||
59 | _capturing( false ), | ||
60 | _pics( 0 ), _videos( 0 ) | ||
56 | { | 61 | { |
57 | #ifdef QT_NO_DEBUG | 62 | #ifdef QT_NO_DEBUG |
58 | if ( !ZCameraIO::instance()->isOpen() ) | 63 | if ( !ZCameraIO::instance()->isOpen() ) |
59 | { | 64 | { |
60 | QVBox* v = new QVBox( this ); | 65 | QVBox* v = new QVBox( this ); |
61 | v->setMargin( 10 ); | 66 | v->setMargin( 10 ); |
62 | QLabel* l1 = new QLabel( v ); | 67 | QLabel* l1 = new QLabel( v ); |
63 | l1->setPixmap( Resource::loadPixmap( "camera/error" ) ); | 68 | l1->setPixmap( Resource::loadPixmap( "camera/error" ) ); |
64 | QLabel* l2 = new QLabel( v ); | 69 | QLabel* l2 = new QLabel( v ); |
65 | l2->setText( "<b>Sorry. could not detect your camera :-(</b><p>" | 70 | l2->setText( "<b>Sorry. could not detect your camera :-(</b><p>" |
66 | "* Is the sharpzdc_cs module loaded ?<br>" | 71 | "* Is the sharpzdc_cs module loaded ?<br>" |
67 | "* Is /dev/sharpzdc read/writable ?<p>" ); | 72 | "* Is /dev/sharpzdc read/writable ?<p>" ); |
68 | connect( new QPushButton( "Exit", v ), SIGNAL( clicked() ), this, SLOT( close() ) ); | 73 | connect( new QPushButton( "Exit", v ), SIGNAL( clicked() ), this, SLOT( close() ) ); |
69 | setCentralWidget( v ); | 74 | setCentralWidget( v ); |
70 | return; | 75 | return; |
71 | } | 76 | } |
72 | #endif | 77 | #endif |
73 | 78 | ||
74 | init(); | 79 | init(); |
75 | 80 | ||
76 | _rotation = 270; //TODO: grab these from the actual settings | 81 | _rotation = 270; //TODO: grab these from the actual settings |
77 | 82 | ||
78 | preview = new PreviewWidget( this, "camera preview widget" ); | 83 | preview = new PreviewWidget( this, "camera preview widget" ); |
79 | //setCentralWidget( preview ); <--- don't do this! | 84 | //setCentralWidget( preview ); <--- don't do this! |
80 | preview->resize( QSize( 240, 288 ) ); | 85 | preview->resize( QSize( 240, 288 ) ); |
81 | preview->show(); | 86 | preview->show(); |
82 | 87 | ||
83 | // construct a System Channel to receive setRotation messages | 88 | // construct a System Channel to receive setRotation messages |
84 | _sysChannel = new QCopChannel( "QPE/System", this ); | 89 | _sysChannel = new QCopChannel( "QPE/System", this ); |
85 | connect( _sysChannel, SIGNAL( received( const QCString&, const QByteArray& ) ), | 90 | connect( _sysChannel, SIGNAL( received( const QCString&, const QByteArray& ) ), |
86 | this, SLOT( systemMessage( const QCString&, const QByteArray& ) ) ); | 91 | this, SLOT( systemMessage( const QCString&, const QByteArray& ) ) ); |
87 | 92 | ||
88 | connect( preview, SIGNAL( contextMenuRequested() ), this, SLOT( showContextMenu() ) ); | 93 | connect( preview, SIGNAL( contextMenuRequested() ), this, SLOT( showContextMenu() ) ); |
89 | 94 | ||
90 | connect( ZCameraIO::instance(), SIGNAL( shutterClicked() ), this, SLOT( shutterClicked() ) ); | 95 | connect( ZCameraIO::instance(), SIGNAL( shutterClicked() ), this, SLOT( shutterClicked() ) ); |
91 | 96 | ||
92 | updateCaption(); | 97 | updateCaption(); |
93 | 98 | ||
94 | }; | 99 | }; |
95 | 100 | ||
96 | 101 | ||
97 | CameraMainWindow::~CameraMainWindow() | 102 | CameraMainWindow::~CameraMainWindow() |
98 | { | 103 | { |
99 | } | 104 | } |
100 | 105 | ||
101 | 106 | ||
102 | void CameraMainWindow::init() | 107 | void CameraMainWindow::init() |
103 | { | 108 | { |
104 | // TODO: Save this stuff in config | 109 | // TODO: Save this stuff in config |
105 | flip = 'A'; // auto | 110 | flip = 'A'; // auto |
106 | quality = 50; | 111 | quality = 50; |
107 | zoom = 1; | 112 | zoom = 1; |
108 | captureX = 640; | 113 | captureX = 480; |
109 | captureY = 480; | 114 | captureY = 640; |
110 | captureFormat = "JPEG"; | 115 | captureFormat = "JPEG"; |
111 | 116 | ||
112 | resog = new QActionGroup( 0, "reso", true ); | 117 | resog = new QActionGroup( 0, "reso", true ); |
113 | resog->setToggleAction( true ); | 118 | resog->setToggleAction( true ); |
114 | new QAction( " 64 x 48", 0, 0, resog, 0, true ); | 119 | new QAction( " 64 x 48", 0, 0, resog, 0, true ); |
115 | new QAction( "128 x 96", 0, 0, resog, 0, true ); | 120 | new QAction( "128 x 96", 0, 0, resog, 0, true ); |
116 | new QAction( "192 x 144", 0, 0, resog, 0, true ); | 121 | new QAction( "192 x 144", 0, 0, resog, 0, true ); |
117 | new QAction( "256 x 192", 0, 0, resog, 0, true ); | 122 | new QAction( "256 x 192", 0, 0, resog, 0, true ); |
118 | new QAction( "320 x 240", 0, 0, resog, 0, true ); | 123 | new QAction( "320 x 240", 0, 0, resog, 0, true ); |
119 | new QAction( "384 x 288", 0, 0, resog, 0, true ); | 124 | new QAction( "384 x 288", 0, 0, resog, 0, true ); |
120 | new QAction( "448 x 336", 0, 0, resog, 0, true ); | 125 | new QAction( "448 x 336", 0, 0, resog, 0, true ); |
121 | new QAction( "512 x 384", 0, 0, resog, 0, true ); | 126 | new QAction( "512 x 384", 0, 0, resog, 0, true ); |
122 | new QAction( "576 x 432", 0, 0, resog, 0, true ); | 127 | new QAction( "576 x 432", 0, 0, resog, 0, true ); |
123 | ( new QAction( "640 x 480", 0, 0, resog, 0, true ) )->setOn( true ); | 128 | ( new QAction( "640 x 480", 0, 0, resog, 0, true ) )->setOn( true ); |
124 | 129 | ||
125 | qualityg = new QActionGroup( 0, "quality", true ); | 130 | qualityg = new QActionGroup( 0, "quality", true ); |
126 | qualityg->setToggleAction( true ); | 131 | qualityg->setToggleAction( true ); |
127 | new QAction( " 0 (minimal)", 0, 0, qualityg, 0, true ); | 132 | new QAction( " 0 (minimal)", 0, 0, qualityg, 0, true ); |
128 | new QAction( " 25 (low)", 0, 0, qualityg, 0, true ); | 133 | new QAction( " 25 (low)", 0, 0, qualityg, 0, true ); |
129 | ( new QAction( " 50 (good)", 0, 0, qualityg, 0, true ) )->setOn( true ); | 134 | ( new QAction( " 50 (good)", 0, 0, qualityg, 0, true ) )->setOn( true ); |
130 | new QAction( " 75 (better)", 0, 0, qualityg, 0, true ); | 135 | new QAction( " 75 (better)", 0, 0, qualityg, 0, true ); |
131 | new QAction( "100 (best)", 0, 0, qualityg, 0, true ); | 136 | new QAction( "100 (best)", 0, 0, qualityg, 0, true ); |
132 | 137 | ||
133 | zoomg = new QActionGroup( 0, "zoom", true ); | 138 | zoomg = new QActionGroup( 0, "zoom", true ); |
134 | zoomg->setToggleAction( true ); | 139 | zoomg->setToggleAction( true ); |
135 | ( new QAction( "x 1", 0, 0, zoomg, 0, true ) )->setOn( true ); | 140 | ( new QAction( "x 1", 0, 0, zoomg, 0, true ) )->setOn( true ); |
136 | new QAction( "x 2", 0, 0, zoomg, 0, true ); | 141 | new QAction( "x 2", 0, 0, zoomg, 0, true ); |
137 | 142 | ||
138 | flipg = new QActionGroup( 0, "flip", true ); | 143 | flipg = new QActionGroup( 0, "flip", true ); |
139 | flipg->setToggleAction( true ); | 144 | flipg->setToggleAction( true ); |
140 | ( new QAction( "Auto (recommended)", 0, 0, flipg, 0, true ) )->setOn( true ); | 145 | ( new QAction( "Auto (recommended)", 0, 0, flipg, 0, true ) )->setOn( true ); |
141 | new QAction( "0 (always off)", 0, 0, flipg, 0, true ); | 146 | new QAction( "0 (always off)", 0, 0, flipg, 0, true ); |
142 | new QAction( "X (always horizontal)", 0, 0, flipg, 0, true ); | 147 | new QAction( "X (always horizontal)", 0, 0, flipg, 0, true ); |
143 | new QAction( "Y (always vertical)", 0, 0, flipg, 0, true ); | 148 | new QAction( "Y (always vertical)", 0, 0, flipg, 0, true ); |
144 | new QAction( "* (always both)", 0, 0, flipg, 0, true ); | 149 | new QAction( "* (always both)", 0, 0, flipg, 0, true ); |
145 | 150 | ||
146 | outputg = new QActionGroup( 0, "output", true ); | 151 | outputg = new QActionGroup( 0, "output", true ); |
147 | outputg->setToggleAction( true ); | 152 | outputg->setToggleAction( true ); |
148 | ( new QAction( "JPEG", 0, 0, outputg, 0, true ) )->setOn( true ); | 153 | ( new QAction( "JPEG", 0, 0, outputg, 0, true ) )->setOn( true ); |
149 | new QAction( "PNG", 0, 0, outputg, 0, true ); | 154 | new QAction( "PNG", 0, 0, outputg, 0, true ); |
150 | new QAction( "BMP", 0, 0, outputg, 0, true ); | 155 | new QAction( "BMP", 0, 0, outputg, 0, true ); |
151 | new QAction( "AVI", 0, 0, outputg, 0, true ); | 156 | new QAction( "AVI", 0, 0, outputg, 0, true ); |
152 | 157 | ||
153 | connect( resog, SIGNAL( selected(QAction*) ), this, SLOT( resoMenuItemClicked(QAction*) ) ); | 158 | connect( resog, SIGNAL( selected(QAction*) ), this, SLOT( resoMenuItemClicked(QAction*) ) ); |
154 | connect( qualityg, SIGNAL( selected(QAction*) ), this, SLOT( qualityMenuItemClicked(QAction*) ) ); | 159 | connect( qualityg, SIGNAL( selected(QAction*) ), this, SLOT( qualityMenuItemClicked(QAction*) ) ); |
155 | connect( zoomg, SIGNAL( selected(QAction*) ), this, SLOT( zoomMenuItemClicked(QAction*) ) ); | 160 | connect( zoomg, SIGNAL( selected(QAction*) ), this, SLOT( zoomMenuItemClicked(QAction*) ) ); |
156 | connect( flipg, SIGNAL( selected(QAction*) ), this, SLOT( flipMenuItemClicked(QAction*) ) ); | 161 | connect( flipg, SIGNAL( selected(QAction*) ), this, SLOT( flipMenuItemClicked(QAction*) ) ); |
157 | connect( outputg, SIGNAL( selected(QAction*) ), this, SLOT( outputMenuItemClicked(QAction*) ) ); | 162 | connect( outputg, SIGNAL( selected(QAction*) ), this, SLOT( outputMenuItemClicked(QAction*) ) ); |
158 | 163 | ||
159 | } | 164 | } |
160 | 165 | ||
161 | 166 | ||
162 | void CameraMainWindow::systemMessage( const QCString& msg, const QByteArray& data ) | 167 | void CameraMainWindow::systemMessage( const QCString& msg, const QByteArray& data ) |
163 | { | 168 | { |
169 | int _newrotation; | ||
170 | |||
164 | QDataStream stream( data, IO_ReadOnly ); | 171 | QDataStream stream( data, IO_ReadOnly ); |
165 | odebug << "received system message: " << msg << oendl; | 172 | odebug << "received system message: " << msg << oendl; |
166 | if ( msg == "setCurrentRotation(int)" ) | 173 | if ( msg == "setCurrentRotation(int)" ) |
167 | { | 174 | { |
168 | stream >> _rotation; | 175 | stream >> _newrotation; |
169 | odebug << "received setCurrentRotation(" << _rotation << ")" << oendl; | 176 | odebug << "received setCurrentRotation(" << _newrotation << ")" << oendl; |
170 | 177 | ||
171 | switch ( _rotation ) | 178 | switch ( _newrotation ) |
172 | { | 179 | { |
173 | case 270: preview->resize( QSize( 240, 288 ) ); break; | 180 | case 270: preview->resize( QSize( 240, 288 ) ); break; |
174 | case 180: preview->resize( QSize( 320, 208 ) ); break; | 181 | case 180: preview->resize( QSize( 320, 208 ) ); break; |
175 | default: QMessageBox::warning( this, "opie-camera", | 182 | default: QMessageBox::warning( this, "opie-camera", |
176 | "This rotation is not supported.\n" | 183 | "This rotation is not supported.\n" |
177 | "Supported are 180° and 270°" ); | 184 | "Supported are 180° and 270°" ); |
178 | } | 185 | } |
186 | |||
187 | if ( _newrotation != _rotation ) | ||
188 | { | ||
189 | int tmp = captureX; | ||
190 | captureX = captureY; | ||
191 | captureY = tmp; | ||
192 | _rotation = _newrotation; | ||
193 | } | ||
194 | |||
195 | updateCaption(); | ||
196 | |||
179 | } | 197 | } |
180 | } | 198 | } |
181 | 199 | ||
182 | 200 | ||
183 | void CameraMainWindow::changeZoom( int zoom ) | 201 | void CameraMainWindow::changeZoom( int zoom ) |
184 | { | 202 | { |
185 | int z; | 203 | int z; |
186 | switch ( zoom ) | 204 | switch ( zoom ) |
187 | { | 205 | { |
188 | case 0: z = 128; break; | 206 | case 0: z = 128; break; |
189 | case 1: z = 256; break; | 207 | case 1: z = 256; break; |
190 | case 2: z = 512; break; | 208 | case 2: z = 512; break; |
191 | default: assert( 0 ); break; | 209 | default: assert( 0 ); break; |
192 | } | 210 | } |
193 | 211 | ||
194 | ZCameraIO::instance()->setCaptureFrame( 240, 160, z ); | 212 | ZCameraIO::instance()->setCaptureFrame( 240, 160, z ); |
195 | } | 213 | } |
196 | 214 | ||
197 | 215 | ||
198 | void CameraMainWindow::showContextMenu() | 216 | void CameraMainWindow::showContextMenu() |
199 | { | 217 | { |
200 | QPopupMenu reso; | 218 | QPopupMenu reso; |
201 | reso.setCheckable( true ); | 219 | reso.setCheckable( true ); |
202 | resog->addTo( &reso ); | 220 | resog->addTo( &reso ); |
203 | 221 | ||
204 | QPopupMenu quality; | 222 | QPopupMenu quality; |
205 | quality.setCheckable( true ); | 223 | quality.setCheckable( true ); |
206 | qualityg->addTo( &quality ); | 224 | qualityg->addTo( &quality ); |
207 | 225 | ||
208 | QPopupMenu flip; | 226 | QPopupMenu flip; |
209 | flip.setCheckable( true ); | 227 | flip.setCheckable( true ); |
210 | flipg->addTo( &flip ); | 228 | flipg->addTo( &flip ); |
211 | 229 | ||
212 | QPopupMenu zoom; | 230 | QPopupMenu zoom; |
213 | zoom.setCheckable( true ); | 231 | zoom.setCheckable( true ); |
214 | zoomg->addTo( &zoom ); | 232 | zoomg->addTo( &zoom ); |
215 | 233 | ||
216 | QPopupMenu output; | 234 | QPopupMenu output; |
217 | output.setCheckable( true ); | 235 | output.setCheckable( true ); |
218 | outputg->addTo( &output ); | 236 | outputg->addTo( &output ); |
219 | 237 | ||
220 | QPopupMenu m( this ); | 238 | QPopupMenu m( this ); |
221 | m.insertItem( "&Resolution", &reso ); | 239 | m.insertItem( "&Resolution", &reso ); |
222 | m.insertItem( "&Zoom", &zoom ); | 240 | m.insertItem( "&Zoom", &zoom ); |
223 | m.insertItem( "&Flip", &flip ); | 241 | m.insertItem( "&Flip", &flip ); |
224 | m.insertItem( "&Quality", &quality ); | 242 | m.insertItem( "&Quality", &quality ); |
225 | m.insertItem( "&Output As", &output ); | 243 | m.insertItem( "&Output As", &output ); |
244 | |||
245 | #ifndef QT_NO_DEBUG | ||
246 | m.insertItem( "&Debug!", this, SLOT( doSomething() ) ); | ||
247 | #endif | ||
248 | |||
226 | m.exec( QCursor::pos() ); | 249 | m.exec( QCursor::pos() ); |
227 | } | 250 | } |
228 | 251 | ||
229 | 252 | ||
230 | void CameraMainWindow::resoMenuItemClicked( QAction* a ) | 253 | void CameraMainWindow::resoMenuItemClicked( QAction* a ) |
231 | { | 254 | { |
232 | captureX = a->text().left(3).toInt(); | 255 | switch ( _rotation ) |
233 | captureY = a->text().right(3).toInt(); | 256 | { |
257 | case 270: | ||
258 | captureY = a->text().left(3).toInt(); | ||
259 | captureX = a->text().right(3).toInt(); | ||
260 | break; | ||
261 | case 180: | ||
262 | captureX = a->text().left(3).toInt(); | ||
263 | captureY = a->text().right(3).toInt(); | ||
264 | break; | ||
265 | default: QMessageBox::warning( this, "opie-camera", | ||
266 | "This rotation is not supported.\n" | ||
267 | "Supported are 180° and 270°" ); | ||
268 | } | ||
234 | odebug << "Capture Resolution now: " << captureX << ", " << captureY << oendl; | 269 | odebug << "Capture Resolution now: " << captureX << ", " << captureY << oendl; |
235 | updateCaption(); | 270 | updateCaption(); |
236 | } | 271 | } |
237 | 272 | ||
238 | 273 | ||
239 | void CameraMainWindow::qualityMenuItemClicked( QAction* a ) | 274 | void CameraMainWindow::qualityMenuItemClicked( QAction* a ) |
240 | { | 275 | { |
241 | quality = a->text().left(3).toInt(); | 276 | quality = a->text().left(3).toInt(); |
242 | odebug << "Quality now: " << quality << oendl; | 277 | odebug << "Quality now: " << quality << oendl; |
243 | updateCaption(); | 278 | updateCaption(); |
244 | } | 279 | } |
245 | 280 | ||
246 | 281 | ||
247 | void CameraMainWindow::zoomMenuItemClicked( QAction* a ) | 282 | void CameraMainWindow::zoomMenuItemClicked( QAction* a ) |
248 | { | 283 | { |
249 | zoom = QString( a->text().at(2) ).toInt(); | 284 | zoom = QString( a->text().at(2) ).toInt(); |
250 | odebug << "Zoom now: " << zoom << oendl; | 285 | odebug << "Zoom now: " << zoom << oendl; |
251 | ZCameraIO::instance()->setZoom( zoom ); | 286 | ZCameraIO::instance()->setZoom( zoom ); |
252 | updateCaption(); | 287 | updateCaption(); |
253 | } | 288 | } |
254 | 289 | ||
255 | 290 | ||
256 | void CameraMainWindow::flipMenuItemClicked( QAction* a ) | 291 | void CameraMainWindow::flipMenuItemClicked( QAction* a ) |
257 | { | 292 | { |
258 | flip = QString( a->text().at(0) ); | 293 | flip = QString( a->text().at(0) ); |
259 | odebug << "Flip now: " << flip << oendl; | 294 | odebug << "Flip now: " << flip << oendl; |
260 | if ( flip == "A" ) | 295 | if ( flip == "A" ) |
261 | ZCameraIO::instance()->setFlip( ZCameraIO::AUTOMATICFLIP ); | 296 | ZCameraIO::instance()->setFlip( ZCameraIO::AUTOMATICFLIP ); |
262 | else if ( flip == "0" ) | 297 | else if ( flip == "0" ) |
263 | ZCameraIO::instance()->setFlip( ZCameraIO::XNOFLIP | ZCameraIO::YNOFLIP ); | 298 | ZCameraIO::instance()->setFlip( ZCameraIO::XNOFLIP | ZCameraIO::YNOFLIP ); |
264 | else if ( flip == "X" ) | 299 | else if ( flip == "X" ) |
265 | ZCameraIO::instance()->setFlip( ZCameraIO::XFLIP ); | 300 | ZCameraIO::instance()->setFlip( ZCameraIO::XFLIP ); |
266 | else if ( flip == "Y" ) | 301 | else if ( flip == "Y" ) |
267 | ZCameraIO::instance()->setFlip( ZCameraIO::YFLIP ); | 302 | ZCameraIO::instance()->setFlip( ZCameraIO::YFLIP ); |
268 | else if ( flip == "*" ) | 303 | else if ( flip == "*" ) |
269 | ZCameraIO::instance()->setFlip( ZCameraIO::XFLIP | ZCameraIO::YFLIP ); | 304 | ZCameraIO::instance()->setFlip( ZCameraIO::XFLIP | ZCameraIO::YFLIP ); |
270 | 305 | ||
271 | updateCaption(); | 306 | updateCaption(); |
272 | } | 307 | } |
273 | 308 | ||
274 | 309 | ||
275 | void CameraMainWindow::outputMenuItemClicked( QAction* a ) | 310 | void CameraMainWindow::outputMenuItemClicked( QAction* a ) |
276 | { | 311 | { |
277 | captureFormat = a->text(); | 312 | captureFormat = a->text(); |
278 | odebug << "Output format now: " << captureFormat << oendl; | 313 | odebug << "Output format now: " << captureFormat << oendl; |
279 | updateCaption(); | 314 | updateCaption(); |
280 | } | 315 | } |
281 | 316 | ||
282 | 317 | ||
283 | void CameraMainWindow::shutterClicked() | 318 | void CameraMainWindow::shutterClicked() |
284 | { | 319 | { |
285 | if ( captureFormat != "AVI" ) // capture one photo per shutterClick | 320 | if ( captureFormat != "AVI" ) // capture one photo per shutterClick |
286 | { | 321 | { |
287 | Global::statusMessage( "CAPTURING..." ); | 322 | Global::statusMessage( "CAPTURING..." ); |
288 | qApp->processEvents(); | 323 | qApp->processEvents(); |
289 | 324 | ||
290 | odebug << "Shutter has been pressed" << oendl; | 325 | odebug << "Shutter has been pressed" << oendl; |
291 | ODevice::inst()->touchSound(); | 326 | ODevice::inst()->touchSound(); |
292 | 327 | ||
293 | performCapture( captureFormat ); | 328 | performCapture( captureFormat ); |
294 | } | 329 | } |
295 | else // capture video! start with one shutter click and stop with the next | 330 | else // capture video! start with one shutter click and stop with the next |
296 | { | 331 | { |
297 | !_capturing ? startVideoCapture() : stopVideoCapture(); | 332 | !_capturing ? startVideoCapture() : stopVideoCapture(); |
298 | } | 333 | } |
299 | } | 334 | } |
300 | 335 | ||
301 | 336 | ||
302 | void CameraMainWindow::performCapture( const QString& format ) | 337 | void CameraMainWindow::performCapture( const QString& format ) |
303 | { | 338 | { |
304 | QString name; | 339 | QString name; |
305 | name.sprintf( "/tmp/image-%d_%d_%d_q%d.%s", _pics++, captureX, captureY, quality, (const char*) captureFormat.lower() ); | 340 | name.sprintf( "/tmp/image-%d_%d_%d_q%d.%s", _pics++, captureX, captureY, quality, (const char*) captureFormat.lower() ); |
306 | QImage i; | 341 | QImage i; |
307 | ZCameraIO::instance()->captureFrame( captureX, captureY, zoom, &i ); | 342 | ZCameraIO::instance()->captureFrame( captureX, captureY, zoom, &i ); |
308 | QImage im = i.convertDepth( 32 ); | 343 | QImage im = i.convertDepth( 32 ); |
309 | bool result = im.save( name, format, quality ); | 344 | bool result = im.save( name, format, quality ); |
310 | if ( !result ) | 345 | if ( !result ) |
311 | { | 346 | { |
312 | oerr << "imageio-Problem while writing." << oendl; | 347 | oerr << "imageio-Problem while writing." << oendl; |
313 | Global::statusMessage( "Error!" ); | 348 | Global::statusMessage( "Error!" ); |
314 | } | 349 | } |
315 | else | 350 | else |
316 | { | 351 | { |
317 | odebug << captureFormat << "-image has been successfully captured" << oendl; | 352 | odebug << captureFormat << "-image has been successfully captured" << oendl; |
318 | Global::statusMessage( "Ok." ); | 353 | Global::statusMessage( "Ok." ); |
319 | } | 354 | } |
320 | } | 355 | } |
321 | 356 | ||
322 | 357 | ||
323 | void CameraMainWindow::startVideoCapture() | 358 | void CameraMainWindow::startVideoCapture() |
324 | { | 359 | { |
325 | //ODevice::inst()->touchSound(); | 360 | //ODevice::inst()->touchSound(); |
326 | ODevice::inst()->setLedState( Led_Mail, Led_BlinkSlow ); | 361 | ODevice::inst()->setLedState( Led_Mail, Led_BlinkSlow ); |
327 | 362 | ||
328 | _capturefd = ::open( CAPTUREFILE, O_WRONLY | O_CREAT ); | 363 | _capturefd = ::open( CAPTUREFILE, O_WRONLY | O_CREAT | O_TRUNC ); |
329 | if ( _capturefd == -1 ) | 364 | if ( _capturefd == -1 ) |
330 | { | 365 | { |
331 | owarn << "can't open capture file: " << strerror(errno) << oendl; | 366 | owarn << "can't open capture file: " << strerror(errno) << oendl; |
332 | return; | 367 | return; |
333 | } | 368 | } |
334 | 369 | ||
335 | _capturebuf = new unsigned char[captureX*captureY*2]; | 370 | _capturebuf = new unsigned char[captureX*captureY*2]; |
336 | _capturing = true; | 371 | _capturing = true; |
337 | _videopics = 0; | 372 | _videopics = 0; |
373 | _framerate = 0; | ||
338 | updateCaption(); | 374 | updateCaption(); |
339 | _time.start(); | 375 | _time.start(); |
340 | preview->setRefreshingRate( 1000 ); | 376 | preview->setRefreshingRate( 1000 ); |
341 | startTimer( 100 ); // too fast but that is ok | 377 | startTimer( 100 ); // too fast but that is ok |
342 | } | 378 | } |
343 | 379 | ||
344 | 380 | ||
345 | void CameraMainWindow::timerEvent( QTimerEvent* ) | 381 | void CameraMainWindow::timerEvent( QTimerEvent* ) |
346 | { | 382 | { |
347 | if ( !_capturing ) | 383 | if ( !_capturing ) |
348 | { | 384 | { |
349 | owarn << "timer event in CameraMainWindow without capturing video ?" << oendl; | 385 | odebug << "timer event in CameraMainWindow without capturing video ?" << oendl; |
350 | return; | 386 | return; |
351 | } | 387 | } |
352 | 388 | ||
389 | odebug << "timer event during video - now capturing frame #" << _videopics+1 << oendl; | ||
390 | |||
353 | ZCameraIO::instance()->captureFrame( captureX, captureY, zoom, _capturebuf ); | 391 | ZCameraIO::instance()->captureFrame( captureX, captureY, zoom, _capturebuf ); |
354 | _videopics++; | 392 | _videopics++; |
355 | ::write( _capturefd, _capturebuf, captureX*captureY*2 ); | 393 | ::write( _capturefd, _capturebuf, captureX*captureY*2 ); |
356 | setCaption( QString().sprintf( "Capturing %dx%d @ %.2f fps %d", | 394 | setCaption( QString().sprintf( "Capturing %dx%d @ %.2f fps %d", |
357 | captureX, captureY, 1000.0 / (_time.elapsed()/_videopics), _videopics ) ); | 395 | captureX, captureY, 1000.0 / (_time.elapsed()/_videopics), _videopics ) ); |
358 | } | 396 | } |
359 | 397 | ||
360 | 398 | ||
361 | void CameraMainWindow::stopVideoCapture() | 399 | void CameraMainWindow::stopVideoCapture() |
362 | { | 400 | { |
363 | killTimers(); | 401 | killTimers(); |
364 | //ODevice::inst()->touchSound(); | 402 | //ODevice::inst()->touchSound(); |
365 | ODevice::inst()->setLedState( Led_Mail, Led_Off ); | 403 | ODevice::inst()->setLedState( Led_Mail, Led_Off ); |
366 | _capturing = false; | 404 | _capturing = false; |
367 | updateCaption(); | 405 | updateCaption(); |
368 | ::close( _capturefd ); | 406 | ::close( _capturefd ); |
407 | _framerate = 1000.0 / (_time.elapsed()/_videopics); | ||
369 | 408 | ||
370 | //postProcessVideo(); | 409 | postProcessVideo( CAPTUREFILE, QString().sprintf( "/tmp/video-%d_%d_%d_q%d-%dfps.avi", _videos++, captureX, captureY, quality, _framerate ) ); |
371 | 410 | ||
372 | #ifndef QT_NO_DEBUG | 411 | #ifndef QT_NO_DEBUG |
373 | preview->setRefreshingRate( 1500 ); | 412 | preview->setRefreshingRate( 1500 ); |
374 | #else | 413 | #else |
375 | preview->setRefreshingRate( 200 ); | 414 | preview->setRefreshingRate( 200 ); |
376 | #endif | 415 | #endif |
377 | 416 | ||
378 | //delete[] _capturebuf; //FIXME: close memory leak | 417 | //delete[] _capturebuf; //FIXME: close memory leak |
379 | } | 418 | } |
380 | 419 | ||
381 | void CameraMainWindow::postProcessVideo() | 420 | void CameraMainWindow::postProcessVideo( const QString& infile, const QString& outfile ) |
382 | { | 421 | { |
383 | preview->setRefreshingRate( 0 ); | 422 | preview->setRefreshingRate( 0 ); |
384 | 423 | ||
385 | /* | 424 | /* |
425 | unsigned char buf[153600]; | ||
386 | 426 | ||
387 | QDialog* fr = new QDialog( this, "splash" ); //, false, QWidget::WStyle_NoBorder | QWidget::WStyle_Customize ); | 427 | int fd = ::open( "/var/compile/opie/noncore/multimedia/camera/capture-320x240.dat", O_RDONLY ); |
428 | ::read( fd, &buf, 153600 ); | ||
429 | QImage i; | ||
430 | bufferToImage( 240, 320, (unsigned char*) &buf, &i ); | ||
431 | QPixmap p; | ||
432 | p.convertFromImage( i ); | ||
433 | preview->setPixmap( p ); | ||
434 | imageToFile( &i, "/tmp/tmpfile", "JPEG", 100 ); | ||
435 | return; | ||
436 | */ | ||
437 | |||
438 | QDialog* fr = new QDialog( this, "splash", false, QWidget::WStyle_StaysOnTop ); //, false, QWidget::WStyle_NoBorder | QWidget::WStyle_Customize ); | ||
388 | fr->setCaption( "Please wait..." ); | 439 | fr->setCaption( "Please wait..." ); |
389 | QVBoxLayout* box = new QVBoxLayout( fr, 2, 2 ); | 440 | QVBoxLayout* box = new QVBoxLayout( fr, 2, 2 ); |
390 | QProgressBar* bar = new QProgressBar( fr ); | 441 | QProgressBar* bar = new QProgressBar( fr ); |
391 | bar->setCenterIndicator( true ); | 442 | bar->setCenterIndicator( true ); |
392 | bar->setTotalSteps( _videopics-1 ); | 443 | bar->setTotalSteps( _videopics-1 ); |
393 | QLabel* label = new QLabel( "Post processing frame bla/bla", fr ); | 444 | QLabel* label = new QLabel( "Post processing frame bla/bla", fr ); |
394 | box->addWidget( bar ); | 445 | box->addWidget( bar ); |
395 | box->addWidget( label ); | 446 | box->addWidget( label ); |
396 | fr->show(); | 447 | fr->show(); |
448 | label->show(); | ||
449 | bar->show(); | ||
450 | fr->repaint(); | ||
397 | qApp->processEvents(); | 451 | qApp->processEvents(); |
398 | 452 | ||
399 | for ( int i = 0; i < _videopics; ++i ) | 453 | // open files |
400 | { | ||
401 | label->setText( QString().sprintf( "Post processing frame %d / %d", i+1, _videopics ) ); | ||
402 | bar->setProgress( i ); | ||
403 | qApp->processEvents(); | ||
404 | } | ||
405 | |||
406 | */ | ||
407 | 454 | ||
408 | int infd = ::open( CAPTUREFILE, O_RDONLY ); | 455 | int infd = ::open( (const char*) infile, O_RDONLY ); |
409 | if ( infd == -1 ) | 456 | if ( infd == -1 ) |
410 | { | 457 | { |
411 | owarn << "couldn't open capture file: " << strerror(errno) << oendl; | 458 | owarn << "couldn't open capture file: " << strerror(errno) << oendl; |
412 | return; | 459 | return; |
413 | } | 460 | } |
414 | 461 | ||
415 | int outfd = ::open( "/tmp/output.avi", O_WRONLY ); | 462 | int outfd = ::open( (const char*) outfile, O_CREAT | O_WRONLY | O_TRUNC, 0644 ); |
416 | if ( outfd == -1 ) | 463 | if ( outfd == -1 ) |
417 | { | 464 | { |
418 | owarn << "couldn't open output file: " << strerror(errno) << oendl; | 465 | owarn << "couldn't open output file: " << strerror(errno) << oendl; |
419 | return; | 466 | return; |
420 | } | 467 | } |
421 | 468 | ||
469 | int framesize = captureX*captureY*2; | ||
470 | |||
471 | unsigned char* inbuffer = new unsigned char[ framesize ]; | ||
472 | QImage image; | ||
422 | 473 | ||
474 | avi_start( outfd, _videopics ); // write preambel | ||
423 | 475 | ||
476 | // post process | ||
477 | |||
478 | for ( int i = 0; i < _videopics; ++i ) | ||
479 | { | ||
480 | odebug << "processing frame " << i << oendl; | ||
481 | |||
482 | // <gui> | ||
483 | label->setText( QString().sprintf( "Post processing frame %d / %d", i+1, _videopics ) ); | ||
484 | bar->setProgress( i ); | ||
485 | bar->repaint(); | ||
486 | qApp->processEvents(); | ||
487 | // </gui> | ||
488 | |||
489 | int read = ::read( infd, inbuffer, framesize ); | ||
490 | odebug << "read " << read << " bytes" << oendl; | ||
491 | bufferToImage( captureX, captureY, inbuffer, &image ); | ||
492 | |||
493 | QPixmap p; | ||
494 | p.convertFromImage( image ); | ||
495 | preview->setPixmap( p ); | ||
496 | preview->repaint(); | ||
497 | qApp->processEvents(); | ||
498 | |||
499 | QString tmpfilename( "/tmp/tempfile" ); | ||
500 | //tmpfilename.sprintf( "/tmp/test/%d.jpg", i ); | ||
501 | |||
502 | imageToFile( &image, tmpfilename, "JPEG", quality ); | ||
503 | |||
504 | QFile framefile( tmpfilename ); | ||
505 | if ( !framefile.open( IO_ReadOnly ) ) | ||
506 | { | ||
507 | oerr << "can't process file: %s" << strerror(errno) << oendl; | ||
508 | return; // TODO: clean up temp ressources | ||
509 | } | ||
510 | |||
511 | int filesize = framefile.size(); | ||
512 | odebug << "filesize for frame " << i << " = " << filesize << oendl; | ||
513 | |||
514 | unsigned char* tempbuffer = new unsigned char[ filesize ]; | ||
515 | framefile.readBlock( (char*) tempbuffer, filesize ); | ||
516 | avi_add( outfd, tempbuffer, filesize ); | ||
517 | delete tempbuffer; | ||
518 | framefile.close(); | ||
519 | } | ||
520 | |||
521 | avi_end( outfd, captureX, captureY, _framerate ); | ||
522 | |||
523 | fr->hide(); | ||
524 | delete fr; | ||
525 | |||
526 | updateCaption(); | ||
424 | 527 | ||
425 | } | 528 | } |
426 | 529 | ||
530 | |||
427 | void CameraMainWindow::updateCaption() | 531 | void CameraMainWindow::updateCaption() |
428 | { | 532 | { |
429 | if ( !_capturing ) | 533 | if ( !_capturing ) |
430 | setCaption( QString().sprintf( "Opie-Camera: %dx%d %s q%d z%d (%s)", captureX, captureY, (const char*) captureFormat.lower(), quality, zoom, (const char*) flip ) ); | 534 | setCaption( QString().sprintf( "Opie-Camera: %dx%d %s q%d z%d (%s)", captureX, captureY, (const char*) captureFormat.lower(), quality, zoom, (const char*) flip ) ); |
431 | else | 535 | else |
432 | setCaption( "Opie-Camera: => CAPTURING <=" ); | 536 | setCaption( "Opie-Camera: => CAPTURING <=" ); |
433 | } | 537 | } |
434 | 538 | ||
435 | 539 | ||
540 | #ifndef QT_NO_DEBUG | ||
541 | void CameraMainWindow::doSomething() | ||
542 | { | ||
543 | captureX = 240; | ||
544 | captureY = 320; | ||
545 | _videopics = 176; | ||
546 | _framerate = 5; | ||
547 | postProcessVideo( "/var/compile/opie/noncore/multimedia/camera/capture-320x240.dat", | ||
548 | "/tmp/output.avi" ); | ||
549 | } | ||
550 | #endif | ||
551 | |||
diff --git a/noncore/multimedia/camera/mainwindow.h b/noncore/multimedia/camera/mainwindow.h index ad8d1b1..ac83488 100644 --- a/noncore/multimedia/camera/mainwindow.h +++ b/noncore/multimedia/camera/mainwindow.h | |||
@@ -1,92 +1,99 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2003 Michael 'Mickey' Lauer. All rights reserved. | 2 | ** Copyright (C) 2003 Michael 'Mickey' Lauer. All rights reserved. |
3 | ** | 3 | ** |
4 | ** This file is part of Opie Environment. | 4 | ** This file is part of Opie Environment. |
5 | ** | 5 | ** |
6 | ** This file may be distributed and/or modified under the terms of the | 6 | ** This file may be distributed and/or modified under the terms of the |
7 | ** GNU General Public License version 2 as published by the Free Software | 7 | ** GNU General Public License version 2 as published by the Free Software |
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | 8 | ** Foundation and appearing in the file LICENSE.GPL included in the |
9 | ** packaging of this file. | 9 | ** packaging of this file. |
10 | ** | 10 | ** |
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
13 | ** | 13 | ** |
14 | **********************************************************************/ | 14 | **********************************************************************/ |
15 | 15 | ||
16 | #ifndef MAINWINDOW_H | 16 | #ifndef MAINWINDOW_H |
17 | #define MAINWINDOW_H | 17 | #define MAINWINDOW_H |
18 | 18 | ||
19 | #include <qmainwindow.h> | 19 | #include <qmainwindow.h> |
20 | #include <qdatetime.h> | 20 | #include <qdatetime.h> |
21 | #include <qimage.h> | 21 | #include <qimage.h> |
22 | #include <qpixmap.h> | 22 | #include <qpixmap.h> |
23 | #include <qdatetime.h> | 23 | #include <qdatetime.h> |
24 | 24 | ||
25 | class QAction; | 25 | class QAction; |
26 | class QActionGroup; | 26 | class QActionGroup; |
27 | class QIconSet; | 27 | class QIconSet; |
28 | class QTimerEvent; | 28 | class QTimerEvent; |
29 | class QToolButton; | 29 | class QToolButton; |
30 | class QLabel; | 30 | class QLabel; |
31 | class MainWindowBase; | 31 | class MainWindowBase; |
32 | class QCopChannel; | 32 | class QCopChannel; |
33 | class PreviewWidget; | 33 | class PreviewWidget; |
34 | 34 | ||
35 | class CameraMainWindow: public QMainWindow | 35 | class CameraMainWindow: public QMainWindow |
36 | { | 36 | { |
37 | Q_OBJECT | 37 | Q_OBJECT |
38 | 38 | ||
39 | public: | 39 | public: |
40 | CameraMainWindow( QWidget * parent = 0, const char * name = "mainwindow", WFlags f = 0 ); | 40 | CameraMainWindow( QWidget * parent = 0, const char * name = "mainwindow", WFlags f = 0 ); |
41 | virtual ~CameraMainWindow(); | 41 | virtual ~CameraMainWindow(); |
42 | 42 | ||
43 | public slots: | 43 | public slots: |
44 | void changeZoom( int ); | 44 | void changeZoom( int ); |
45 | void systemMessage( const QCString&, const QByteArray& ); | 45 | void systemMessage( const QCString&, const QByteArray& ); |
46 | void showContextMenu(); | 46 | void showContextMenu(); |
47 | void resoMenuItemClicked( QAction* ); | 47 | void resoMenuItemClicked( QAction* ); |
48 | void qualityMenuItemClicked( QAction* ); | 48 | void qualityMenuItemClicked( QAction* ); |
49 | void zoomMenuItemClicked( QAction* ); | 49 | void zoomMenuItemClicked( QAction* ); |
50 | void flipMenuItemClicked( QAction* ); | 50 | void flipMenuItemClicked( QAction* ); |
51 | void outputMenuItemClicked( QAction* ); | 51 | void outputMenuItemClicked( QAction* ); |
52 | void shutterClicked(); | 52 | void shutterClicked(); |
53 | 53 | ||
54 | void updateCaption(); | 54 | void updateCaption(); |
55 | 55 | ||
56 | protected: | 56 | protected: |
57 | void init(); | 57 | void init(); |
58 | void startVideoCapture(); | 58 | void startVideoCapture(); |
59 | void stopVideoCapture(); | 59 | void stopVideoCapture(); |
60 | void postProcessVideo(); | 60 | void postProcessVideo( const QString&, const QString& ); |
61 | void performCapture( const QString& ); | 61 | void performCapture( const QString& ); |
62 | 62 | ||
63 | virtual void timerEvent( QTimerEvent* ); | 63 | virtual void timerEvent( QTimerEvent* ); |
64 | 64 | ||
65 | protected slots: | ||
66 | #ifndef QT_NO_DEBUG | ||
67 | void doSomething(); // solely for debugging purposes | ||
68 | #endif | ||
69 | |||
65 | private: | 70 | private: |
66 | PreviewWidget* preview; | 71 | PreviewWidget* preview; |
67 | int _rotation; | 72 | int _rotation; |
68 | QCopChannel* _sysChannel; | 73 | QCopChannel* _sysChannel; |
69 | 74 | ||
70 | QActionGroup* resog; | 75 | QActionGroup* resog; |
71 | QActionGroup* qualityg; | 76 | QActionGroup* qualityg; |
72 | QActionGroup* zoomg; | 77 | QActionGroup* zoomg; |
73 | QActionGroup* flipg; | 78 | QActionGroup* flipg; |
74 | QActionGroup* outputg; | 79 | QActionGroup* outputg; |
75 | 80 | ||
76 | QString flip; | 81 | QString flip; |
77 | int quality; | 82 | int quality; |
78 | int zoom; | 83 | int zoom; |
79 | int captureX; | 84 | int captureX; |
80 | int captureY; | 85 | int captureY; |
81 | QString captureFormat; | 86 | QString captureFormat; |
82 | 87 | ||
83 | bool _capturing; | 88 | bool _capturing; |
84 | int _pics; | 89 | int _pics; |
90 | int _videos; | ||
85 | 91 | ||
86 | QTime _time; | 92 | QTime _time; |
87 | int _videopics; | 93 | int _videopics; |
88 | int _capturefd; | 94 | int _capturefd; |
95 | int _framerate; | ||
89 | unsigned char* _capturebuf; | 96 | unsigned char* _capturebuf; |
90 | }; | 97 | }; |
91 | 98 | ||
92 | #endif | 99 | #endif |
diff --git a/noncore/multimedia/camera/zcameraio.cpp b/noncore/multimedia/camera/zcameraio.cpp index 1c449e7..c940b45 100644 --- a/noncore/multimedia/camera/zcameraio.cpp +++ b/noncore/multimedia/camera/zcameraio.cpp | |||
@@ -1,318 +1,311 @@ | |||
1 | /********************************************************************** | 1 | /********************************************************************** |
2 | ** Copyright (C) 2002 Michael 'Mickey' Lauer. All rights reserved. | 2 | ** Copyright (C) 2002 Michael 'Mickey' Lauer. All rights reserved. |
3 | ** | 3 | ** |
4 | ** This file is part of Opie Environment. | 4 | ** This file is part of Opie Environment. |
5 | ** | 5 | ** |
6 | ** This file may be distributed and/or modified under the terms of the | 6 | ** This file may be distributed and/or modified under the terms of the |
7 | ** GNU General Public License version 2 as published by the Free Software | 7 | ** GNU General Public License version 2 as published by the Free Software |
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | 8 | ** Foundation and appearing in the file LICENSE.GPL included in the |
9 | ** packaging of this file. | 9 | ** packaging of this file. |
10 | ** | 10 | ** |
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
13 | ** | 13 | ** |
14 | **********************************************************************/ | 14 | **********************************************************************/ |
15 | 15 | ||
16 | #include "zcameraio.h" | 16 | #include "zcameraio.h" |
17 | 17 | ||
18 | #include <sys/types.h> | 18 | #include <sys/types.h> |
19 | #include <sys/stat.h> | 19 | #include <sys/stat.h> |
20 | #include <errno.h> | 20 | #include <errno.h> |
21 | #include <string.h> | 21 | #include <string.h> |
22 | #include <fcntl.h> | 22 | #include <fcntl.h> |
23 | #include <unistd.h> | 23 | #include <unistd.h> |
24 | #include <stdio.h> | 24 | #include <stdio.h> |
25 | 25 | ||
26 | #include <qimage.h> | 26 | #include <qimage.h> |
27 | #include <qdatetime.h> | 27 | #include <qdatetime.h> |
28 | 28 | ||
29 | #include <opie2/odebug.h> | 29 | #include <opie2/odebug.h> |
30 | 30 | ||
31 | #define SHARPZDC "/dev/sharp_zdc" | 31 | #define SHARPZDC "/dev/sharp_zdc" |
32 | 32 | ||
33 | ZCameraIO* ZCameraIO::_instance = 0; | 33 | ZCameraIO* ZCameraIO::_instance = 0; |
34 | 34 | ||
35 | ZCameraIO* ZCameraIO::instance() | 35 | ZCameraIO* ZCameraIO::instance() |
36 | { | 36 | { |
37 | if ( !ZCameraIO::_instance ) | 37 | if ( !ZCameraIO::_instance ) |
38 | { | 38 | { |
39 | odebug << "Creating ZCameraIO::_instance" << oendl; | 39 | odebug << "Creating ZCameraIO::_instance" << oendl; |
40 | ZCameraIO::_instance = new ZCameraIO(); | 40 | ZCameraIO::_instance = new ZCameraIO(); |
41 | } | 41 | } |
42 | return ZCameraIO::_instance; | 42 | return ZCameraIO::_instance; |
43 | } | 43 | } |
44 | 44 | ||
45 | 45 | ||
46 | ZCameraIO::ZCameraIO() | 46 | ZCameraIO::ZCameraIO() |
47 | : _pressed( false ), _height( 0 ), _width( 0 ), _zoom( 0 ), | 47 | : _pressed( false ), _height( 0 ), _width( 0 ), _zoom( 0 ), |
48 | _flip( -1 ), _rot( 0 ), _readlen( 0 ) | 48 | _flip( -1 ), _rot( 0 ), _readlen( 0 ) |
49 | 49 | ||
50 | { | 50 | { |
51 | _driver = ::open( SHARPZDC, O_RDWR ); | 51 | _driver = ::open( SHARPZDC, O_RDWR ); |
52 | if ( _driver == -1 ) | 52 | if ( _driver == -1 ) |
53 | oerr << "Can't open camera driver: " << strerror(errno) << oendl; | 53 | oerr << "Can't open camera driver: " << strerror(errno) << oendl; |
54 | else | 54 | else |
55 | init(); | 55 | init(); |
56 | } | 56 | } |
57 | 57 | ||
58 | 58 | ||
59 | void ZCameraIO::init() | 59 | void ZCameraIO::init() |
60 | { | 60 | { |
61 | if ( ZCameraIO::_instance ) | 61 | if ( ZCameraIO::_instance ) |
62 | ofatal << "Don't create more than one ZCameraIO instances." << oendl; | 62 | ofatal << "Don't create more than one ZCameraIO instances." << oendl; |
63 | else | 63 | else |
64 | { | 64 | { |
65 | _timer = new QTime(); | 65 | _timer = new QTime(); |
66 | setReadMode( STATUS ); | 66 | setReadMode( STATUS ); |
67 | } | 67 | } |
68 | } | 68 | } |
69 | 69 | ||
70 | 70 | ||
71 | ZCameraIO::~ZCameraIO() | 71 | ZCameraIO::~ZCameraIO() |
72 | { | 72 | { |
73 | if ( _driver != -1 ) | 73 | if ( _driver != -1 ) |
74 | { | 74 | { |
75 | setReadMode( 0 ); | 75 | setReadMode( 0 ); |
76 | ::close( _driver ); | 76 | ::close( _driver ); |
77 | } | 77 | } |
78 | } | 78 | } |
79 | 79 | ||
80 | 80 | ||
81 | bool ZCameraIO::isOpen() const | 81 | bool ZCameraIO::isOpen() const |
82 | { | 82 | { |
83 | return _driver != -1; | 83 | return _driver != -1; |
84 | } | 84 | } |
85 | 85 | ||
86 | 86 | ||
87 | bool ZCameraIO::isShutterPressed() | 87 | bool ZCameraIO::isShutterPressed() |
88 | { | 88 | { |
89 | if ( _status[0] == 'S' ) | 89 | if ( _status[0] == 'S' ) |
90 | { | 90 | { |
91 | if ( !_pressed ) // wasn't pressed before, but is now! | 91 | if ( !_pressed ) // wasn't pressed before, but is now! |
92 | { | 92 | { |
93 | _pressed = true; | 93 | _pressed = true; |
94 | _timer->start(); | 94 | _timer->start(); |
95 | return true; | 95 | return true; |
96 | } | 96 | } |
97 | 97 | ||
98 | if ( _timer->elapsed() > 2000 ) // the press is pretty old now | 98 | if ( _timer->elapsed() > 2000 ) // the press is pretty old now |
99 | { | 99 | { |
100 | clearShutterLatch(); | 100 | clearShutterLatch(); |
101 | _status[0] = 's'; | 101 | _status[0] = 's'; |
102 | _pressed = false; | 102 | _pressed = false; |
103 | } | 103 | } |
104 | } | 104 | } |
105 | 105 | ||
106 | return false; | 106 | return false; |
107 | } | 107 | } |
108 | 108 | ||
109 | 109 | ||
110 | bool ZCameraIO::isFinderReversed() const | 110 | bool ZCameraIO::isFinderReversed() const |
111 | { | 111 | { |
112 | return _status[1] == 'M'; | 112 | return _status[1] == 'M'; |
113 | } | 113 | } |
114 | 114 | ||
115 | 115 | ||
116 | bool ZCameraIO::isCapturing() const | 116 | bool ZCameraIO::isCapturing() const |
117 | { | 117 | { |
118 | return _status[2] == 'C'; | 118 | return _status[2] == 'C'; |
119 | } | 119 | } |
120 | 120 | ||
121 | 121 | ||
122 | bool ZCameraIO::isAvailable() const | 122 | bool ZCameraIO::isAvailable() const |
123 | { | 123 | { |
124 | return _status[3] == 'A'; | 124 | return _status[3] == 'A'; |
125 | } | 125 | } |
126 | 126 | ||
127 | 127 | ||
128 | bool ZCameraIO::setCaptureFrame( int width, int height, int zoom, bool rot ) | 128 | bool ZCameraIO::setCaptureFrame( int width, int height, int zoom, bool rot ) |
129 | { | 129 | { |
130 | odebug << "setCaptureFrame( " << width << ", " << height << ", " << zoom << ", " << rot << " )" << oendl; | 130 | odebug << "setCaptureFrame( " << width << ", " << height << ", " << zoom << ", " << rot << " )" << oendl; |
131 | char b[100]; | 131 | char b[100]; |
132 | sprintf( b, "%c=%d,%d,%d,%d", rot ? 'R':'S', width, height, zoom, width*2 ); | 132 | sprintf( b, "%c=%d,%d,%d,%d", rot ? 'R':'S', width, height, zoom, width*2 ); |
133 | if ( write( b ) ) | 133 | if ( write( b ) ) |
134 | { | 134 | { |
135 | _width = width; | 135 | _width = width; |
136 | _height = height; | 136 | _height = height; |
137 | _zoom = zoom; | 137 | _zoom = zoom; |
138 | _rot = rot; | 138 | _rot = rot; |
139 | _readlen = 2 * _width * _height; // camera is fixed @ 16 bits per pixel | 139 | _readlen = 2 * _width * _height; // camera is fixed @ 16 bits per pixel |
140 | return true; | 140 | return true; |
141 | } | 141 | } |
142 | return false; | 142 | return false; |
143 | } | 143 | } |
144 | 144 | ||
145 | 145 | ||
146 | bool ZCameraIO::setZoom( int zoom ) | 146 | bool ZCameraIO::setZoom( int zoom ) |
147 | { | 147 | { |
148 | return setCaptureFrame( _width, _height, zoom*256, _rot ); | 148 | return setCaptureFrame( _width, _height, zoom*256, _rot ); |
149 | } | 149 | } |
150 | 150 | ||
151 | 151 | ||
152 | void ZCameraIO::setReadMode( int mode ) | 152 | void ZCameraIO::setReadMode( int mode ) |
153 | { | 153 | { |
154 | char b[10]; | 154 | char b[10]; |
155 | sprintf( b, "M=%d", mode ); | 155 | sprintf( b, "M=%d", mode ); |
156 | write( b, mode <= 9 ? 3 : 4 ); | 156 | write( b, mode <= 9 ? 3 : 4 ); |
157 | if ( mode & STATUS ) // STATUS bit is set | 157 | if ( mode & STATUS ) // STATUS bit is set |
158 | { | 158 | { |
159 | read( _status, 4 ); | 159 | read( _status, 4 ); |
160 | if ( isShutterPressed() ) | 160 | if ( isShutterPressed() ) |
161 | { | 161 | { |
162 | emit shutterClicked(); | 162 | emit shutterClicked(); |
163 | } | 163 | } |
164 | } | 164 | } |
165 | } | 165 | } |
166 | 166 | ||
167 | 167 | ||
168 | void ZCameraIO::setFlip( int flip ) | 168 | void ZCameraIO::setFlip( int flip ) |
169 | { | 169 | { |
170 | _flip = flip; | 170 | _flip = flip; |
171 | } | 171 | } |
172 | 172 | ||
173 | 173 | ||
174 | void ZCameraIO::clearShutterLatch() | 174 | void ZCameraIO::clearShutterLatch() |
175 | { | 175 | { |
176 | write( "B", 1 ); | 176 | write( "B", 1 ); |
177 | } | 177 | } |
178 | 178 | ||
179 | 179 | ||
180 | bool ZCameraIO::read( char* b, int len ) | 180 | bool ZCameraIO::read( char* b, int len ) |
181 | { | 181 | { |
182 | #ifndef NO_TIMING | 182 | #ifndef NO_TIMING |
183 | QTime t; | 183 | QTime t; |
184 | t.start(); | 184 | t.start(); |
185 | #endif | 185 | #endif |
186 | int rlen = ::read( _driver, b, len ); | 186 | int rlen = ::read( _driver, b, len ); |
187 | #ifndef NO_TIMING | 187 | #ifndef NO_TIMING |
188 | int time = t.elapsed(); | 188 | int time = t.elapsed(); |
189 | #else | 189 | #else |
190 | int time = -1; | 190 | int time = -1; |
191 | #endif | 191 | #endif |
192 | if ( rlen ) | 192 | if ( rlen ) |
193 | odebug << "read " << rlen << " ('" << b[0] << b[1] << b[2] << b[3] << "') [" << time << " ms] from driver." << oendl; | 193 | odebug << "read " << rlen << " ('" << b[0] << b[1] << b[2] << b[3] << "') [" << time << " ms] from driver." << oendl; |
194 | else | 194 | else |
195 | odebug << "read nothing from driver." << oendl; | 195 | odebug << "read nothing from driver." << oendl; |
196 | return rlen == len; | 196 | return rlen == len; |
197 | } | 197 | } |
198 | 198 | ||
199 | 199 | ||
200 | bool ZCameraIO::write( char* buf, int len ) | 200 | bool ZCameraIO::write( char* buf, int len ) |
201 | { | 201 | { |
202 | if ( !len ) | 202 | if ( !len ) |
203 | len = strlen( buf ); | 203 | len = strlen( buf ); |
204 | 204 | ||
205 | odebug << "writing '" << buf << "' to driver." << oendl; | 205 | odebug << "writing '" << buf << "' to driver." << oendl; |
206 | 206 | ||
207 | return ::write( _driver, buf, len ) == len; | 207 | return ::write( _driver, buf, len ) == len; |
208 | } | 208 | } |
209 | 209 | ||
210 | 210 | ||
211 | bool ZCameraIO::snapshot( QImage* image ) | 211 | bool ZCameraIO::snapshot( QImage* image ) |
212 | { | 212 | { |
213 | setReadMode( STATUS ); | 213 | setReadMode( STATUS ); |
214 | 214 | ||
215 | odebug << "finder reversed = " << isFinderReversed() << oendl; | 215 | odebug << "finder reversed = " << isFinderReversed() << oendl; |
216 | odebug << "rotation = " << _rot << oendl; | 216 | odebug << "rotation = " << _rot << oendl; |
217 | 217 | ||
218 | int readmode; | 218 | int readmode; |
219 | if ( _flip == -1 ) // AUTO | 219 | if ( _flip == -1 ) // AUTO |
220 | { | 220 | { |
221 | if ( _rot ) // Portrait | 221 | if ( _rot ) // Portrait |
222 | { | 222 | { |
223 | readmode = IMAGE | isFinderReversed() ? XFLIP | YFLIP : 0; | 223 | readmode = IMAGE | isFinderReversed() ? XFLIP | YFLIP : 0; |
224 | } | 224 | } |
225 | else // Landscape | 225 | else // Landscape |
226 | { | 226 | { |
227 | readmode = IMAGE | XFLIP | YFLIP; | 227 | readmode = IMAGE | XFLIP | YFLIP; |
228 | } | 228 | } |
229 | } | 229 | } |
230 | else // OVERRIDE | 230 | else // OVERRIDE |
231 | { | 231 | { |
232 | readmode = IMAGE | _flip; | 232 | readmode = IMAGE | _flip; |
233 | } | 233 | } |
234 | 234 | ||
235 | setReadMode( readmode ); | 235 | setReadMode( readmode ); |
236 | 236 | ||
237 | char buf[_readlen]; | 237 | char buf[_readlen]; |
238 | char* bp = buf; | 238 | char* bp = buf; |
239 | unsigned char* p; | 239 | unsigned char* p; |
240 | 240 | ||
241 | read( bp, _readlen ); | 241 | read( bp, _readlen ); |
242 | 242 | ||
243 | image->create( _width, _height, 16 ); | 243 | image->create( _width, _height, 16 ); |
244 | for ( int i = 0; i < _height; ++i ) | 244 | for ( int i = 0; i < _height; ++i ) |
245 | { | 245 | { |
246 | p = image->scanLine( i ); | 246 | p = image->scanLine( i ); |
247 | for ( int j = 0; j < _width; j++ ) | 247 | for ( int j = 0; j < _width; j++ ) |
248 | { | 248 | { |
249 | *p = *bp; | 249 | *p = *bp; |
250 | p++; | 250 | p++; |
251 | bp++; | 251 | bp++; |
252 | *p = *bp; | 252 | *p = *bp; |
253 | p++; | 253 | p++; |
254 | bp++; | 254 | bp++; |
255 | } | 255 | } |
256 | } | 256 | } |
257 | 257 | ||
258 | return true; | 258 | return true; |
259 | } | 259 | } |
260 | 260 | ||
261 | 261 | ||
262 | bool ZCameraIO::snapshot( unsigned char* buf ) | 262 | bool ZCameraIO::snapshot( unsigned char* buf ) |
263 | { | 263 | { |
264 | setReadMode( STATUS ); | 264 | setReadMode( STATUS ); |
265 | 265 | ||
266 | odebug << "finder reversed = " << isFinderReversed() << oendl; | 266 | odebug << "finder reversed = " << isFinderReversed() << oendl; |
267 | odebug << "rotation = " << _rot << oendl; | 267 | odebug << "rotation = " << _rot << oendl; |
268 | 268 | ||
269 | int readmode; | 269 | int readmode; |
270 | if ( _flip == -1 ) // AUTO | 270 | if ( _flip == -1 ) // AUTO |
271 | { | 271 | { |
272 | if ( _rot ) // Portrait | 272 | if ( _rot ) // Portrait |
273 | { | 273 | { |
274 | readmode = IMAGE | isFinderReversed() ? XFLIP | YFLIP : 0; | 274 | readmode = IMAGE | isFinderReversed() ? XFLIP | YFLIP : 0; |
275 | } | 275 | } |
276 | else // Landscape | 276 | else // Landscape |
277 | { | 277 | { |
278 | readmode = IMAGE | XFLIP | YFLIP; | 278 | readmode = IMAGE | XFLIP | YFLIP; |
279 | } | 279 | } |
280 | } | 280 | } |
281 | else // OVERRIDE | 281 | else // OVERRIDE |
282 | { | 282 | { |
283 | readmode = IMAGE | _flip; | 283 | readmode = IMAGE | _flip; |
284 | } | 284 | } |
285 | 285 | ||
286 | setReadMode( readmode ); | 286 | setReadMode( readmode ); |
287 | read( (char*) buf, _readlen ); | 287 | read( (char*) buf, _readlen ); |
288 | 288 | ||
289 | } | 289 | } |
290 | 290 | ||
291 | 291 | ||
292 | void ZCameraIO::captureFrame( int w, int h, int zoom, QImage* image ) | 292 | void ZCameraIO::captureFrame( int w, int h, int zoom, QImage* image ) |
293 | { | 293 | { |
294 | int pw = _width; | 294 | int pw = _width; |
295 | int ph = _height; | 295 | int ph = _height; |
296 | if ( _rot ) | 296 | setCaptureFrame( w, h, zoom*256, _rot ); |
297 | setCaptureFrame( h, w, zoom*256, true ); | ||
298 | else | ||
299 | setCaptureFrame( w, h, zoom*256, false ); | ||
300 | snapshot( image ); | 297 | snapshot( image ); |
301 | setCaptureFrame( pw, ph, _zoom, _rot ); | 298 | setCaptureFrame( pw, ph, _zoom, _rot ); |
302 | } | 299 | } |
303 | 300 | ||
304 | 301 | ||
305 | void ZCameraIO::captureFrame( int w, int h, int zoom, unsigned char* buf ) | 302 | void ZCameraIO::captureFrame( int w, int h, int zoom, unsigned char* buf ) |
306 | { | 303 | { |
307 | //FIXME: this is too slow | 304 | //FIXME: this is too slow |
308 | int pw = _width; | 305 | int pw = _width; |
309 | int ph = _height; | 306 | int ph = _height; |
310 | if ( _rot ) | 307 | setCaptureFrame( w, h, zoom*256, _rot ); |
311 | setCaptureFrame( h, w, zoom*256, true ); | ||
312 | else | ||
313 | setCaptureFrame( w, h, zoom*256, false ); | ||
314 | |||
315 | snapshot( buf ); | 308 | snapshot( buf ); |
316 | setCaptureFrame( pw, ph, _zoom, _rot ); | 309 | setCaptureFrame( pw, ph, _zoom, _rot ); |
317 | } | 310 | } |
318 | 311 | ||