2
pygame - Python Game Library
3
Copyright (C) 2000-2001 Pete Shinners
5
This library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Library General Public
7
License as published by the Free Software Foundation; either
8
version 2 of the License, or (at your option) any later version.
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
Library General Public License for more details.
15
You should have received a copy of the GNU Library General Public
16
License along with this library; if not, write to the Free
17
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
* movie playback for pygame
36
#define PyMovie_AsSMPEG(x) (((PyMovieObject*)x)->movie)
39
staticforward PyTypeObject PyMovie_Type;
40
static PyObject* PyMovie_New(SMPEG*);
41
#define PyMovie_Check(x) ((x)->ob_type == &PyMovie_Type)
47
/* movie object methods */
49
/*DOC*/ static char doc_movie_play[] =
50
/*DOC*/ "Movie.play(loops=0) -> None\n"
51
/*DOC*/ "start movie playback\n"
53
/*DOC*/ "Starts playback of a movie. If audio or video is enabled\n"
54
/*DOC*/ "for the Movie, those outputs will be created. \n"
56
/*DOC*/ "You can specify an optional argument which will be the\n"
57
/*DOC*/ "number of times the movie loops while playing.\n"
60
static PyObject* movie_play(PyObject* self, PyObject* args)
62
SMPEG* movie = PyMovie_AsSMPEG(self);
64
if(!PyArg_ParseTuple(args, "|i", &loops))
66
Py_BEGIN_ALLOW_THREADS
67
SMPEG_loop(movie, loops);
75
/*DOC*/ static char doc_movie_stop[] =
76
/*DOC*/ "Movie.stop() -> None\n"
77
/*DOC*/ "stop movie playback\n"
79
/*DOC*/ "Stops playback of a movie. If sound and video are being\n"
80
/*DOC*/ "rendered, both will be stopped at their current position.\n"
83
static PyObject* movie_stop(PyObject* self, PyObject* args)
85
SMPEG* movie = PyMovie_AsSMPEG(self);
86
if(!PyArg_ParseTuple(args, ""))
88
Py_BEGIN_ALLOW_THREADS
95
/*DOC*/ static char doc_movie_pause[] =
96
/*DOC*/ "Movie.pause() -> None\n"
97
/*DOC*/ "pause/resume movie playback\n"
99
/*DOC*/ "This will temporarily stop playback of the movie. When called\n"
100
/*DOC*/ "a second time, playback will resume where it left off.\n"
103
static PyObject* movie_pause(PyObject* self, PyObject* args)
105
SMPEG* movie = PyMovie_AsSMPEG(self);
106
if(!PyArg_ParseTuple(args, ""))
108
Py_BEGIN_ALLOW_THREADS
115
/*DOC*/ static char doc_movie_rewind[] =
116
/*DOC*/ "Movie.rewind() -> None\n"
117
/*DOC*/ "set playback position to the beginning of the movie\n"
119
/*DOC*/ "Sets the movie playback position to the start of\n"
120
/*DOC*/ "the movie.\n"
123
static PyObject* movie_rewind(PyObject* self, PyObject* args)
125
SMPEG* movie = PyMovie_AsSMPEG(self);
126
if(!PyArg_ParseTuple(args, ""))
128
Py_BEGIN_ALLOW_THREADS
134
/*DOC*/ static char doc_movie_skip[] =
135
/*DOC*/ "Movie.skip(seconds) -> None\n"
136
/*DOC*/ "skip the movie playback position forward\n"
138
/*DOC*/ "Sets the movie playback position ahead by the given\n"
139
/*DOC*/ "amount of seconds. the seconds value is a floating\n"
140
/*DOC*/ "point value\n"
143
static PyObject* movie_skip(PyObject* self, PyObject* args)
145
SMPEG* movie = PyMovie_AsSMPEG(self);
147
if(!PyArg_ParseTuple(args, "f", &seconds))
149
Py_BEGIN_ALLOW_THREADS
150
SMPEG_skip(movie, seconds);
156
/*DOC*/ static char doc_movie_set_volume[] =
157
/*DOC*/ "Movie.set_volume(val) -> None\n"
158
/*DOC*/ "change volume for sound\n"
160
/*DOC*/ "Set the play volume for this Movie. The volume value is between\n"
161
/*DOC*/ "0.0 and 1.0.\n"
164
static PyObject* movie_set_volume(PyObject* self, PyObject* args)
166
SMPEG* movie = PyMovie_AsSMPEG(self);
169
if(!PyArg_ParseTuple(args, "f", &value))
172
Py_BEGIN_ALLOW_THREADS
173
volume = (int)(value * 100);
174
if(volume<0) volume = 0;
175
if(volume>100) volume = 100;
176
SMPEG_setvolume(movie, volume);
183
/*DOC*/ static char doc_movie_set_display[] =
184
/*DOC*/ "Movie.set_display(Surface, [pos]) -> None\n"
185
/*DOC*/ "change the video output surface\n"
187
/*DOC*/ "Set the output surface for the Movie's video. You may\n"
188
/*DOC*/ "also specify a position for the topleft corner of the\n"
189
/*DOC*/ "video. The position defaults to (0,0) if not given.\n"
191
/*DOC*/ "The position argument can optionally be a rectangle,\n"
192
/*DOC*/ "in which case the video will be stretched to fill the\n"
193
/*DOC*/ "rectangular area.\n"
195
/*DOC*/ "You may also pass None as the destination Surface, and\n"
196
/*DOC*/ "no video will be rendered for the movie playback.\n"
199
static PyObject* movie_set_display(PyObject* self, PyObject* args)
201
SMPEG* movie = PyMovie_AsSMPEG(self);
202
PyObject* surfobj, *posobj=NULL;
203
GAME_Rect *rect, temp;
205
if(!PyArg_ParseTuple(args, "O|O", &surfobj, &posobj))
208
Py_XDECREF(((PyMovieObject*)self)->surftarget);
209
((PyMovieObject*)self)->surftarget = NULL;
211
if(PySurface_Check(surfobj))
219
SMPEG_getinfo(movie, &info);
220
SMPEG_scaleXY(movie, info.width, info.height);
223
else if(TwoShortsFromObj(posobj, &x, &y))
226
SMPEG_getinfo(movie, &info);
227
SMPEG_scaleXY(movie, info.width, info.height);
229
else if((rect = GameRect_FromObject(posobj, &temp)))
233
SMPEG_scaleXY(movie, rect->w, rect->h);
236
return RAISE(PyExc_TypeError, "Invalid position argument");
238
surf = PySurface_AsSurface(surfobj);
240
SMPEG_getinfo(movie, &info);
241
SMPEG_enablevideo(movie, 1);
242
SMPEG_setdisplay(movie, surf, NULL, NULL);
243
SMPEG_move(movie, x, y);
247
Py_BEGIN_ALLOW_THREADS
248
SMPEG_enablevideo(movie, 0);
250
if(surfobj != Py_None)
251
return RAISE(PyExc_TypeError, "destination must be a Surface");
258
/*DOC*/ static char doc_movie_has_video[] =
259
/*DOC*/ "Movie.has_video() -> bool\n"
260
/*DOC*/ "query if movie stream has video\n"
262
/*DOC*/ "Returns a true value when the Movie object has a valid\n"
263
/*DOC*/ "video stream.\n"
267
static PyObject* movie_has_video(PyObject* self, PyObject* args)
269
SMPEG* movie = PyMovie_AsSMPEG(self);
272
if(!PyArg_ParseTuple(args, ""))
275
Py_BEGIN_ALLOW_THREADS
276
SMPEG_getinfo(movie, &info);
278
return PyInt_FromLong(info.has_video);
281
/*DOC*/ static char doc_movie_has_audio[] =
282
/*DOC*/ "Movie.has_audio() -> bool\n"
283
/*DOC*/ "query if movie stream has audio\n"
285
/*DOC*/ "Returns a true value when the Movie object has a valid\n"
286
/*DOC*/ "audio stream.\n"
289
static PyObject* movie_has_audio(PyObject* self, PyObject* args)
291
SMPEG* movie = PyMovie_AsSMPEG(self);
294
if(!PyArg_ParseTuple(args, ""))
297
Py_BEGIN_ALLOW_THREADS
298
SMPEG_getinfo(movie, &info);
300
return PyInt_FromLong(info.has_audio);
303
/*DOC*/ static char doc_movie_get_size[] =
304
/*DOC*/ "Movie.get_size() -> width,height\n"
305
/*DOC*/ "query the size of the video image\n"
307
/*DOC*/ "Returns the size of the video image the mpeg provides.\n"
310
static PyObject* movie_get_size(PyObject* self, PyObject* args)
312
SMPEG* movie = PyMovie_AsSMPEG(self);
315
if(!PyArg_ParseTuple(args, ""))
318
Py_BEGIN_ALLOW_THREADS
319
SMPEG_getinfo(movie, &info);
321
return Py_BuildValue("(ii)", info.width, info.height);
324
/*DOC*/ static char doc_movie_get_frame[] =
325
/*DOC*/ "Movie.get_frame() -> int\n"
326
/*DOC*/ "query the current frame in the movie\n"
328
/*DOC*/ "Gets the current video frame number for the movie.\n"
331
static PyObject* movie_get_frame(PyObject* self, PyObject* args)
333
SMPEG* movie = PyMovie_AsSMPEG(self);
336
if(!PyArg_ParseTuple(args, ""))
339
Py_BEGIN_ALLOW_THREADS
340
SMPEG_getinfo(movie, &info);
342
return PyInt_FromLong(info.current_frame);
345
/*DOC*/ static char doc_movie_get_time[] =
346
/*DOC*/ "Movie.get_time() -> float\n"
347
/*DOC*/ "query the current time in the movie\n"
349
/*DOC*/ "Gets the current time (in seconds) for the movie.\n"
350
/*DOC*/ "(currently not working? SMPEG always reports 0)\n"
353
static PyObject* movie_get_time(PyObject* self, PyObject* args)
355
SMPEG* movie = PyMovie_AsSMPEG(self);
358
if(!PyArg_ParseTuple(args, ""))
361
Py_BEGIN_ALLOW_THREADS
362
SMPEG_getinfo(movie, &info);
364
return PyFloat_FromDouble(info.current_time);
367
/*DOC*/ static char doc_movie_get_length[] =
368
/*DOC*/ "Movie.get_length() -> float\n"
369
/*DOC*/ "query playback time of the movie\n"
371
/*DOC*/ "Returns the total time (in seconds) of the movie.\n"
374
static PyObject* movie_get_length(PyObject* self, PyObject* args)
376
SMPEG* movie = PyMovie_AsSMPEG(self);
379
if(!PyArg_ParseTuple(args, ""))
382
Py_BEGIN_ALLOW_THREADS
383
SMPEG_getinfo(movie, &info);
385
return PyFloat_FromDouble(info.total_time);
388
/*DOC*/ static char doc_movie_get_busy[] =
389
/*DOC*/ "Movie.get_busy() -> bool\n"
390
/*DOC*/ "query the playback state\n"
392
/*DOC*/ "Returns true if the movie is currently playing.\n"
395
static PyObject* movie_get_busy(PyObject* self, PyObject* args)
397
SMPEG* movie = PyMovie_AsSMPEG(self);
399
if(!PyArg_ParseTuple(args, ""))
402
return PyInt_FromLong(SMPEG_status(movie) == SMPEG_PLAYING);
406
static PyMethodDef movie_builtins[] =
408
{ "play", movie_play, 1, doc_movie_play },
409
{ "stop", movie_stop, 1, doc_movie_stop },
410
{ "pause", movie_pause, 1, doc_movie_pause },
411
{ "rewind", movie_rewind, 1, doc_movie_rewind },
412
{ "skip", movie_skip, 1, doc_movie_skip },
414
{ "set_volume", movie_set_volume, 1, doc_movie_set_volume },
415
{ "set_display", movie_set_display, 1, doc_movie_set_display },
417
{ "has_video", movie_has_video, 1, doc_movie_has_video },
418
{ "has_audio", movie_has_audio, 1, doc_movie_has_audio },
419
{ "get_size", movie_get_size, 1, doc_movie_get_size },
420
{ "get_frame", movie_get_frame, 1, doc_movie_get_frame },
421
{ "get_time", movie_get_time, 1, doc_movie_get_time },
422
{ "get_length", movie_get_length, 1, doc_movie_get_length },
423
{ "get_busy", movie_get_busy, 1, doc_movie_get_busy },
429
/*sound object internals*/
431
static void movie_dealloc(PyObject* self)
433
SMPEG* movie = PyMovie_AsSMPEG(self);
434
Py_BEGIN_ALLOW_THREADS
437
Py_XDECREF(((PyMovieObject*)self)->surftarget);
438
Py_XDECREF(((PyMovieObject*)self)->filesource);
443
static PyObject* movie_getattr(PyObject* self, char* attrname)
445
return Py_FindMethod(movie_builtins, self, attrname);
449
/*DOC*/ static char doc_Movie_MODULE[] =
450
/*DOC*/ "The Movie object represents an opened MPEG file.\n"
451
/*DOC*/ "You control playback similar to a Sound object.\n"
453
/*DOC*/ "Movie objects have a target display Surface.\n"
454
/*DOC*/ "The movie is rendered to this Surface in a background\n"
455
/*DOC*/ "thread. If the Surface is the display surface, and\n"
456
/*DOC*/ "the system supports it, the movie will render into a\n"
457
/*DOC*/ "Hardware YUV overlay plane. If you don't set a display\n"
458
/*DOC*/ "Surface, it will default to the display Surface.\n"
460
/*DOC*/ "Movies are played back in background threads, so there\n"
461
/*DOC*/ "is very little management needed on the user end. Just\n"
462
/*DOC*/ "load the Movie, set the destination, and Movie.play()\n"
464
/*DOC*/ "Movies will only playback audio if the pygame.mixer\n"
465
/*DOC*/ "module is not initialized. It is easy to temporarily\n"
466
/*DOC*/ "call pygame.mixer.quit() to disable audio, then create\n"
467
/*DOC*/ "and play your movie. Finally calling pygame.mixer.init()\n"
468
/*DOC*/ "again when finished with the Movie.\n"
472
static PyTypeObject PyMovie_Type =
474
PyObject_HEAD_INIT(NULL)
477
sizeof(PyMovieObject),
486
NULL, /*as_sequence*/
488
(hashfunc)NULL, /*hash*/
489
(ternaryfunc)NULL, /*call*/
490
(reprfunc)NULL, /*str*/
492
doc_Movie_MODULE /* Documentation string */
498
/*movie module methods*/
501
/*DOC*/ static char doc_Movie[] =
502
/*DOC*/ "pygame.movie.Movie(file) -> Movie\n"
503
/*DOC*/ "load a new MPEG stream\n"
505
/*DOC*/ "Loads a new movie stream from a MPEG file. The file\n"
506
/*DOC*/ "argument is either a filename, or any python file-like object\n"
509
static PyObject* Movie(PyObject* self, PyObject* arg)
511
PyObject* file, *final, *filesource=NULL;
518
if(!PyArg_ParseTuple(arg, "O", &file))
521
if(!SDL_WasInit(SDL_INIT_AUDIO))
524
if(PyString_Check(file) || PyUnicode_Check(file))
526
if(!PyArg_ParseTuple(arg, "s", &name))
528
movie = SMPEG_new(name, &info, audioavail);
530
else if(PyFile_Check(file))
532
SDL_RWops *rw = SDL_RWFromFP(PyFile_AsFile(file), 0);
533
movie = SMPEG_new_rwops(rw, &info, audioavail);
540
if(!(rw = RWopsFromPythonThreaded(file)))
542
Py_BEGIN_ALLOW_THREADS
543
movie = SMPEG_new_rwops(rw, &info, audioavail);
548
return RAISE(PyExc_SDLError, "Cannot create Movie object");
550
error = SMPEG_error(movie);
553
/* while this would seem correct, it causes a crash, so don't delete */
554
/* SMPEG_delete(movie);*/
555
return RAISE(PyExc_SDLError, error);
558
Py_BEGIN_ALLOW_THREADS
559
SMPEG_enableaudio(movie, audioavail);
561
screen = SDL_GetVideoSurface();
563
SMPEG_setdisplay(movie, screen, NULL, NULL);
565
SMPEG_scaleXY(movie, info.width, info.height);
568
final = PyMovie_New(movie);
571
((PyMovieObject*)final)->filesource = filesource;
579
static PyMethodDef mixer_builtins[] =
581
{ "Movie", Movie, 1, doc_Movie },
588
static PyObject* PyMovie_New(SMPEG* movie)
590
PyMovieObject* movieobj;
593
return RAISE(PyExc_RuntimeError, "unable to create movie.");
595
movieobj = PyObject_NEW(PyMovieObject, &PyMovie_Type);
597
movieobj->movie = movie;
599
movieobj->surftarget = NULL;
600
movieobj->filesource = NULL;
602
return (PyObject*)movieobj;
607
/*DOC*/ static char doc_pygame_movie_MODULE[] =
608
/*DOC*/ "The movie module is an optional pygame module that\n"
609
/*DOC*/ "allows for decoding and playback of MPEG movie files.\n"
610
/*DOC*/ "The module only contains a single function, Movie()\n"
611
/*DOC*/ "which creates a new Movie object.\n"
613
/*DOC*/ "Movies are played back in background threads, so there\n"
614
/*DOC*/ "is very little management needed on the user end. Just\n"
615
/*DOC*/ "load the Movie, set the destination, and Movie.play()\n"
617
/*DOC*/ "Movies will only playback audio if the pygame.mixer\n"
618
/*DOC*/ "module is not initialized. It is easy to temporarily\n"
619
/*DOC*/ "call pygame.mixer.quit() to disable audio, then create\n"
620
/*DOC*/ "and play your movie. Finally calling pygame.mixer.init()\n"
621
/*DOC*/ "again when finished with the Movie.\n"
627
PyObject *module, *dict;
629
PyType_Init(PyMovie_Type);
631
/* create the module */
632
module = Py_InitModule3("movie", mixer_builtins, doc_pygame_movie_MODULE);
633
dict = PyModule_GetDict(module);
635
PyDict_SetItemString(dict, "MovieType", (PyObject *)&PyMovie_Type);
637
/*imported needed apis*/
638
import_pygame_base();
639
import_pygame_surface();
640
import_pygame_rwobject();
641
import_pygame_rect();