Panda3D
|
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 ©) : 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 ©) : 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 ©) { 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