Commit | Line | Data |
---|---|---|
72db9a20 | 1 | /* |
ae500130 | 2 | * Copyright 2002 Dmitry Timoshkov for CodeWeavers |
888eaae7 | 3 | * Copyright 2005 Maarten Lankhorst |
72db9a20 DT |
4 | * |
5 | * This library is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU Lesser General Public | |
7 | * License as published by the Free Software Foundation; either | |
8 | * version 2.1 of the License, or (at your option) any later version. | |
9 | * | |
10 | * This library is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * Lesser General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU Lesser General Public | |
16 | * License along with this library; if not, write to the Free Software | |
360a3f91 | 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
72db9a20 DT |
18 | */ |
19 | ||
888eaae7 | 20 | #include "config.h" |
49b7fdcf AJ |
21 | #include "wine/port.h" |
22 | ||
e37c6e18 | 23 | #include <stdarg.h> |
888eaae7 ML |
24 | #include <stdio.h> |
25 | #include <fcntl.h> | |
26 | #ifdef HAVE_SYS_IOCTL_H | |
27 | # include <sys/ioctl.h> | |
28 | #endif | |
29 | #ifdef HAVE_SYS_STAT_H | |
30 | # include <sys/stat.h> | |
31 | #endif | |
32 | #ifdef HAVE_SYS_ERRNO_H | |
33 | # include <sys/errno.h> | |
34 | #endif | |
35 | #ifdef HAVE_SYS_TIME_H | |
36 | # include <sys/time.h> | |
37 | #endif | |
38 | #ifdef HAVE_ASM_TYPES_H | |
39 | # include <asm/types.h> | |
40 | #endif | |
41 | #ifdef HAVE_LINUX_VIDEODEV_H | |
42 | # include <linux/videodev.h> | |
43 | #endif | |
44 | #ifdef HAVE_UNISTD_H | |
45 | # include <unistd.h> | |
46 | #endif | |
e37c6e18 AJ |
47 | |
48 | #include "windef.h" | |
49 | #include "winbase.h" | |
50 | #include "wingdi.h" | |
20c169e0 | 51 | #include "winuser.h" |
72db9a20 | 52 | #include "vfw.h" |
888eaae7 | 53 | #include "winnls.h" |
16377936 | 54 | #include "winternl.h" |
72db9a20 DT |
55 | #include "wine/debug.h" |
56 | ||
888eaae7 ML |
57 | #define CAP_DESC_MAX 32 |
58 | ||
72db9a20 DT |
59 | WINE_DEFAULT_DEBUG_CHANNEL(avicap); |
60 | ||
16377936 SL |
61 | |
62 | /*********************************************************************** | |
63 | * capCreateCaptureWindowW (AVICAP32.@) | |
64 | */ | |
65 | HWND VFWAPI capCreateCaptureWindowW(LPCWSTR lpszWindowName, DWORD dwStyle, INT x, | |
66 | INT y, INT nWidth, INT nHeight, HWND hWnd, | |
67 | INT nID) | |
68 | { | |
41dd56cb | 69 | FIXME("%s, %08x, %08x, %08x, %08x, %08x, %p, %08x\n", |
16377936 SL |
70 | debugstr_w(lpszWindowName), dwStyle, |
71 | x, y, nWidth, nHeight, hWnd, nID); | |
72 | return 0; | |
73 | } | |
74 | ||
75 | /*********************************************************************** | |
76 | * capCreateCaptureWindowA (AVICAP32.@) | |
77 | */ | |
78 | HWND VFWAPI capCreateCaptureWindowA(LPCSTR lpszWindowName, DWORD dwStyle, INT x, | |
79 | INT y, INT nWidth, INT nHeight, HWND hWnd, | |
80 | INT nID) | |
81 | { UNICODE_STRING nameW; | |
82 | HWND retW; | |
83 | ||
84 | if (lpszWindowName) RtlCreateUnicodeStringFromAsciiz(&nameW, lpszWindowName); | |
85 | else nameW.Buffer = NULL; | |
86 | ||
87 | retW = capCreateCaptureWindowW(nameW.Buffer, dwStyle, x, y, nWidth, nHeight, | |
88 | hWnd, nID); | |
89 | RtlFreeUnicodeString(&nameW); | |
90 | ||
91 | return retW; | |
92 | } | |
93 | ||
888eaae7 ML |
94 | #ifdef HAVE_LINUX_VIDEODEV_H |
95 | ||
96 | static int xioctl(int fd, int request, void * arg) | |
97 | { | |
98 | int r; | |
99 | ||
100 | do r = ioctl (fd, request, arg); | |
101 | while (-1 == r && EINTR == errno); | |
102 | ||
103 | return r; | |
104 | } | |
105 | ||
106 | static BOOL query_video_device(int devnum, char *name, int namesize, char *version, int versionsize) | |
107 | { | |
108 | int fd; | |
109 | char device[16]; | |
110 | struct stat st; | |
111 | struct video_capability capa; | |
112 | #ifdef HAVE_V4L2 | |
113 | struct v4l2_capability caps; | |
114 | #endif | |
115 | ||
116 | snprintf(device, sizeof(device), "/dev/video%i", devnum); | |
117 | ||
118 | if (stat (device, &st) == -1) { | |
119 | /* This is probably because the device does not exist */ | |
120 | WARN("%s: %s\n", device, strerror(errno)); | |
121 | return FALSE; | |
122 | } | |
123 | ||
124 | if (!S_ISCHR (st.st_mode)) { | |
125 | ERR("%s: Not a device\n", device); | |
126 | return FALSE; | |
127 | } | |
128 | ||
129 | fd = open(device, O_RDWR | O_NONBLOCK); | |
130 | if (fd == -1) { | |
131 | ERR("%s: Failed to open: %s\n", device, strerror(errno)); | |
132 | return FALSE; | |
133 | } | |
134 | ||
135 | #ifdef HAVE_V4L2 | |
136 | memset(&caps, 0, sizeof(caps)); | |
137 | if (xioctl(fd, VIDIOC_QUERYCAP, &caps) != -1) { | |
cbca5f22 AJ |
138 | lstrcpynA(name, (char *)caps.card, namesize); |
139 | snprintf(version, versionsize, "%s v%u.%u.%u", (char *)caps.driver, (caps.version >> 16) & 0xFF, | |
888eaae7 ML |
140 | (caps.version >> 8) & 0xFF, caps.version & 0xFF); |
141 | close(fd); | |
142 | return TRUE; | |
143 | } | |
144 | ||
145 | if (errno != EINVAL && errno != 515) | |
146 | WARN("%s: ioctl failed: %s -- Falling back to V4L\n", device, strerror(errno)); | |
147 | else WARN("%s: Not a V4L2 compatible device, trying V4l 1\n", device); | |
148 | #endif /* HAVE_V4L2 */ | |
149 | ||
150 | memset(&capa, 0, sizeof(capa)); | |
151 | if (xioctl(fd, VIDIOCGCAP, &capa) == -1) { | |
152 | /* errno 515 is used by some webcam drivers for unknown IOICTL command */ | |
153 | if (errno != EINVAL && errno != 515) | |
154 | ERR("%s: Querying failed: %s\n", device, strerror(errno)); | |
82babbee | 155 | else ERR("%s: Querying failed: Not a V4L compatible device\n", device); |
888eaae7 ML |
156 | close(fd); |
157 | return FALSE; | |
158 | } | |
159 | ||
160 | lstrcpynA(name, capa.name, namesize); | |
161 | lstrcpynA(version, device, versionsize); | |
162 | close(fd); | |
163 | return TRUE; | |
164 | } | |
165 | ||
166 | #else /* HAVE_LINUX_VIDEODEV_H */ | |
167 | ||
168 | static BOOL query_video_device(int devnum, char *name, int namesize, char *version, int versionsize) | |
169 | { | |
170 | ERR("Video 4 Linux support not enabled\n"); | |
171 | return FALSE; | |
172 | } | |
173 | ||
174 | #endif /* HAVE_LINUX_VIDEODEV_H */ | |
175 | ||
16377936 SL |
176 | /*********************************************************************** |
177 | * capGetDriverDescriptionA (AVICAP32.@) | |
178 | */ | |
72db9a20 | 179 | BOOL VFWAPI capGetDriverDescriptionA(WORD wDriverIndex, LPSTR lpszName, |
888eaae7 | 180 | INT cbName, LPSTR lpszVer, INT cbVer) |
72db9a20 | 181 | { |
03812357 | 182 | BOOL retval; |
888eaae7 ML |
183 | WCHAR devname[CAP_DESC_MAX], devver[CAP_DESC_MAX]; |
184 | TRACE("--> capGetDriverDescriptionW\n"); | |
185 | retval = capGetDriverDescriptionW(wDriverIndex, devname, CAP_DESC_MAX, devver, CAP_DESC_MAX); | |
186 | if (retval) { | |
187 | WideCharToMultiByte(CP_ACP, 0, devname, -1, lpszName, cbName, NULL, NULL); | |
188 | WideCharToMultiByte(CP_ACP, 0, devver, -1, lpszVer, cbVer, NULL, NULL); | |
189 | } | |
190 | return retval; | |
72db9a20 DT |
191 | } |
192 | ||
16377936 SL |
193 | /*********************************************************************** |
194 | * capGetDriverDescriptionW (AVICAP32.@) | |
195 | */ | |
72db9a20 | 196 | BOOL VFWAPI capGetDriverDescriptionW(WORD wDriverIndex, LPWSTR lpszName, |
888eaae7 | 197 | INT cbName, LPWSTR lpszVer, INT cbVer) |
72db9a20 | 198 | { |
888eaae7 ML |
199 | char devname[CAP_DESC_MAX], devver[CAP_DESC_MAX]; |
200 | ||
201 | if (!query_video_device(wDriverIndex, devname, CAP_DESC_MAX, devver, CAP_DESC_MAX)) return FALSE; | |
202 | ||
203 | MultiByteToWideChar(CP_UNIXCP, 0, devname, -1, lpszName, cbName); | |
204 | MultiByteToWideChar(CP_UNIXCP, 0, devver, -1, lpszVer, cbVer); | |
205 | TRACE("Version: %s - Name: %s\n", debugstr_w(lpszVer), debugstr_w(lpszName)); | |
206 | return TRUE; | |
72db9a20 | 207 | } |