source: trunk/lang/tcl/src/RpVideoTclInterface.cc @ 1925

Last change on this file since 1925 was 1925, checked in by dkearney, 14 years ago

updates for video widget code. adding uploadWord to filexfer to match the downloadWord. adding some images.

File size: 10.8 KB
Line 
1/*
2 * ----------------------------------------------------------------------
3 *  Rappture::MediaPlayer
4 *
5 *  This is an interface to the rappture movieplayer module.
6 *  It allows you to grab image frames from mpeg movies using ffmpeg.
7 * ======================================================================
8 *  AUTHOR:  Derrick Kearney, Purdue University
9 *  Copyright (c) 2005-2010  Purdue Research Foundation
10 *
11 *  See the file "license.terms" for information on usage and
12 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 * ======================================================================
14 */
15#include <tcl.h>
16#include <string.h>
17#include "RpVideo.h"
18
19extern "C" Tcl_AppInitProc RpVideo_Init;
20
21#include "RpOp.h"
22
23static Tcl_ObjCmdProc VideoCmd;
24static Tcl_ObjCmdProc VideoCallCmd;
25static Tcl_ObjCmdProc GetOp;
26static Tcl_ObjCmdProc NextOp;
27static Tcl_ObjCmdProc SeekOp;
28static Tcl_ObjCmdProc SizeOp;
29static Tcl_ObjCmdProc ReleaseOp;
30
31static Rp_OpSpec rpVideoOps[] = {
32    {"get",  1, (void *)GetOp, 3, 5, "[image ?width height?]|[position cur|end]|[framerate]",},
33    {"next",  1, (void *)NextOp, 2, 2, "",},
34    {"seek",  1, (void *)SeekOp, 3, 3, "+n|-n|n",},
35    {"size",  1, (void *)SizeOp, 2, 2, "",},
36    {"release", 1, (void *)ReleaseOp, 2, 2, "",},
37};
38
39static int nRpVideoOps = sizeof(rpVideoOps) / sizeof(Rp_OpSpec);
40
41/*
42 * ------------------------------------------------------------------------
43 *  RpVideo_Init()
44 *
45 *  Called in Rappture_Init() to initialize the commands defined
46 *  in this file.
47 * ------------------------------------------------------------------------
48 */
49int
50RpVideo_Init(Tcl_Interp *interp)
51{
52
53    Tcl_CreateObjCommand(interp, "::Rappture::Video",
54        VideoCmd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
55
56    return TCL_OK;
57}
58
59/*
60 * USAGE: Video <type> <data>
61 */
62static int
63VideoCmd(ClientData clientData, Tcl_Interp *interp, int objc,
64       Tcl_Obj* const *objv)
65{
66    char cmdName[64];
67    static int movieCount = 0;
68    const char *type = NULL;
69    const char *data = NULL;
70    int err = 0;
71
72    if (objc != 3) {
73        Tcl_AppendResult(interp, "wrong # args: should be \"",
74            "Video <type> <data>\"", (char*)NULL);
75        return TCL_ERROR;
76    }
77
78    type = Tcl_GetString(objv[1]);
79    data = Tcl_GetString(objv[2]);
80
81    // create a new command
82    VideoObj *movie = NULL;
83    movie = VideoInitCmd();
84    if (movie == NULL) {
85        Tcl_AppendResult(interp, "error while creating movie object", "\n",
86                         "VideoInitCmd(movie);", (char*)NULL);
87        return TCL_ERROR;
88    }
89
90    if ((*type == 'd') && (strcmp(type,"data") == 0)) {
91        Tcl_AppendResult(interp, "error while creating movie: type == data not supported",
92                         "\n", "VideoInitCmd(movie);", (char*)NULL);
93        return TCL_ERROR;
94    } else if ((*type == 'f') && (strcmp(type,"file") == 0)) {
95        err = VideoOpenFile(movie,data,"r");
96        if (err) {
97            Tcl_AppendResult(interp, "error while creating movie object: ",
98                             "\n", "VideoInitCmd(movie);", (char*)NULL);
99            return TCL_ERROR;
100        }
101    }
102
103    sprintf(cmdName,"::movieObj%d",movieCount);
104    movieCount++;
105
106    Tcl_CreateObjCommand(interp, cmdName, VideoCallCmd,
107        (ClientData)movie, (Tcl_CmdDeleteProc*)NULL);
108
109    Tcl_AppendResult(interp, cmdName, (char*)NULL);
110    return TCL_OK;
111}
112
113
114static int
115VideoCallCmd(ClientData clientData, Tcl_Interp *interp, int objc,
116           Tcl_Obj *const *objv)
117{
118    Tcl_ObjCmdProc *proc;
119
120    proc = (Tcl_ObjCmdProc *)Rp_GetOpFromObj(interp, nRpVideoOps, rpVideoOps,
121        RP_OP_ARG1, objc, objv, 0);
122
123    if (proc == NULL) {
124        return TCL_ERROR;
125    }
126    return (*proc)(clientData, interp, objc, objv);
127}
128
129/**********************************************************************/
130// FUNCTION: GetOp()
131/// Get info about the video
132/**
133 * Full function call:
134 *
135 * get position cur
136 * get position end
137 * get image ?width height?
138 * get framerate
139 *
140 */
141static int
142GetOp (ClientData clientData, Tcl_Interp *interp, int objc,
143         Tcl_Obj *const *objv)
144{
145    const char *cmd = Tcl_GetString(objv[1]);
146
147    /*
148     * Decode the first arg and figure out how we're supposed to advance.
149     */
150    if (objc > 5) {
151        Tcl_AppendResult(interp, "wrong # args: should be \"", cmd,
152            " [image width height]|[position cur|end]\"", (char*)NULL);
153        return TCL_ERROR;
154    }
155
156    const char *info = Tcl_GetString(objv[2]);
157    if ((*info == 'p') && (strcmp(info,"position") == 0)) {
158        if (objc != 4) {
159            Tcl_AppendResult(interp, "wrong # args: should be \"", cmd,
160                " position cur|end\"", (char*)NULL);
161            return TCL_ERROR;
162        }
163        const char *which = Tcl_GetString(objv[3]);
164        if ((*which == 'c') && (strcmp(which,"cur") == 0)) {
165            int pos = 0;
166            VideoGetPositionCur((VideoObj *)clientData,&pos);
167            Tcl_SetObjResult(interp, Tcl_NewIntObj(pos));
168        }
169        else if ((*which == 'e') && (strcmp(which,"end") == 0)) {
170            int pos = 0;
171            VideoGetPositionEnd((VideoObj *)clientData,&pos);
172            Tcl_SetObjResult(interp, Tcl_NewIntObj(pos));
173        }
174        else {
175            Tcl_AppendResult(interp, "unrecognized command: \"", which,
176                "\" should be one of cur,end ", (char*)NULL);
177            return TCL_ERROR;
178        }
179    }
180    else if ((*info == 'i') && (strcmp(info,"image") == 0)) {
181        if ((objc != 3) && (objc != 5)) {
182            Tcl_AppendResult(interp, "wrong # args: should be \"", cmd,
183                " image ?width height?\"", (char*)NULL);
184            return TCL_ERROR;
185        }
186
187        void *img = NULL;
188        int width = -1;
189        int height = -1;
190        int bufSize = 0;
191
192        if (objc == 5) {
193            Tcl_GetIntFromObj(interp, objv[3], &width);
194            Tcl_GetIntFromObj(interp, objv[4], &height);
195        }
196
197        VideoGetImage((VideoObj *)clientData, width, height, &img, &bufSize);
198
199        Tcl_SetByteArrayObj(Tcl_GetObjResult(interp),
200                            (const unsigned char*)img, bufSize);
201    }
202    else if ((*info == 'f') && (strcmp(info,"framerate") == 0)) {
203        if (objc != 3) {
204            Tcl_AppendResult(interp, "wrong # args: should be \"", cmd,
205                " framerate\"", (char*)NULL);
206            return TCL_ERROR;
207        }
208
209        double fr = 0;
210        int err = 0;
211
212        err = VideoGetFrameRate((VideoObj *)clientData, &fr);
213        if (err) {
214            Tcl_AppendResult(interp, "error while calculating framerate",
215                (char*)NULL);
216            return TCL_ERROR;
217        }
218        Tcl_SetObjResult(interp, Tcl_NewDoubleObj(fr));
219    }
220    else {
221        Tcl_AppendResult(interp, "unrecognized command \"", info, "\": should be \"", cmd,
222            " [image width height]|[position cur|end]|[framerate]\"", (char*)NULL);
223        return TCL_ERROR;
224    }
225
226
227    return TCL_OK;
228}
229
230
231/**********************************************************************/
232// FUNCTION: NextOp()
233/// Get the next frame from a video
234/**
235 * Return the next frame from a video as an image
236 * Full function call:
237 *
238 * next
239 *
240 */
241static int
242NextOp (ClientData clientData, Tcl_Interp *interp, int objc,
243         Tcl_Obj *const *objv)
244{
245
246//    void *img = NULL;
247//    int width = 960;
248//    int height = 540;
249//    int bufSize = 0;
250
251    int pos = 0;
252    VideoGoNext((VideoObj *)clientData);
253    VideoGetPositionCur((VideoObj *)clientData,&pos);
254    Tcl_SetObjResult(interp, Tcl_NewIntObj(pos));
255//    VideoGetImage((VideoObj *)clientData, width, height, &img, &bufSize);
256
257//    Tcl_SetByteArrayObj(Tcl_GetObjResult(interp),
258//                        (const unsigned char*)img, bufSize);
259
260    return TCL_OK;
261}
262
263/**********************************************************************/
264// FUNCTION: SeekOp()
265/// Get the next frame from a video
266/**
267 * Return the frame specified, or at the specified offset, as an image
268 * Full function call:
269 *
270 * seek +5
271 * seek -5
272 * seek 22
273 *
274 */
275static int
276SeekOp (ClientData clientData, Tcl_Interp *interp, int objc,
277         Tcl_Obj *const *objv)
278{
279
280//    void *img = NULL;
281//    int width = 960;
282//    int height = 540;
283//    int bufSize = 0;
284    const char *val_s = NULL;
285    int val = 0;
286    int pos = 0;
287
288    val_s = Tcl_GetString(objv[2]);
289    if (*val_s == '+') {
290        if (Tcl_GetInt(interp, val_s+1, &val) != TCL_OK) {
291            Tcl_AppendResult(interp, "bad value \"", val_s,
292                "\": should be next, +n, -n, or n", (char*)NULL);
293            return TCL_ERROR;
294        }
295        VideoGoPlusMinusN((VideoObj *)clientData, val);
296    }
297    else if (*val_s == '-') {
298        if (Tcl_GetInt(interp, val_s, &val) != TCL_OK) {
299            Tcl_AppendResult(interp, "bad value \"", val_s,
300                "\": should be next, +n, -n, or n", (char*)NULL);
301            return TCL_ERROR;
302        }
303        VideoGoPlusMinusN((VideoObj *)clientData, val);
304    }
305    else if (Tcl_GetInt(interp, val_s, &val) != TCL_OK) {
306        Tcl_AppendResult(interp, "bad value \"", val_s,
307            "\": should be next, +n, -n, or n", (char*)NULL);
308        return TCL_ERROR;
309    }
310    else {
311        int c = 0;
312        c = VideoGoToN((VideoObj *)clientData, val);
313        // printf("c = %d\tval = %d\n",c,val);
314    }
315
316//    VideoGetImage((VideoObj *)clientData, width, height, &img, &bufSize);
317
318//    if (img == NULL) {
319//        printf("img is null\n");
320//    }
321
322//    Tcl_SetByteArrayObj(Tcl_GetObjResult(interp),
323//                        (const unsigned char*)img, bufSize);
324
325    VideoGetPositionCur((VideoObj *)clientData,&pos);
326    Tcl_SetObjResult(interp, Tcl_NewIntObj(pos));
327
328    return TCL_OK;
329}
330
331/**********************************************************************/
332// FUNCTION: SizeOp()
333/// Get the size of the video
334/**
335 * Return the original size of the video frame
336 *
337 * Full function call:
338 *
339 * size
340 *
341 */
342static int
343SizeOp (ClientData clientData, Tcl_Interp *interp, int objc,
344         Tcl_Obj *const *objv)
345{
346
347    int width = 0;
348    int height = 0;
349    int err = 0;
350    Tcl_Obj *dim = NULL;
351
352
353    err = VideoSizeCmd((VideoObj *)clientData,&width,&height);
354
355    if (err) {
356        Tcl_AppendResult(interp, "error while calculating size of video",
357            (char*)NULL);
358        return TCL_ERROR;
359    }
360
361
362    dim = Tcl_NewListObj(0, NULL);
363    Tcl_ListObjAppendElement(interp, dim, Tcl_NewIntObj(width));
364    Tcl_ListObjAppendElement(interp, dim, Tcl_NewIntObj(height));
365    Tcl_SetObjResult(interp, dim);
366
367    return TCL_OK;
368}
369
370/**********************************************************************/
371// FUNCTION: ReleaseOp()
372/// Clean up memory from an open video in a movie player object
373/**
374 * Close all file handles and free allocated memory associated with an
375 * open video in a movie player object.
376 * Full function call:
377 *
378 * close
379 *
380 */
381static int
382ReleaseOp (ClientData clientData, Tcl_Interp *interp, int objc,
383         Tcl_Obj *const *objv)
384{
385    VideoClose((VideoObj *)clientData);
386
387    Tcl_ResetResult(interp);
388    return TCL_OK;
389}
Note: See TracBrowser for help on using the repository browser.