style cleanup
[blender-staging.git] / release / windows / contrib / vfapi / vfapi-plugin.c
1 /*
2  * VFAPI-Plugin
3  *
4  * Copyright (c) 2006 Peter Schlaile
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  */
17
18 #include <windows.h>
19 #include <winbase.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <direct.h>
23
24 #define VF_STREAM_VIDEO         0x00000001
25 #define VF_STREAM_AUDIO         0x00000002
26 #define VF_OK                           0x00000000
27 #define VF_ERROR                        0x80004005
28
29 typedef struct {
30         DWORD   dwSize;
31         DWORD   dwAPIVersion;   
32         DWORD   dwVersion;      
33         DWORD   dwSupportStreamType;    
34         char    cPluginInfo[256];       
35         char    cFileType[256];         
36 } VF_PluginInfo,*LPVF_PluginInfo;
37
38 typedef DWORD   VF_FileHandle,*LPVF_FileHandle;
39
40 typedef struct {
41         DWORD   dwSize;                 
42         DWORD   dwHasStreams;           
43 } VF_FileInfo,*LPVF_FileInfo;
44
45 typedef struct {
46         DWORD   dwSize;                 
47         DWORD   dwLengthL;      
48         DWORD   dwLengthH;      
49         DWORD   dwRate;                 
50         DWORD   dwScale;                
51         DWORD   dwWidth;                
52         DWORD   dwHeight;               
53         DWORD   dwBitCount;             
54 } VF_StreamInfo_Video,*LPVF_StreamInfo_Video;
55
56 typedef struct {
57         DWORD   dwSize;                 
58         DWORD   dwLengthL;      
59         DWORD   dwLengthH;      
60         DWORD   dwRate;                 
61         DWORD   dwScale;                
62         DWORD   dwChannels;             
63         DWORD   dwBitsPerSample;        
64         DWORD   dwBlockAlign;           
65 } VF_StreamInfo_Audio,*LPVF_StreamInfo_Audio;
66
67 typedef struct {
68         DWORD   dwSize;                 
69         DWORD   dwFrameNumberL; 
70         DWORD   dwFrameNumberH; 
71         void    *lpData;                
72         long    lPitch;                 
73 } VF_ReadData_Video,*LPVF_ReadData_Video;
74
75 typedef struct {
76         DWORD   dwSize;                 
77         LONGLONG        dwSamplePos;    
78         DWORD   dwSampleCount;          
79         DWORD   dwReadedSampleCount;    
80         DWORD   dwBufSize;              
81         void    *lpBuf;                 
82 } VF_ReadData_Audio,*LPVF_ReadData_Audio;
83
84 typedef struct {
85         DWORD   dwSize;
86         HRESULT (__stdcall *OpenFile)(
87                 char *lpFileName, LPVF_FileHandle lpFileHandle );
88         HRESULT (__stdcall *CloseFile)( VF_FileHandle hFileHandle );
89         HRESULT (__stdcall *GetFileInfo)( VF_FileHandle hFileHandle,
90                                           LPVF_FileInfo lpFileInfo );
91         HRESULT (__stdcall *GetStreamInfo)( VF_FileHandle hFileHandle,
92                                             DWORD dwStream,void *lpStreamInfo );
93         HRESULT (__stdcall *ReadData)( VF_FileHandle hFileHandle,
94                                        DWORD dwStream,void *lpData );
95 } VF_PluginFunc,*LPVF_PluginFunc;
96
97 __declspec(dllexport) HRESULT vfGetPluginInfo( 
98         LPVF_PluginInfo lpPluginInfo )
99 {
100         if (!lpPluginInfo || lpPluginInfo->dwSize != sizeof(VF_PluginInfo)) {
101                 return VF_ERROR;
102         }
103
104         lpPluginInfo->dwAPIVersion = 1;
105         lpPluginInfo->dwVersion = 1;
106         lpPluginInfo->dwSupportStreamType = VF_STREAM_VIDEO;
107         strcpy(lpPluginInfo->cPluginInfo, "Blender Frameserver");
108         strcpy(lpPluginInfo->cFileType, 
109                "Blender Frame-URL-File (*.blu)|*.blu");
110
111         return VF_OK;
112 }
113
114 static unsigned long getipaddress(const char * ipaddr)
115 {
116         struct hostent  *host;
117         unsigned long   ip;
118
119         if (((ip = inet_addr(ipaddr)) == INADDR_NONE) &&
120             strcmp(ipaddr, "255.255.255.255") != 0)
121         {
122                 if ((host = gethostbyname(ipaddr)) != NULL) {
123                         memcpy(&ip, host->h_addr, sizeof(ip));
124                 }
125         }
126
127         return (ip);
128 }
129
130 static void my_send(SOCKET sock, char *str)
131 {
132         send(sock, str, strlen(str), 0);
133 }
134
135 static int my_recv(SOCKET sock, char *line, int maxlen)
136 {
137         int got = 0;
138         int toget = maxlen;
139
140         while (toget > 0) {
141                 got = recv(sock, line, toget, 0);
142                 if (got <= 0) {
143                         return got;
144                 }
145                 toget -= got;
146                 line += got;
147         }
148         return maxlen;
149 }
150
151 static int my_gets(SOCKET sock, char *line, int maxlen)
152 {
153         int last_rval = 0;
154
155         while (((last_rval = my_recv(sock, line, 1)) == 1) && maxlen > 0) {
156                 if (*line == '\n') {
157                         line++;
158                         *line = 0;
159                         break;
160                 }
161                 else {
162                         line++;
163                         maxlen--;
164                 }
165         }
166         return last_rval;
167 }
168
169 typedef struct conndesc_ {
170         struct sockaddr_in      addr;
171         int width;
172         int height;
173         int start;
174         int end;
175         int rate;
176         int ratescale;
177 } conndesc;
178
179
180
181 HRESULT __stdcall VF_OpenFileFunc_Blen( 
182         char *lpFileName, LPVF_FileHandle lpFileHandle )
183 {
184         conndesc * rval;
185         char * host;
186         char * p;
187         int port;
188         SOCKET s_in;
189         char buf[256];
190         struct sockaddr_in      addr;
191         FILE *fp;
192
193         p = lpFileName;
194         while (*p && *p != '.') p++;
195         if (*p) p++;
196         if (strcmp(p, "blu") != 0) {
197                 return VF_ERROR;
198         }
199
200         fp = fopen(lpFileName, "r");
201         if (!fp) {
202                 return VF_ERROR;
203         }
204         fgets(buf, 256, fp);
205         fclose(fp);
206
207         host = buf;
208         p = host;
209         while (*p && *p != ':') p++;
210         if (*p) p++;
211         p[-1] = 0;
212         port = atoi(p);
213         if (!port) {
214                 port = 8080;
215         }
216
217         addr.sin_family = AF_INET;
218         addr.sin_port = htons(port);
219         addr.sin_addr.s_addr = getipaddress(host);
220
221         s_in = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
222         if (s_in < 0) {
223                 return VF_ERROR;
224         }
225
226         if (connect(s_in, (struct sockaddr*) &addr,
227                     sizeof(addr)) < 0) {
228                 closesocket(s_in);
229                 return VF_ERROR;
230         }
231
232         rval = (conndesc *) malloc(sizeof(conndesc));
233
234         rval->addr = addr;
235
236         my_send(s_in, "GET /info.txt HTTP/1.0\n\n");
237
238         for (;;) {
239                 char * key;
240                 char * val;
241
242                 if (my_gets(s_in, buf, 250) <= 0) {
243                         break;
244                 }
245
246                 key = buf;
247                 val = buf;
248                 while (*val && *val != ' ') val++;
249                 if (*val) {
250                         *val = 0;
251                         val++;
252                         
253                         if (strcmp(key, "width") == 0) {
254                                 rval->width = atoi(val);
255                         }
256                         else if (strcmp(key, "height") == 0) {
257                                 rval->height = atoi(val);
258                         }
259                         else if (strcmp(key, "start") == 0) {
260                                 rval->start = atoi(val);
261                         }
262                         else if (strcmp(key, "end") == 0) {
263                                 rval->end = atoi(val);
264                         }
265                         else if (strcmp(key, "rate") == 0) {
266                                 rval->rate = atoi(val);
267                         }
268                         else if (strcmp(key, "ratescale") == 0) {
269                                 rval->ratescale = atoi(val);
270                         }
271                 }
272         }
273
274         closesocket(s_in);
275
276         *lpFileHandle = (VF_FileHandle) rval;
277
278         return VF_OK;
279 }
280
281 HRESULT __stdcall VF_CloseFileFunc_Blen( 
282         VF_FileHandle hFileHandle )
283 {
284         free((conndesc *) hFileHandle);
285
286         return VF_OK;
287 }
288
289 HRESULT __stdcall VF_GetFileInfoFunc_Blen( 
290         VF_FileHandle hFileHandle,
291         LPVF_FileInfo lpFileInfo )
292 {
293         conndesc *c = (conndesc *) hFileHandle;
294         if (c == 0) { 
295                 return VF_ERROR; 
296         }
297
298         if (lpFileInfo->dwSize != sizeof(VF_FileInfo)) {
299                 return VF_ERROR;
300         }
301         
302         lpFileInfo->dwHasStreams = VF_STREAM_VIDEO;
303
304         return VF_OK;
305 }
306
307 HRESULT __stdcall VF_GetStreamInfoFunc_Blen( 
308         VF_FileHandle hFileHandle,
309         DWORD dwStream,void *lpStreamInfo )
310 {
311         conndesc * c = (conndesc*) hFileHandle;
312
313         LPVF_StreamInfo_Video v = (LPVF_StreamInfo_Video) lpStreamInfo;
314
315         if (c == 0 || dwStream != VF_STREAM_VIDEO || v == 0) { 
316                 return VF_ERROR;
317         }
318
319         v->dwLengthL = c->end - c->start;
320         v->dwLengthH = 0;
321         v->dwScale = c->ratescale;
322         v->dwRate = c->rate;
323         v->dwWidth = c->width;
324         v->dwHeight = c->height;
325         v->dwBitCount = 24;
326
327         return VF_OK;
328 }
329
330 HRESULT __stdcall VF_ReadDataFunc_Blen( 
331         VF_FileHandle hFileHandle,
332         DWORD dwStream,void *lpData )
333 {
334         char req[256];
335         char buf[256];
336         SOCKET s_in;
337         int width;
338         int height;
339         int y;
340         int rval;
341         unsigned char * framebuf;
342
343         conndesc * c = (conndesc*) hFileHandle;
344         LPVF_ReadData_Video v = (LPVF_ReadData_Video) lpData;
345
346         if (c == 0 || dwStream != VF_STREAM_VIDEO || v == 0) { 
347                 return VF_ERROR;
348         }
349
350         s_in = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
351         if (s_in < 0) {
352                 return VF_ERROR;
353         }
354
355         if (connect(s_in, (struct sockaddr*) &c->addr,
356                     sizeof(c->addr)) < 0) {
357                 goto errout;
358         }
359
360         sprintf(req, "GET /images/ppm/%d.ppm HTTP/1.0\n\n",
361                 (int) (v->dwFrameNumberL) + c->start);
362
363         my_send(s_in, req);
364
365         do {
366                 if (my_gets(s_in, buf, 256) <= 0) {
367                         goto errout;
368                 }
369         } while (strcmp(buf, "P6\n") != 0);
370
371         do {
372                 rval = my_gets(s_in, buf, 256);
373         } while ( (buf[0] == '#' || buf[0] == '\n') && rval >= 0);
374
375         if (sscanf(buf, "%d %d\n", &width, &height) != 2) {
376                 goto errout;
377         }
378
379         if (width != c->width || height != c->height) {
380                 goto errout;
381         }
382
383         my_gets(s_in, buf, 256); /* 255 */
384
385         framebuf = (unsigned char *) v->lpData;
386
387         for (y = 0; y < height; y++) {
388                 unsigned char *p = framebuf + v->lPitch * y;
389                 unsigned char *e = p + width * 3;
390
391                 my_recv(s_in, (char *)p, width * 3);
392                 while (p != e) {
393                         unsigned char tmp = p[2];
394                         p[2] = p[0];
395                         p[0] = tmp;
396
397                         p += 3;
398                 }
399         }
400         closesocket(s_in);
401         return VF_OK;
402  errout:
403         closesocket(s_in);
404         return VF_ERROR;
405 }
406
407 __declspec(dllexport) HRESULT vfGetPluginFunc( 
408         LPVF_PluginFunc lpPluginFunc )
409 {
410         if (!lpPluginFunc || lpPluginFunc->dwSize != sizeof(VF_PluginFunc)) {
411                 return VF_ERROR;
412         }
413
414         lpPluginFunc->OpenFile = VF_OpenFileFunc_Blen;
415         lpPluginFunc->CloseFile = VF_CloseFileFunc_Blen;
416         lpPluginFunc->GetFileInfo = VF_GetFileInfoFunc_Blen;
417         lpPluginFunc->GetStreamInfo = VF_GetStreamInfoFunc_Blen;
418         lpPluginFunc->ReadData = VF_ReadDataFunc_Blen;
419
420         return VF_OK;
421 }