Panda3D

movieTexture.cxx

00001 // Filename: movieTexture.cxx
00002 // Created by: jyelon (01Aug2007)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "pandabase.h"
00016 
00017 #ifdef HAVE_AUDIO
00018 
00019 #include "movieVideo.h"
00020 #include "movieVideoCursor.h"
00021 #include "movieTexture.h"
00022 #include "clockObject.h"
00023 #include "config_gobj.h"
00024 #include "config_grutil.h"
00025 #include "bamCacheRecord.h"
00026 #include "bamReader.h"
00027 #include "math.h"
00028 #include "audioSound.h"
00029 
00030 TypeHandle MovieTexture::_type_handle;
00031 
00032 ////////////////////////////////////////////////////////////////////
00033 //     Function: MovieTexture::Constructor
00034 //       Access: Published
00035 //  Description: Creates a blank movie texture.  Movies must be 
00036 //               added using do_read_one or do_load_one.
00037 ////////////////////////////////////////////////////////////////////
00038 MovieTexture::
00039 MovieTexture(const string &name) : 
00040   Texture(name)
00041 {
00042 }
00043 
00044 ////////////////////////////////////////////////////////////////////
00045 //     Function: MovieTexture::Constructor
00046 //       Access: Published
00047 //  Description: Creates a texture playing the specified movie.
00048 ////////////////////////////////////////////////////////////////////
00049 MovieTexture::
00050 MovieTexture(PT(MovieVideo) video) : 
00051   Texture(video->get_name())
00052 {
00053   do_load_one(video->open(), NULL, 0, LoaderOptions());
00054 }
00055 
00056 ////////////////////////////////////////////////////////////////////
00057 //     Function: MovieTexture::CData::Constructor
00058 //       Access: public
00059 //  Description: xxx
00060 ////////////////////////////////////////////////////////////////////
00061 MovieTexture::CData::
00062 CData() :
00063   _video_width(1),
00064   _video_height(1),
00065   _video_length(1.0),
00066   _playing(false),
00067   _clock(0.0),
00068   _play_rate(1.0),
00069   _loop_count(1),
00070   _loops_total(1)
00071 {
00072 }
00073 
00074 ////////////////////////////////////////////////////////////////////
00075 //     Function: MovieTexture::CData::Copy Constructor
00076 //       Access: public
00077 //  Description: xxx
00078 ////////////////////////////////////////////////////////////////////
00079 MovieTexture::CData::
00080 CData(const CData &copy) :
00081   _pages(copy._pages),
00082   _video_width(copy._video_width),
00083   _video_height(copy._video_height),
00084   _video_length(copy._video_length),
00085   _playing(false),
00086   _clock(0.0),
00087   _play_rate(1.0),
00088   _loop_count(1),
00089   _loops_total(1)
00090 {
00091 }
00092 
00093 ////////////////////////////////////////////////////////////////////
00094 //     Function: MovieTexture::CData::make_copy
00095 //       Access: public
00096 //  Description: xxx
00097 ////////////////////////////////////////////////////////////////////
00098 CycleData *MovieTexture::CData::
00099 make_copy() const {
00100   return new CData(*this);
00101 }
00102 
00103 ////////////////////////////////////////////////////////////////////
00104 //     Function: MovieTexture::Copy Constructor
00105 //       Access: Protected
00106 //  Description: Use MovieTexture::make_copy() to make a duplicate copy of
00107 //               an existing MovieTexture.
00108 ////////////////////////////////////////////////////////////////////
00109 MovieTexture::
00110 MovieTexture(const MovieTexture &copy) : 
00111   Texture(copy)
00112 {
00113   nassertv(false);
00114 }
00115 
00116 ////////////////////////////////////////////////////////////////////
00117 //     Function: MovieTexture::Destructor
00118 //       Access: Published, Virtual
00119 //  Description: xxx
00120 ////////////////////////////////////////////////////////////////////
00121 MovieTexture::
00122 ~MovieTexture() {
00123   clear();
00124 }
00125 
00126 ////////////////////////////////////////////////////////////////////
00127 //     Function: MovieTexture::make_texture
00128 //       Access: Public, Static
00129 //  Description: A factory function to make a new MovieTexture, used
00130 //               to pass to the TexturePool.
00131 ////////////////////////////////////////////////////////////////////
00132 PT(Texture) MovieTexture::
00133 make_texture() {
00134   return new MovieTexture("");
00135 }
00136 
00137 ////////////////////////////////////////////////////////////////////
00138 //     Function: MovieTexture::VideoPage::Constructor
00139 //       Access: Private
00140 //  Description: Creates a completely blank video page.
00141 ////////////////////////////////////////////////////////////////////
00142 MovieTexture::VideoPage::
00143 VideoPage() :
00144   _color(0),
00145   _alpha(0)
00146 {
00147 }
00148 
00149 ////////////////////////////////////////////////////////////////////
00150 //     Function: MovieTexture::do_recalculate_image_properties
00151 //       Access: Protected
00152 //  Description: Resizes the texture, and adjusts the format,
00153 //               based on the source movies.  The resulting texture
00154 //               will be large enough to hold all the videos.
00155 //
00156 //               Assumes the lock is already held.
00157 ////////////////////////////////////////////////////////////////////
00158 void MovieTexture::
00159 do_recalculate_image_properties(CDWriter &cdata, const LoaderOptions &options) {
00160   int x_max = 1;
00161   int y_max = 1;
00162   bool alpha = false;
00163   double len = 0.0;
00164   
00165   for (int i=0; i<_z_size; i++) {
00166     MovieVideoCursor *t = cdata->_pages[i]._color;
00167     if (t) {
00168       if (t->size_x() > x_max) x_max = t->size_x();
00169       if (t->size_y() > y_max) y_max = t->size_y();
00170       if (t->length() > len) len = t->length();
00171       if (t->get_num_components() == 4) alpha=true;
00172     }
00173     t = cdata->_pages[i]._alpha;
00174     if (t) {
00175       if (t->size_x() > x_max) x_max = t->size_x();
00176       if (t->size_y() > y_max) y_max = t->size_y();
00177       if (t->length() > len) len = t->length();
00178       alpha = true;
00179     }
00180   }
00181 
00182   cdata->_video_width  = x_max;
00183   cdata->_video_height = y_max;
00184   cdata->_video_length = len;
00185   
00186   if (_texture_type == TT_cube_map) {
00187     // Texture must be square.
00188     if (x_max > y_max) y_max = x_max;
00189     if (y_max > x_max) x_max = y_max;
00190   }
00191 
00192   int x_size = x_max;
00193   int y_size = y_max;
00194   if (Texture::get_textures_power_2() != ATS_none) {
00195     x_max = up_to_power_2(x_max);
00196     y_max = up_to_power_2(y_max);
00197   }
00198   
00199   do_reconsider_image_properties(x_max, y_max, alpha?4:3, 
00200                                  T_unsigned_byte, cdata->_pages.size(),
00201                                  options);
00202   do_set_pad_size(x_max - x_size, y_max - y_size, 0);
00203 }
00204 
00205 ////////////////////////////////////////////////////////////////////
00206 //     Function: MovieTexture::do_read_one
00207 //       Access: Protected, Virtual
00208 //  Description: Combines a color and alpha video image from the two
00209 //               indicated filenames.  Both must be the same kind of
00210 //               video with similar properties.
00211 ////////////////////////////////////////////////////////////////////
00212 bool MovieTexture::
00213 do_read_one(const Filename &fullpath, const Filename &alpha_fullpath,
00214             int z, int n, int primary_file_num_channels, int alpha_file_channel,
00215             const LoaderOptions &options,
00216             bool header_only, BamCacheRecord *record) {
00217 
00218   nassertr(n == 0, false);
00219   nassertr(z >= 0 && z < _z_size, false);
00220   
00221   if (record != (BamCacheRecord *)NULL) {
00222     record->add_dependent_file(fullpath);
00223   }
00224 
00225   PT(MovieVideoCursor) color;
00226   PT(MovieVideoCursor) alpha;
00227   
00228   color = MovieVideo::get(fullpath)->open();
00229   if (color == 0) {
00230     return false;
00231   }
00232   if (!alpha_fullpath.empty()) {
00233     alpha = MovieVideo::get(alpha_fullpath)->open();
00234     if (alpha == 0) {
00235       return false;
00236     }
00237   }
00238   
00239   if (z == 0) {
00240     if (!has_name()) {
00241       set_name(fullpath.get_basename_wo_extension());
00242     }
00243     // Don't use has_filename() here, it will cause a deadlock
00244     if (_filename.empty()) {
00245       _filename = fullpath;
00246       _alpha_filename = alpha_fullpath;
00247     }
00248     
00249     _fullpath = fullpath;
00250     _alpha_fullpath = alpha_fullpath;
00251   }
00252 
00253   _primary_file_num_channels = primary_file_num_channels;
00254   _alpha_file_channel = alpha_file_channel;
00255   
00256   if (!do_load_one(color, alpha, z, options)) {
00257     return false;
00258   }
00259   
00260   set_loaded_from_image();
00261   set_loop(true);
00262   play();
00263   return true;
00264 }
00265 
00266 ////////////////////////////////////////////////////////////////////
00267 //     Function: MovieTexture::do_load_one
00268 //       Access: Protected, Virtual
00269 //  Description: Loads movie objects into the texture.
00270 ////////////////////////////////////////////////////////////////////
00271 bool MovieTexture::
00272 do_load_one(PT(MovieVideoCursor) color, PT(MovieVideoCursor) alpha, int z,
00273             const LoaderOptions &options) {
00274   
00275   {
00276     CDWriter cdata(_cycler);
00277     cdata->_pages.resize(z+1);
00278     cdata->_pages[z]._color = color;
00279     cdata->_pages[z]._alpha = alpha;
00280     do_recalculate_image_properties(cdata, options);
00281   }
00282   
00283   return true;
00284 }
00285 
00286 ////////////////////////////////////////////////////////////////////
00287 //     Function: MovieTexture::do_load_one
00288 //       Access: Protected, Virtual
00289 //  Description: Loading a static image into a MovieTexture is
00290 //               an error.
00291 ////////////////////////////////////////////////////////////////////
00292 bool MovieTexture::
00293 do_load_one(const PNMImage &pnmimage, const string &name, int z, int n,
00294             const LoaderOptions &options) {
00295   grutil_cat.error() << "You cannot load a static image into a MovieTexture\n";
00296   return false;
00297 }
00298 
00299 ////////////////////////////////////////////////////////////////////
00300 //     Function: MovieTexture::register_with_read_factory
00301 //       Access: Public, Static
00302 //  Description: Factory method to generate a Texture object
00303 ////////////////////////////////////////////////////////////////////
00304 void MovieTexture::
00305 register_with_read_factory() {
00306   // Since Texture is such a funny object that is reloaded from the
00307   // TexturePool each time, instead of actually being read fully from
00308   // the bam file, and since the VideoTexture and MovieTexture
00309   // classes don't really add any useful data to the bam record, we
00310   // don't need to define make_from_bam(), fillin(), or
00311   // write_datagram() in this class--we just inherit the same
00312   // functions from Texture.
00313 
00314   // We do, however, have to register this class with the BamReader,
00315   // to avoid warnings about creating the wrong kind of object from
00316   // the bam file.
00317   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00318 }
00319 
00320 ////////////////////////////////////////////////////////////////////
00321 //     Function: MovieTexture::has_cull_callback
00322 //       Access: Public, Virtual
00323 //  Description: Should be overridden by derived classes to return
00324 //               true if cull_callback() has been defined.  Otherwise,
00325 //               returns false to indicate cull_callback() does not
00326 //               need to be called for this node during the cull
00327 //               traversal.
00328 ////////////////////////////////////////////////////////////////////
00329 bool MovieTexture::
00330 has_cull_callback() const {
00331   return true;
00332 }
00333 
00334 ////////////////////////////////////////////////////////////////////
00335 //     Function: MovieTexture::cull_callback
00336 //       Access: Public, Virtual
00337 //  Description: This function will be called during the cull 
00338 //               traversal to update the MovieTexture.  This update
00339 //               consists of fetching the next video frame from the
00340 //               underlying MovieVideo sources.  The MovieVideo
00341 //               object belongs to the cull thread.
00342 ////////////////////////////////////////////////////////////////////
00343 bool MovieTexture::
00344 cull_callback(CullTraverser *, const CullTraverserData &) const {
00345   CDReader cdata(_cycler);
00346   
00347   double offset;
00348   if (cdata->_synchronize != 0) {
00349     offset = cdata->_synchronize->get_time();
00350   } else {
00351     // Calculate the cursor position modulo the length of the movie.
00352     double now = ClockObject::get_global_clock()->get_frame_time();
00353     double clock = cdata->_clock;
00354     if (cdata->_playing) {
00355       clock += now * cdata->_play_rate;
00356     }
00357     int true_loop_count = cdata->_loops_total;
00358     if (true_loop_count <= 0) {
00359       true_loop_count = 1000000000;
00360     }
00361     if (clock >= cdata->_video_length * true_loop_count) {
00362       offset = cdata->_video_length;
00363     } else {
00364       offset = fmod(clock, cdata->_video_length);
00365     }
00366   }
00367   
00368   for (int i=0; i<((int)(cdata->_pages.size())); i++) {
00369     MovieVideoCursor *color = cdata->_pages[i]._color;
00370     MovieVideoCursor *alpha = cdata->_pages[i]._alpha;
00371     if (color && alpha) {
00372       if ((offset >= color->next_start())||
00373           ((offset < color->last_start()) && (color->can_seek()))) {
00374         color->fetch_into_texture_rgb(offset, (MovieTexture*)this, i);
00375       }
00376       if ((offset >= alpha->next_start())||
00377           ((offset < alpha->last_start()) && (alpha->can_seek()))) {
00378         alpha->fetch_into_texture_alpha(offset, (MovieTexture*)this, i, _alpha_file_channel);
00379       }
00380     } else if (color) {
00381       if ((offset >= color->next_start())||
00382           ((offset < color->last_start()) && (color->can_seek()))) {
00383         color->fetch_into_texture(offset, (MovieTexture*)this, i);
00384       }
00385     }
00386   }
00387   return true;
00388 }
00389 
00390 ////////////////////////////////////////////////////////////////////
00391 //     Function: MovieTexture::get_keep_ram_image
00392 //       Access: Published, Virtual
00393 //  Description: A MovieTexture must always keep its ram image, 
00394 //               since there is no way to reload it from the 
00395 //               source MovieVideo.
00396 ////////////////////////////////////////////////////////////////////
00397 bool MovieTexture::
00398 get_keep_ram_image() const {
00399   // A MovieTexture should never dump its RAM image.
00400   return true;
00401 }
00402 
00403 ////////////////////////////////////////////////////////////////////
00404 //     Function: MovieTexture::do_make_copy
00405 //       Access: Protected, Virtual
00406 //  Description: Returns a new copy of the same Texture.  This copy,
00407 //               if applied to geometry, will be copied into texture
00408 //               as a separate texture from the original, so it will
00409 //               be duplicated in texture memory (and may be
00410 //               independently modified if desired).
00411 //               
00412 //               If the Texture is an MovieTexture, the resulting
00413 //               duplicate may be animated independently of the
00414 //               original.
00415 ////////////////////////////////////////////////////////////////////
00416 PT(Texture) MovieTexture::
00417 do_make_copy() {
00418   PT(MovieTexture) tex = new MovieTexture(get_name());
00419   tex->do_assign(*this);
00420 
00421   return tex.p();
00422 }
00423 
00424 ////////////////////////////////////////////////////////////////////
00425 //     Function: MovieTexture::do_assign
00426 //       Access: Protected
00427 //  Description: Implements make_copy().
00428 ////////////////////////////////////////////////////////////////////
00429 void MovieTexture::
00430 do_assign(const MovieTexture &copy) {
00431   Texture::do_assign(copy);
00432 
00433   // Since 'make_copy' can be a slow operation, 
00434   // I release the read lock before calling make_copy.
00435   
00436   pvector<MovieVideoCursor *> color;
00437   pvector<MovieVideoCursor *> alpha;
00438   {
00439     CDReader copy_cdata(copy._cycler);
00440     color.resize(copy_cdata->_pages.size());
00441     alpha.resize(copy_cdata->_pages.size());
00442     for (int i=0; i<(int)(color.size()); i++) {
00443       color[i] = copy_cdata->_pages[i]._color;
00444       alpha[i] = copy_cdata->_pages[i]._alpha;
00445     }
00446   }
00447   
00448   {
00449     CDWriter cdata(_cycler);
00450     cdata->_pages.resize(color.size());
00451     for (int i=0; i<(int)(color.size()); i++) {
00452       if (color[i]) {
00453         cdata->_pages[i]._color = color[i]->get_source()->open();
00454       }
00455       if (alpha[i]) {
00456         cdata->_pages[i]._alpha = alpha[i]->get_source()->open();
00457       }
00458     }
00459     do_recalculate_image_properties(cdata, LoaderOptions());
00460   }
00461 }
00462 
00463 ////////////////////////////////////////////////////////////////////
00464 //     Function: MovieTexture::reload_ram_image
00465 //       Access: Protected, Virtual
00466 //  Description: A MovieTexture must always keep its ram image, 
00467 //               since there is no way to reload it from the 
00468 //               source MovieVideo.
00469 ////////////////////////////////////////////////////////////////////
00470 void MovieTexture::
00471 do_reload_ram_image() {
00472   // A MovieTexture should never dump its RAM image.
00473   // Therefore, this is not needed.
00474 }
00475 
00476 ////////////////////////////////////////////////////////////////////
00477 //     Function: MovieTexture::restart
00478 //       Access: Published
00479 //  Description: Start playing the movie from where it was last
00480 //               paused.  Has no effect if the movie is not paused,
00481 //               or if the movie's cursor is already at the end.
00482 ////////////////////////////////////////////////////////////////////
00483 void MovieTexture::
00484 restart() {
00485   CDWriter cdata(_cycler);
00486   if (!cdata->_playing) {
00487     double now = ClockObject::get_global_clock()->get_frame_time();
00488     cdata->_clock = cdata->_clock - (now * cdata->_play_rate);
00489     cdata->_playing = true;
00490   }
00491 }
00492 
00493 ////////////////////////////////////////////////////////////////////
00494 //     Function: MovieTexture::stop
00495 //       Access: Published
00496 //  Description: Stops a currently playing or looping movie right
00497 //               where it is.  The movie's cursor remains frozen at
00498 //               the point where it was stopped.
00499 ////////////////////////////////////////////////////////////////////
00500 void MovieTexture::
00501 stop() {
00502   CDWriter cdata(_cycler);
00503   if (cdata->_playing) {
00504     double now = ClockObject::get_global_clock()->get_frame_time();
00505     cdata->_clock = cdata->_clock + (now * cdata->_play_rate);
00506     cdata->_playing = false;
00507   }
00508 }
00509 
00510 ////////////////////////////////////////////////////////////////////
00511 //     Function: MovieTexture::play
00512 //       Access: Published
00513 //  Description: Plays the movie from the beginning.
00514 ////////////////////////////////////////////////////////////////////
00515 void MovieTexture::
00516 play() {
00517   CDWriter cdata(_cycler);
00518   double now = ClockObject::get_global_clock()->get_frame_time();
00519   cdata->_clock = 0.0 - (now * cdata->_play_rate);
00520   cdata->_playing = true;
00521   cdata->_loops_total = cdata->_loop_count;
00522 }
00523 
00524 ////////////////////////////////////////////////////////////////////
00525 //     Function: MovieTexture::set_time
00526 //       Access: Published
00527 //  Description: Sets the movie's cursor.
00528 ////////////////////////////////////////////////////////////////////
00529 void MovieTexture::
00530 set_time(double t) {
00531   CDWriter cdata(_cycler);
00532   t = min(cdata->_video_length, max(0.0, t));
00533   if (cdata->_playing) {
00534     double now = ClockObject::get_global_clock()->get_frame_time();
00535     cdata->_clock = t - (now * cdata->_play_rate);
00536   } else {
00537     cdata->_clock = t;
00538   }
00539 }
00540 
00541 ////////////////////////////////////////////////////////////////////
00542 //     Function: MovieTexture::get_time
00543 //       Access: Published
00544 //  Description: Returns the current value of the movie's cursor.
00545 //               If the movie's loop count is greater than one, then
00546 //               its length is effectively multiplied for the
00547 //               purposes of this function.  In other words, 
00548 //               the return value will be in the range 0.0 
00549 //               to (length * loopcount).
00550 ////////////////////////////////////////////////////////////////////
00551 double MovieTexture::
00552 get_time() const {
00553   CDReader cdata(_cycler);
00554   double clock = cdata->_clock;
00555   if (cdata->_playing) {
00556     double now = ClockObject::get_global_clock()->get_frame_time();
00557     clock += (now * cdata->_play_rate);
00558   }
00559   if (clock >= cdata->_video_length * cdata->_loops_total) {
00560     return cdata->_video_length;
00561   } else {
00562     return fmod(clock, cdata->_video_length);
00563   }
00564 }
00565 
00566 ////////////////////////////////////////////////////////////////////
00567 //     Function: MovieTexture::set_loop
00568 //       Access: Published
00569 //  Description: If true, sets the movie's loop count to 1 billion.
00570 //               If false, sets the movie's loop count to one.
00571 ////////////////////////////////////////////////////////////////////
00572 void MovieTexture::
00573 set_loop(bool loop) {
00574   set_loop_count(loop ? 0:1);
00575 }
00576 
00577 ////////////////////////////////////////////////////////////////////
00578 //     Function: MovieTexture::get_loop
00579 //       Access: Published
00580 //  Description: Returns true if the movie's loop count is not equal
00581 //               to one.
00582 ////////////////////////////////////////////////////////////////////
00583 bool MovieTexture::
00584 get_loop() const {
00585   CDReader cdata(_cycler);
00586   return (cdata->_loop_count == 0);
00587 }
00588 
00589 ////////////////////////////////////////////////////////////////////
00590 //     Function: MovieTexture::set_loop_count
00591 //       Access: Published
00592 //  Description: Sets the movie's loop count to the desired value.
00593 ////////////////////////////////////////////////////////////////////
00594 void MovieTexture::
00595 set_loop_count(int n) {
00596   CDWriter cdata(_cycler);
00597   cdata->_loop_count = n;
00598 }
00599 
00600 ////////////////////////////////////////////////////////////////////
00601 //     Function: MovieTexture::get_loop_count
00602 //       Access: Published
00603 //  Description: Returns the movie's loop count.
00604 ////////////////////////////////////////////////////////////////////
00605 int MovieTexture::
00606 get_loop_count() const {
00607   CDReader cdata(_cycler);
00608   return cdata->_loop_count;
00609 }
00610 
00611 ////////////////////////////////////////////////////////////////////
00612 //     Function: MovieTexture::set_play_rate
00613 //       Access: Published
00614 //  Description: Sets the movie's play-rate.  This is the speed at
00615 //               which the movie's cursor advances.  The default is
00616 //               to advance 1.0 movie-seconds per real-time second.
00617 ////////////////////////////////////////////////////////////////////
00618 void MovieTexture::
00619 set_play_rate(double rate) {
00620   CDWriter cdata(_cycler);
00621   if (cdata->_playing) {
00622     double now = ClockObject::get_global_clock()->get_frame_time();
00623     cdata->_clock += (now * cdata->_play_rate);
00624     cdata->_play_rate = rate;
00625     cdata->_clock -= (now * cdata->_play_rate);
00626   } else {
00627     cdata->_play_rate = rate;
00628   }    
00629 }
00630 
00631 ////////////////////////////////////////////////////////////////////
00632 //     Function: MovieTexture::get_play_rate
00633 //       Access: Published
00634 //  Description: Gets the movie's play-rate.
00635 ////////////////////////////////////////////////////////////////////
00636 double MovieTexture::
00637 get_play_rate() const {
00638   CDReader cdata(_cycler);
00639   return cdata->_play_rate;
00640 }
00641 
00642 ////////////////////////////////////////////////////////////////////
00643 //     Function: MovieTexture::is_playing
00644 //       Access: Published
00645 //  Description: Returns true if the movie's cursor is advancing.
00646 ////////////////////////////////////////////////////////////////////
00647 bool MovieTexture::
00648 is_playing() const {
00649   CDReader cdata(_cycler);
00650   return cdata->_playing;
00651 }
00652 
00653 ////////////////////////////////////////////////////////////////////
00654 //     Function: MovieTexture::synchronize_to
00655 //       Access: Published
00656 //  Description: Synchronize this texture to a sound.  Typically,
00657 //               you would load the texture and the sound from the
00658 //               same AVI file.
00659 ////////////////////////////////////////////////////////////////////
00660 void MovieTexture::
00661 synchronize_to(AudioSound *s) {
00662   CDWriter cdata(_cycler);
00663   cdata->_synchronize = s;
00664 }
00665 
00666 ////////////////////////////////////////////////////////////////////
00667 //     Function: MovieTexture::unsynchronize
00668 //       Access: Published
00669 //  Description: Stop synchronizing with a sound.
00670 ////////////////////////////////////////////////////////////////////
00671 void MovieTexture::
00672 unsynchronize() {
00673   CDWriter cdata(_cycler);
00674   cdata->_synchronize = 0;
00675 }
00676 
00677 #endif  // HAVE_AUDIO
 All Classes Functions Variables Enumerations