- added a new math function double_round, useful for rounding a number to a number...
[blender.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
19 #include <windows.h>
20 #include <winbase.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <direct.h>
24
25 #define VF_STREAM_VIDEO         0x00000001
26 #define VF_STREAM_AUDIO         0x00000002
27 #define VF_OK                           0x00000000
28 #define VF_ERROR                        0x80004005
29
30 typedef struct {
31         DWORD   dwSize;
32         DWORD   dwAPIVersion;   
33         DWORD   dwVersion;      
34         DWORD   dwSupportStreamType;    
35         char    cPluginInfo[256];       
36         char    cFileType[256];         
37 } VF_PluginInfo,*LPVF_PluginInfo;
38
39 typedef DWORD   VF_FileHandle,*LPVF_FileHandle;
40
41 typedef struct {
42         DWORD   dwSize;                 
43         DWORD   dwHasStreams;           
44 } VF_FileInfo,*LPVF_FileInfo;
45
46 typedef struct {
47         DWORD   dwSize;                 
48         DWORD   dwLengthL;      
49         DWORD   dwLengthH;      
50         DWORD   dwRate;                 
51         DWORD   dwScale;                
52         DWORD   dwWidth;                
53         DWORD   dwHeight;               
54         DWORD   dwBitCount;             
55 } VF_StreamInfo_Video,*LPVF_StreamInfo_Video;
56
57 typedef struct {
58         DWORD   dwSize;                 
59         DWORD   dwLengthL;      
60         DWORD   dwLengthH;      
61         DWORD   dwRate;                 
62         DWORD   dwScale;                
63         DWORD   dwChannels;             
64         DWORD   dwBitsPerSample;        
65         DWORD   dwBlockAlign;           
66 } VF_StreamInfo_Audio,*LPVF_StreamInfo_Audio;
67
68 typedef struct {
69         DWORD   dwSize;                 
70         DWORD   dwFrameNumberL; 
71         DWORD   dwFrameNumberH; 
72         void    *lpData;                
73         long    lPitch;                 
74 } VF_ReadData_Video,*LPVF_ReadData_Video;
75
76 typedef struct {
77         DWORD   dwSize;                 
78         LONGLONG        dwSamplePos;    
79         DWORD   dwSampleCount;          
80         DWORD   dwReadedSampleCount;    
81         DWORD   dwBufSize;              
82         void    *lpBuf;                 
83 } VF_ReadData_Audio,*LPVF_ReadData_Audio;
84
85 typedef struct {
86         DWORD   dwSize;                 
87         HRESULT (__stdcall *OpenFile)( 
88                 char *lpFileName, LPVF_FileHandle lpFileHandle );
89         HRESULT (__stdcall *CloseFile)( VF_FileHandle hFileHandle );
90         HRESULT (__stdcall *GetFileInfo)( VF_FileHandle hFileHandle,
91                                          LPVF_FileInfo lpFileInfo );
92         HRESULT (__stdcall *GetStreamInfo)( VF_FileHandle hFileHandle,
93                                            DWORD dwStream,void *lpStreamInfo );
94         HRESULT (__stdcall *ReadData)( VF_FileHandle hFileHandle,
95                                       DWORD dwStream,void *lpData ); 
96 } VF_PluginFunc,*LPVF_PluginFunc;
97
98 __declspec(dllexport) HRESULT vfGetPluginInfo( 
99         LPVF_PluginInfo lpPluginInfo )
100 {
101         if (!lpPluginInfo || lpPluginInfo->dwSize != sizeof(VF_PluginInfo)) {
102                 return VF_ERROR;
103         }
104
105         lpPluginInfo->dwAPIVersion = 1;
106         lpPluginInfo->dwVersion = 1;
107         lpPluginInfo->dwSupportStreamType = VF_STREAM_VIDEO;
108         strcpy(lpPluginInfo->cPluginInfo, "Blender Frameserver");
109         strcpy(lpPluginInfo->cFileType, 
110                "Blender Frame-URL-File (*.blu)|*.blu");
111
112         return VF_OK;
113 }
114
115 static unsigned long getipaddress(const char * ipaddr)
116 {
117         struct hostent  *host;
118         unsigned long   ip;
119
120         if (((ip = inet_addr(ipaddr)) == INADDR_NONE)
121             && strcmp(ipaddr, "255.255.255.255") != 0) {
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                 } else {
161                         line++;
162                         maxlen--;
163                 }
164         }
165         return last_rval;
166 }
167
168 typedef struct conndesc_ {
169         struct sockaddr_in      addr;
170         int width;
171         int height;
172         int start;
173         int end;
174         int rate;
175         int ratescale;
176 } conndesc;
177
178
179
180 HRESULT __stdcall VF_OpenFileFunc_Blen( 
181         char *lpFileName, LPVF_FileHandle lpFileHandle )
182 {
183         conndesc * rval;
184         char * host;
185         char * p;
186         int port;
187         SOCKET s_in;
188         char buf[256];
189         struct sockaddr_in      addr;
190         FILE* fp;
191
192         p = lpFileName;
193         while (*p && *p != '.') p++;
194         if (*p) p++;
195         if (strcmp(p, "blu") != 0) {
196                 return VF_ERROR;
197         }
198
199         fp = fopen(lpFileName, "r");
200         if (!fp) {
201                 return VF_ERROR;
202         }
203         fgets(buf, 256, fp);
204         fclose(fp);
205
206         host = buf;
207         p = host;
208         while (*p && *p != ':') p++;
209         if (*p) p++;
210         p[-1] = 0;
211         port = atoi(p);
212         if (!port) {
213                 port = 8080;
214         }
215
216         addr.sin_family = AF_INET;
217         addr.sin_port = htons(port);
218         addr.sin_addr.s_addr = getipaddress(host);
219
220         s_in = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
221         if (s_in < 0) {
222                 return VF_ERROR;
223         }
224
225         if (connect(s_in, (struct sockaddr*) &addr,
226                     sizeof(addr)) < 0) {
227                 closesocket(s_in);
228                 return VF_ERROR;
229         }
230
231         rval = (conndesc*) malloc(sizeof(conndesc));
232
233         rval->addr = addr;
234
235         my_send(s_in, "GET /info.txt HTTP/1.0\n\n");
236
237         for (;;) {
238                 char * key;
239                 char * val;
240
241                 if (my_gets(s_in, buf, 250) <= 0) {
242                         break;
243                 }
244
245                 key = buf;
246                 val = buf;
247                 while (*val && *val != ' ') val++;
248                 if (*val) {
249                         *val = 0;
250                         val++;
251                         
252                         if (strcmp(key, "width") == 0) {
253                                 rval->width = atoi(val);
254                         } else if (strcmp(key, "height") == 0) {
255                                 rval->height = atoi(val);
256                         } else if (strcmp(key, "start") == 0) {
257                                 rval->start = atoi(val);
258                         } else if (strcmp(key, "end") == 0) {
259                                 rval->end = atoi(val);
260                         } else if (strcmp(key, "rate") == 0) {
261                                 rval->rate = atoi(val);
262                         } else if (strcmp(key, "ratescale") == 0) {
263                                 rval->ratescale = atoi(val);
264                         }
265                 }
266         }
267
268         closesocket(s_in);
269
270         *lpFileHandle = (VF_FileHandle) rval;
271
272         return VF_OK;
273 }
274
275 HRESULT __stdcall VF_CloseFileFunc_Blen( 
276         VF_FileHandle hFileHandle )
277 {
278         free((conndesc*) hFileHandle);
279
280         return VF_OK;
281 }
282
283 HRESULT __stdcall VF_GetFileInfoFunc_Blen( 
284         VF_FileHandle hFileHandle,
285         LPVF_FileInfo lpFileInfo )
286 {
287         conndesc * c = (conndesc*) hFileHandle;
288         if (c == 0) { 
289                 return VF_ERROR; 
290         }
291
292         if (lpFileInfo->dwSize != sizeof(VF_FileInfo)) {
293                 return VF_ERROR;
294         }
295         
296         lpFileInfo->dwHasStreams = VF_STREAM_VIDEO;
297
298         return VF_OK;
299 }
300
301 HRESULT __stdcall VF_GetStreamInfoFunc_Blen( 
302         VF_FileHandle hFileHandle,
303         DWORD dwStream,void *lpStreamInfo )
304 {
305         conndesc * c = (conndesc*) hFileHandle;
306
307         LPVF_StreamInfo_Video v = (LPVF_StreamInfo_Video) lpStreamInfo;
308
309         if (c == 0 || dwStream != VF_STREAM_VIDEO || v == 0) { 
310                 return VF_ERROR;
311         }
312
313         v->dwLengthL = c->end - c->start;
314         v->dwLengthH = 0;
315         v->dwScale = c->ratescale;
316         v->dwRate = c->rate;
317         v->dwWidth = c->width;
318         v->dwHeight = c->height;
319         v->dwBitCount = 24;
320
321         return VF_OK;
322 }
323
324 HRESULT __stdcall VF_ReadDataFunc_Blen( 
325         VF_FileHandle hFileHandle,
326         DWORD dwStream,void *lpData )
327 {
328         char req[256];
329         char buf[256];
330         SOCKET s_in;
331         int width;
332         int height;
333         int y;
334         int rval;
335         unsigned char * framebuf;
336
337         conndesc * c = (conndesc*) hFileHandle;
338         LPVF_ReadData_Video v = (LPVF_ReadData_Video) lpData;
339
340         if (c == 0 || dwStream != VF_STREAM_VIDEO || v == 0) { 
341                 return VF_ERROR;
342         }
343
344         s_in = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
345         if (s_in < 0) {
346                 return VF_ERROR;
347         }
348
349         if (connect(s_in, (struct sockaddr*) &c->addr,
350                     sizeof(c->addr)) < 0) {
351                 goto errout;
352         }
353
354         sprintf(req, "GET /images/ppm/%d.ppm HTTP/1.0\n\n",
355                 (int) (v->dwFrameNumberL) + c->start);
356
357         my_send(s_in, req);
358
359         do {
360                 if (my_gets(s_in, buf, 256) <= 0) {
361                         goto errout;
362                 }
363         } while (strcmp(buf, "P6\n") != 0);
364
365         do {
366                 rval = my_gets(s_in, buf, 256); 
367         } while ( (buf[0] == '#' || buf[0] == '\n') && rval >= 0);
368
369         if (sscanf(buf, "%d %d\n", &width, &height) != 2) {
370                 goto errout;
371         }
372
373         if (width != c->width || height != c->height) {
374                 goto errout;
375         }
376
377         my_gets(s_in, buf, 256); /* 255 */
378
379         framebuf = (unsigned char*) v->lpData;
380
381         for (y = 0; y < height; y++) {
382                 unsigned char * p = framebuf + v->lPitch * y;
383                 unsigned char * e = p + width * 3;
384
385                 my_recv(s_in, (char*) p, width * 3);
386                 while (p != e) {
387                         unsigned char tmp = p[2];
388                         p[2] = p[0];
389                         p[0] = tmp;
390
391                         p += 3;
392                 }
393         }
394         closesocket(s_in);
395         return VF_OK;
396  errout:
397         closesocket(s_in);
398         return VF_ERROR;
399 }
400
401 __declspec(dllexport) HRESULT vfGetPluginFunc( 
402         LPVF_PluginFunc lpPluginFunc )
403 {
404         if (!lpPluginFunc || lpPluginFunc->dwSize != sizeof(VF_PluginFunc)) {
405                 return VF_ERROR;
406         }
407
408         lpPluginFunc->OpenFile = VF_OpenFileFunc_Blen;
409         lpPluginFunc->CloseFile = VF_CloseFileFunc_Blen;
410         lpPluginFunc->GetFileInfo = VF_GetFileInfoFunc_Blen;
411         lpPluginFunc->GetStreamInfo = VF_GetStreamInfoFunc_Blen;
412         lpPluginFunc->ReadData = VF_ReadDataFunc_Blen;
413
414         return VF_OK;
415 }
416
417
418