home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 1999 November / SOTMC_Nov1999-Ultimate.iso / mac / REALbasic ƒ / Plugins / Plugins SDK / QTPlugin.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-11  |  23.7 KB  |  902 lines  |  [TEXT/CWIE]

  1. #include "rb_plugin.h"
  2. #include <Movies.h>
  3. #include <QuicktimeComponents.h>
  4. #include "QTEffect.h"
  5.  
  6. static double playerGetPosition(REALmoviePlayer instance, long param);
  7. static void playerSetPosition(REALmoviePlayer instance, long param, double value);
  8. static int movieTrackCount(REALobject instance, long param);
  9. static REALobject movieTrack(REALobject instance, int index);
  10. static REALobject newVideoTrack(REALobject movie, int width, int height, int frameRate);
  11. static double trackGetDuration(REALobject instance, long param);
  12. static unsigned long trackGetEnabled(REALobject instance, long param);
  13. static void trackSetEnabled(REALobject instance, long param, unsigned long value);
  14. static REALpicture effectSequenceImageGetter(REALobject instance, long param);
  15. static REALobject getQTSMPTEEffect(int wipeId);
  16. static REALobject getQTCrossFadeEffect(void);
  17. static void newQTEffectSequence(REALobject object, REALobject effect, REALpicture pic1, REALpicture pic2, int frames);
  18. static REALobject createMovie(REALfolderItem location);
  19. static REALobject openAsEditableMovie(REALfolderItem location);
  20. static void videoTrackAppendPicture(REALobject track, REALpicture pic);
  21. static int videoTrackSelectCompression(REALobject videoTrack);
  22. static void trackDestructor(REALobject track, void *garbage);
  23. static void videoTrackDestructor(REALobject track, void *garbage);
  24. static void qtEffectDestructor(REALobject object, void *crud);
  25. static void qtEffectSequenceDestructor(REALobject object, void *crud);
  26. static void editableMovieDestructor(REALobject instance, void *garbage);
  27.  
  28. static double moviePositionGetter(REALobject instance, long param);
  29. static void moviePositionSetter(REALobject instance, long param, double value);
  30. static double movieDurationGetter(REALobject instance, long param);
  31. static int movieEOFGetter(REALobject instance, long param);
  32.  
  33. static void trackFirstSample(REALobject track);
  34. static void trackNextSample(REALobject track);
  35. static void trackFirstSync(REALobject track);
  36. static void trackNextSync(REALobject track);
  37. static REALstring trackMediaType(REALobject track, long param);
  38.  
  39. static Boolean gQuicktime21Installed, gQuicktime30Installed;
  40.  
  41. REALproperty playerProperties[1] = {
  42.     { nil, "Position", "Double", 0, (REALproc) playerGetPosition, (REALproc) playerSetPosition },
  43. };
  44.  
  45. REALproperty movieProperties[] = {
  46.     { nil, "TrackCount", "Integer", 0, (REALproc) movieTrackCount },
  47.     { nil, "Position", "Double", 0, (REALproc) moviePositionGetter, (REALproc) moviePositionSetter },
  48.     { nil, "Duration", "Double", 0, (REALproc) movieDurationGetter },
  49.     { nil, "EOF", "Boolean", 0, (REALproc) movieEOFGetter },
  50. };
  51.  
  52. REALmethodDefinition movieMethods[] = {
  53.     { (REALproc) movieTrack, REALnoImplementation, "Track(index as integer) As QTTrack"},
  54.     { (REALproc) newVideoTrack, REALnoImplementation, "NewVideoTrack(width as integer, height as integer, timeScale as integer) As QTVideoTrack" },
  55. };
  56.  
  57. REALproperty trackProperties[] = {
  58.     { nil, "Duration", "Double", 0, (REALproc) trackGetDuration },
  59.     { nil, "Enabled", "Boolean", 0, (REALproc) trackGetEnabled, (REALproc) trackSetEnabled },
  60.     { nil, "MediaType", "String", 0, (REALproc) trackMediaType },
  61. };
  62.  
  63. REALproperty effectSequenceProperties[2] = {
  64.     { nil, "Image", "Picture", 0, (REALproc) effectSequenceImageGetter },
  65.     { nil, "Frame", "Integer", 0, REALstandardGetter, REALstandardSetter, FieldOffset(EffectSequenceData, currentFrame) },
  66. };
  67.  
  68. REALmethodDefinition GetQTSMPTEEffectMethod = 
  69.     { (REALproc) getQTSMPTEEffect, REALnoImplementation, "GetQTSMPTEEffect(Id as integer) As QTEffect" };
  70.  
  71. REALmethodDefinition GetQTCrossFadeEffectMethod = 
  72.     { (REALproc) getQTCrossFadeEffect, REALnoImplementation, "GetQTCrossFadeEffect As QTEffect" };
  73.  
  74. REALmethodDefinition effectSequenceMethods[1] = {
  75.     { (REALproc) newQTEffectSequence, REALnoImplementation, "QTEffectSequence(effect as QTEffect, image1 as Picture, image2 as Picture, frames as integer)" },
  76. };
  77.  
  78. REALmethodDefinition folderItemMethods[2] = {
  79.     { (REALproc) createMovie, REALnoImplementation, "CreateMovie As EditableMovie" },
  80.     { (REALproc) openAsEditableMovie, REALnoImplementation, "OpenEditableMovie As EditableMovie" },
  81. };
  82.  
  83. REALmethodDefinition trackMethods[] = {
  84.     { (REALproc) trackFirstSample, REALnoImplementation, "FindFirstSample" },
  85.     { (REALproc) trackNextSample, REALnoImplementation, "FindNextSample" },
  86.     { (REALproc) trackFirstSync, REALnoImplementation, "FindFirstKeyFrame" },
  87.     { (REALproc) trackNextSync, REALnoImplementation, "FindNextKeyFrame" },
  88. };
  89.  
  90. REALmethodDefinition videoTrackMethods[] = {
  91.     { (REALproc) videoTrackAppendPicture, REALnoImplementation, "AppendPicture(pic As Picture)"},
  92.     { (REALproc) videoTrackSelectCompression, REALnoImplementation, "SelectCompressionSettings As Boolean" },
  93. };
  94.  
  95. REALclassDefinition playerExtension = {
  96.     kCurrentREALControlVersion,
  97.     "MoviePlayer",
  98.     nil,
  99.     0,
  100.     0,
  101.     nil,
  102.     nil,
  103.     playerProperties,
  104.     1,
  105.     nil,
  106.     0,
  107.     nil,
  108.     0,
  109. };
  110.  
  111. struct EditableMovieData
  112. {
  113.     Movie aMovie;
  114.     short resRefNum, resId;
  115.     Boolean bDirty, bNew;
  116.     TimeValue currentTime;
  117. };
  118.  
  119. REALclassDefinition editableMovieClass = {
  120.     kCurrentREALControlVersion,
  121.     "EditableMovie",
  122.     nil,
  123.     sizeof(EditableMovieData),
  124.     0,
  125.     nil,
  126.     (REALproc) editableMovieDestructor,
  127.     movieProperties,
  128.     sizeof(movieProperties) / sizeof(REALproperty),
  129.     movieMethods,
  130.     sizeof(movieMethods) / sizeof(REALmethodDefinition),
  131.     nil,
  132.     0,
  133. };
  134.  
  135. REALclassDefinition folderItemExtension = {
  136.     kCurrentREALControlVersion,
  137.     "FolderItem",
  138.     nil,
  139.     0,
  140.     0,
  141.     nil,
  142.     nil,
  143.     nil,
  144.     0,
  145.     folderItemMethods,
  146.     sizeof(folderItemMethods) / sizeof(REALmethodDefinition),
  147.     nil,
  148.     0,
  149. };
  150.  
  151. struct TrackData
  152. {
  153.     Track theTrack;
  154.  
  155.     REALobject movie;
  156. };
  157.  
  158. struct VideoTrackData
  159. {
  160.     Boolean bEdits;
  161.     TimeValue oldDuration;
  162.  
  163.     Fixed frameRate;
  164.  
  165.     Boolean bCodecSelected;
  166.     short codecDepth;
  167.     CodecQ codecQuality;
  168.     CodecQ temporalQuality;
  169.     CodecType cType;
  170.     CompressorComponent codec;
  171.     int keyFrameRate;
  172.  
  173.     ComponentInstance standardCompressor;
  174.  
  175.     Boolean bCompressorPrepared;
  176.     long maxSize;
  177.     Handle bits;
  178.     GWorldPtr compressionPage;
  179.     ImageSequence seq;
  180.     ImageDescription **imageDescriptionH;
  181.  
  182.     Boolean bFirstFrame;
  183. };
  184.  
  185. REALclassDefinition trackClass = {
  186.     kCurrentREALControlVersion,
  187.     "QTTrack",
  188.     nil,
  189.     sizeof(TrackData),
  190.     0,
  191.     nil,
  192.     (REALproc) trackDestructor,
  193.     trackProperties,
  194.     sizeof(trackProperties) / sizeof(REALproperty),
  195.     nil,
  196.     0,
  197.     nil,
  198.     0,
  199. };
  200.  
  201. REALclassDefinition videoTrackClass = {
  202.     kCurrentREALControlVersion,
  203.     "QTVideoTrack",
  204.     "QTTrack",
  205.     sizeof(VideoTrackData),
  206.     0,
  207.     nil,
  208.     (REALproc) videoTrackDestructor,
  209.     nil,
  210.     0,
  211.     videoTrackMethods,
  212.     sizeof(videoTrackMethods) / sizeof(REALmethodDefinition),
  213.     nil,
  214.     0,
  215. };
  216.  
  217. REALclassDefinition qteffectClass = {
  218.     kCurrentREALControlVersion,
  219.     "QTEffect",
  220.     nil,
  221.     sizeof(EffectData),
  222.     0,
  223.     nil,
  224.     (REALproc) qtEffectDestructor,
  225.     nil,
  226.     0,
  227.     nil,
  228.     0,
  229.     nil,
  230.     0
  231. };
  232.  
  233. REALclassDefinition qteffectSequenceClass = {
  234.     kCurrentREALControlVersion,
  235.     "QTEffectSequence",
  236.     nil,
  237.     sizeof(EffectSequenceData),
  238.     0,
  239.     nil,
  240.     (REALproc) qtEffectSequenceDestructor,
  241.     effectSequenceProperties,
  242.     sizeof(effectSequenceProperties) / sizeof(REALproperty),
  243.     effectSequenceMethods,
  244.     sizeof(effectSequenceMethods) / sizeof(REALmethodDefinition),
  245.     nil,
  246.     0
  247. };
  248.  
  249. static double playerGetPosition(REALmoviePlayer instance, long param)
  250. {
  251.     TimeScale scale;
  252.     float f;
  253.  
  254.     scale = 1000;
  255.     f = MCGetCurrentTime(REALgetMoviePlayerController(instance), &scale);
  256.     f = f / scale;
  257.     return f;
  258. }
  259.  
  260. static void playerSetPosition(REALmoviePlayer instance, long param, double value)
  261. {
  262.     TimeRecord timeSpec;
  263.     Movie movie;
  264.     MovieController ctl = REALgetMoviePlayerController(instance);
  265.  
  266.     if (!ctl)
  267.         return;
  268.     movie = MCGetMovie(ctl);
  269.     if (!movie)
  270.         return;
  271.  
  272.     if (value < 0.0)
  273.         value = 0.0;
  274.     timeSpec.scale = GetMovieTimeScale(movie);
  275.     value = value * timeSpec.scale;
  276.     timeSpec.value.lo = value;
  277.     timeSpec.value.hi = 0;
  278.     timeSpec.base = GetMovieTimeBase(movie);
  279.  
  280.     MCDoAction(ctl, mcActionGoToTime, &timeSpec);
  281. }
  282.  
  283. static int movieTrackCount(REALobject instance, long param)
  284. {
  285.     ClassData(editableMovieClass, instance, EditableMovieData, data);
  286.  
  287.     return GetMovieTrackCount(data->aMovie);
  288. }
  289.  
  290. static REALobject movieTrack(REALobject instance, int index)
  291. {
  292.     ClassData(editableMovieClass, instance, EditableMovieData, mdata);
  293.     Track t = GetMovieIndTrack(mdata->aMovie, index);
  294.     REALobject rv;
  295.  
  296.     if (!t)
  297.         return nil;
  298.     rv = REALnewInstance("QTTrack");    
  299.     if (rv)
  300.     {
  301.         ClassData(trackClass, rv, TrackData, data);
  302.         data->theTrack = t;
  303.         data->movie = instance;
  304.         REALLockObject(data->movie);
  305.     }
  306.     return rv;
  307. }
  308.  
  309. static double trackGetDuration(REALobject instance, long param)
  310. {
  311.     ClassData(trackClass, instance, TrackData, data);
  312.  
  313.     double v = GetTrackDuration(data->theTrack);
  314.     v = v / GetMovieTimeScale(GetTrackMovie(data->theTrack));
  315.     return v;
  316. }
  317.  
  318. static unsigned long trackGetEnabled(REALobject instance, long param)
  319. {
  320.     ClassData(trackClass, instance, TrackData, data);
  321.  
  322.     if (GetTrackEnabled(data->theTrack))
  323.         return 1;
  324.     else
  325.         return 0;
  326. }
  327.  
  328. static void trackSetEnabled(REALobject instance, long param, unsigned long value)
  329. {
  330.     ClassData(trackClass, instance, TrackData, data);
  331.  
  332.     SetTrackEnabled(data->theTrack, value != 0);
  333. }
  334.  
  335. static REALpicture effectSequenceImageGetter(REALobject instance, long param)
  336. {
  337.     ClassData(qteffectSequenceClass, instance, EffectSequenceData, data);
  338.  
  339.     if (data->lastFrame != data->currentFrame)
  340.     {
  341.         BuildEffectSequenceFrame(data, data->currentFrame);
  342.         data->lastFrame = data->currentFrame;
  343.     }
  344.  
  345.     REALLockObject((REALobject) data->destPicture);
  346.     return data->destPicture;
  347. }
  348.  
  349. static REALobject getQTSMPTEEffect(int wipeId)
  350. {
  351.     REALobject rv;
  352.  
  353.     if (!gQuicktime30Installed)
  354.         return nil;
  355.  
  356.     if (!REALenterMovies())
  357.         return nil;
  358.  
  359.     rv = REALnewInstance("QTEffect");    
  360.     if (rv)
  361.     {
  362.         ClassData(qteffectClass, rv, EffectData, data);
  363.         BuildSMPTEEffect(data, wipeId);
  364.     }
  365.     return rv;
  366. }
  367.  
  368. static REALobject getQTCrossFadeEffect(void)
  369. {
  370.     REALobject rv;
  371.  
  372.     if (!gQuicktime30Installed)
  373.         return nil;
  374.  
  375.     if (!REALenterMovies())
  376.         return nil;
  377.  
  378.     rv = REALnewInstance("QTEffect");    
  379.     if (rv)
  380.     {
  381.         ClassData(qteffectClass, rv, EffectData, data);
  382.         BuildCrossFadeEffect(data);
  383.     }
  384.     return rv;
  385. }
  386.  
  387. static void newQTEffectSequence(REALobject object, REALobject effect, REALpicture pic1, REALpicture pic2, int frames)
  388. {
  389.     if (!gQuicktime30Installed)
  390.         return;
  391.  
  392.     if (!REALenterMovies())
  393.         return;
  394.     
  395.     if (effect)
  396.     {
  397.         ClassData(qteffectSequenceClass, object, EffectSequenceData, data);
  398.         ClassData(qteffectClass, effect, EffectData, effectData);
  399.         if (effectData->theEffectType)
  400.             BuildEffectSquence(data, effectData, pic1, pic2, frames);
  401.     }
  402. }
  403.  
  404. static void qtEffectDestructor(REALobject object, void *crud)
  405. {
  406.     ClassData(qteffectClass, object, EffectData, effectData);
  407.  
  408.     if (effectData->fEffectDescription)
  409.         QTDisposeAtomContainer(effectData->fEffectDescription);
  410. }
  411.  
  412. static void qtEffectSequenceDestructor(REALobject object, void *crud)
  413. {
  414.     ClassData(qteffectSequenceClass, object, EffectSequenceData, data);
  415.  
  416.     if (data->fEffectSequenceID != 0L)
  417.         CDSequenceEnd(data->fEffectSequenceID);
  418.  
  419.     if (data->fEffectDescription)
  420.         QTDisposeAtomContainer(data->fEffectDescription);
  421.     if (data->pic1)
  422.     {
  423.         REALUnlockPictureDescription(data->pic1);
  424.         REALUnlockObject((REALobject) data->pic1);
  425.     }
  426.     else if (data->fGW1)
  427.         DisposeGWorld(data->fGW1);
  428.     if (data->pic2)
  429.     {
  430.         REALUnlockPictureDescription(data->pic2);
  431.         REALUnlockObject((REALobject) data->pic2);
  432.     }
  433.     else if (data->fGW2)
  434.         DisposeGWorld(data->fGW2);
  435.  
  436.     if (data->destPicture)
  437.         REALUnlockObject((REALobject) data->destPicture);
  438.  
  439.     if (data->fSampleDescription)
  440.         DisposeHandle((Handle) data->fSampleDescription);
  441. }
  442.  
  443. static REALobject createMovie(REALfolderItem location)
  444. {
  445.     FSSpec spec;
  446.     short resRefNum;
  447.     Movie aMovie;
  448.     REALobject newMovie;
  449.  
  450.     if (!REALenterMovies())
  451.         return nil;
  452.  
  453.     if (!REALFSSpecFromFolderItem(&spec, location))
  454.         return nil;
  455.  
  456.     if (noErr != CreateMovieFile(&spec, 'TVOD', 0, createMovieFileDeleteCurFile | newMovieActive, &resRefNum, &aMovie))
  457.         return nil;
  458.  
  459.     newMovie = REALnewInstance("editableMovie");
  460.     ClassData(editableMovieClass, newMovie, EditableMovieData, data);
  461.     data->aMovie = aMovie;
  462.     data->resRefNum = resRefNum;
  463.     data->bDirty = true;
  464.     data->bNew = true;
  465.     return newMovie;
  466. }
  467.  
  468. static REALobject openAsEditableMovie(REALfolderItem location)
  469. {
  470.     FSSpec spec;
  471.     short resRefNum, movieResID;
  472.     Movie aMovie;
  473.     REALobject newMovie;
  474.     OSErr err;
  475.  
  476.     if (!REALenterMovies())
  477.         return nil;
  478.  
  479.     if (!REALFSSpecFromFolderItem(&spec, location))
  480.         return nil;
  481.  
  482.     if (noErr != OpenMovieFile(&spec, &resRefNum, fsRdPerm))
  483.         return nil;
  484.     err = NewMovieFromFile(&aMovie, resRefNum,
  485.                             &movieResID, nil, newMovieActive, nil);
  486.     if (noErr != err)
  487.         return nil;
  488.  
  489.     newMovie = REALnewInstance("editableMovie");
  490.     ClassData(editableMovieClass, newMovie, EditableMovieData, data);
  491.     data->aMovie = aMovie;
  492.     data->resRefNum = resRefNum;
  493.     data->resId = movieResID;
  494.     data->bDirty = true;
  495.     data->bNew = false;
  496.     return newMovie;
  497. }
  498.  
  499. static void editableMovieDestructor(REALobject instance, void *garbage)
  500. {
  501.     ClassData(editableMovieClass, instance, EditableMovieData, data);
  502.     short resId = 0;
  503.  
  504.     if (data->bNew)
  505.         AddMovieResource(data->aMovie, data->resRefNum, &resId, nil);
  506.     else if (data->bDirty)
  507.         UpdateMovieResource(data->aMovie, data->resRefNum, data->resId, nil);
  508.  
  509.     DisposeMovie(data->aMovie);
  510.     if (data->resRefNum)
  511.         CloseMovieFile(data->resRefNum);
  512. }
  513.  
  514. static double moviePositionGetter(REALobject instance, long param)
  515. {
  516.     ClassData(editableMovieClass, instance, EditableMovieData, data);
  517.     double v = data->currentTime / GetMovieTimeScale(data->aMovie);
  518.     
  519.     return v;
  520. }
  521.  
  522. static double movieDurationGetter(REALobject instance, long param)
  523. {
  524.     ClassData(editableMovieClass, instance, EditableMovieData, data);
  525.     double v = GetMovieDuration(data->aMovie) / GetMovieTimeScale(data->aMovie);
  526.     
  527.     return v;
  528. }
  529.  
  530. static int movieEOFGetter(REALobject instance, long param)
  531. {
  532.     ClassData(editableMovieClass, instance, EditableMovieData, data);
  533.     if (data->currentTime >= GetMovieDuration(data->aMovie))
  534.         return 1;
  535.     return 0;
  536. }
  537.  
  538. static void moviePositionSetter(REALobject instance, long param, double value)
  539. {
  540.     ClassData(editableMovieClass, instance, EditableMovieData, data);
  541.     long v = value * GetMovieTimeScale(data->aMovie);
  542.     if (v < 0)
  543.         v = 0;
  544.     else if (v > GetMovieDuration(data->aMovie))
  545.         v = GetMovieDuration(data->aMovie);
  546.     data->currentTime = v;
  547. }
  548.  
  549. static void trackFirstSample(REALobject track)
  550. {
  551.     ClassData(trackClass, track, TrackData, trackData);
  552.     ClassData(editableMovieClass, trackData->movie, EditableMovieData, movieData);
  553.     TimeValue theTime = GetMovieDuration(movieData->aMovie);
  554.  
  555.     GetTrackNextInterestingTime(trackData->theTrack, nextTimeMediaSample + nextTimeEdgeOK, 0, fixed1, &theTime, nil);
  556.     if (noErr != GetMoviesError())
  557.         movieData->currentTime = GetMovieDuration(movieData->aMovie);
  558.     else
  559.         movieData->currentTime = theTime;
  560. }
  561.  
  562. static void trackNextSample(REALobject track)
  563. {
  564.     ClassData(trackClass, track, TrackData, trackData);
  565.     ClassData(editableMovieClass, trackData->movie, EditableMovieData, movieData);
  566.     TimeValue theTime = GetMovieDuration(movieData->aMovie);
  567.  
  568.     if (gQuicktime21Installed)
  569.         GetTrackNextInterestingTime(trackData->theTrack, nextTimeStep, movieData->currentTime, fixed1, &theTime, nil);
  570.     else
  571.         GetTrackNextInterestingTime(trackData->theTrack, nextTimeMediaSample, movieData->currentTime, fixed1, &theTime, nil);
  572.     if (noErr != GetMoviesError())
  573.         movieData->currentTime = GetMovieDuration(movieData->aMovie);
  574.     else
  575.         movieData->currentTime = theTime;
  576. }
  577.  
  578. static void trackFirstSync(REALobject track)
  579. {
  580.     ClassData(trackClass, track, TrackData, trackData);
  581.     ClassData(editableMovieClass, trackData->movie, EditableMovieData, movieData);
  582.     TimeValue theTime = GetMovieDuration(movieData->aMovie);
  583.  
  584.     GetTrackNextInterestingTime(trackData->theTrack, nextTimeSyncSample + nextTimeEdgeOK, 0, fixed1, &theTime, nil);
  585.     if (noErr != GetMoviesError())
  586.         movieData->currentTime = GetMovieDuration(movieData->aMovie);
  587.     else
  588.         movieData->currentTime = theTime;
  589. }
  590.  
  591. static void trackNextSync(REALobject track)
  592. {
  593.     ClassData(trackClass, track, TrackData, trackData);
  594.     ClassData(editableMovieClass, trackData->movie, EditableMovieData, movieData);
  595.     TimeValue theTime = GetMovieDuration(movieData->aMovie);
  596.  
  597.     GetTrackNextInterestingTime(trackData->theTrack, nextTimeSyncSample, movieData->currentTime, fixed1, &theTime, nil);
  598.     if (noErr != GetMoviesError())
  599.         movieData->currentTime = GetMovieDuration(movieData->aMovie);
  600.     else
  601.         movieData->currentTime = theTime;
  602. }
  603.  
  604. static REALstring trackMediaType(REALobject track, long param)
  605. {
  606.     ClassData(trackClass, track, TrackData, trackData);
  607.     OSType mediaType;
  608.  
  609.     GetMediaHandlerDescription(GetTrackMedia(trackData->theTrack), &mediaType, nil, nil);
  610.     return REALBuildString((Ptr) &mediaType, 4);
  611. }
  612.  
  613. static REALobject newVideoTrack(REALobject instance, int width, int height, int frameRate)
  614. {
  615.     ClassData(editableMovieClass, instance, EditableMovieData, data);
  616.     Track aTrack = NewMovieTrack(data->aMovie, (long)width << 16, (long)height << 16, 0);
  617.     REALobject rv;
  618.  
  619.     if (!aTrack)
  620.         return nil;
  621.  
  622.     Media aMedia = NewTrackMedia(aTrack, VideoMediaType, frameRate, nil, (OSType)nil);
  623.  
  624.     if (!aMedia)
  625.         return nil;
  626.  
  627.     BeginMediaEdits(aMedia);
  628.  
  629.     rv = REALnewInstance("QTVideoTrack");
  630.     if (rv)
  631.     {
  632.         ClassData(trackClass, rv, TrackData, trackData);
  633.         ClassData(videoTrackClass, rv, VideoTrackData, data);
  634.         trackData->theTrack = aTrack;
  635.         trackData->movie = instance;
  636.         REALLockObject(trackData->movie);
  637.         data->bEdits = true;
  638.     }
  639.  
  640.     return rv;
  641. }
  642.  
  643. static void videoTrackAppendPicture(REALobject track, REALpicture pic)
  644. {
  645.     ClassData(trackClass, track, TrackData, trackData);
  646.     ClassData(videoTrackClass, track, VideoTrackData, data);
  647.     Rect r;
  648.     Fixed width, height;
  649.     long compressedFrameSize;
  650.     Media trackMedia = GetTrackMedia(trackData->theTrack);
  651.     CGrafPtr oldPort;
  652.     GDHandle oldDevice;
  653.  
  654.     if (!data->bEdits)
  655.     {
  656.         BeginMediaEdits(trackMedia);
  657.         data->bEdits = true;
  658.         data->oldDuration = GetMediaDuration(trackMedia);
  659.  
  660.         ClassData(editableMovieClass, trackData->movie, EditableMovieData, data);
  661.         data->bDirty = true;
  662.     }
  663.  
  664.     GetTrackDimensions(trackData->theTrack, &width, &height);
  665.     SetRect(&r, 0, 0, width >> 16, height >> 16);
  666.  
  667.     if (data->standardCompressor)
  668.     {
  669.         if (data->bFirstFrame)
  670.         {
  671.             SCSpatialSettings ss;
  672.             SCGetInfo(data->standardCompressor, scSpatialSettingsType, &ss);
  673.             if (ss.depth == 0)
  674.                 ss.depth = 16;
  675.             if (noErr != NewGWorld(&data->compressionPage, ss.depth, &r, nil, nil, 0))
  676.                 NewGWorld(&data->compressionPage, ss.depth, &r, nil, nil, useTempMem);
  677.         }
  678.     }
  679.     else
  680.     {
  681.         if (!data->bCodecSelected)
  682.         {
  683.             data->codecDepth = 16;
  684.             data->codecQuality = codecNormalQuality;
  685.             data->temporalQuality = 0;
  686.             data->cType = 'raw ';
  687.             data->codec = anyCodec;
  688.             data->keyFrameRate = 16;
  689.             data->bCodecSelected = true;
  690.         }
  691.  
  692.         if (!data->bCompressorPrepared)
  693.         {
  694.             if (noErr != NewGWorld(&data->compressionPage, data->codecDepth, &r, nil, nil, 0))
  695.                 NewGWorld(&data->compressionPage, data->codecDepth, &r, nil, nil, useTempMem);
  696.  
  697.             GetMaxCompressionSize(data->compressionPage->portPixMap, &r, data->codecDepth, data->codecQuality, data->cType, data->codec, &data->maxSize);
  698.             data->bCompressorPrepared = true;
  699.             data->bits = NewHandle(data->maxSize);
  700.             data->imageDescriptionH = (ImageDescription **)NewHandle(sizeof(ImageDescription));
  701.  
  702.             data->bFirstFrame = true;
  703.             data->bCompressorPrepared = true;
  704.         }
  705.     }
  706.  
  707.     LockPixels(GetGWorldPixMap(data->compressionPage));
  708.     GetGWorld(&oldPort, &oldDevice);
  709.     SetGWorld(data->compressionPage, nil);
  710.  
  711.     EraseRect(&r);
  712.     if (pic)
  713.         REALDrawPicturePrimitive(pic, &r, false);
  714.  
  715.     OSErr result;
  716.     Handle bits;
  717.  
  718.     if (data->standardCompressor)
  719.     {
  720.         short notSyncFlag = 0;
  721.  
  722.         if (data->bFirstFrame)
  723.         {
  724.             SCCompressSequenceBegin(data->standardCompressor, data->compressionPage->portPixMap, &r, &data->imageDescriptionH);
  725.             data->bFirstFrame = false;
  726.         }
  727.  
  728.         SCCompressSequenceFrame(data->standardCompressor, data->compressionPage->portPixMap, &r, &bits, &compressedFrameSize, ¬SyncFlag);
  729.     }
  730.     else
  731.     {
  732.         if (data->bFirstFrame)
  733.         {
  734.             result = CompressSequenceBegin(&data->seq, data->compressionPage->portPixMap, nil, &r, nil, data->codecDepth, data->cType, data->codec, data->codecQuality, data->temporalQuality, data->keyFrameRate, nil, codecFlagUpdatePreviousComp, data->imageDescriptionH);
  735.             data->bFirstFrame = false;
  736.         }
  737.  
  738.         HLock(data->bits);
  739.         Ptr compressBits = StripAddress(*data->bits);
  740.  
  741.         result = CompressSequenceFrame(data->seq, data->compressionPage->portPixMap, &r, codecFlagUpdatePreviousComp, compressBits, &compressedFrameSize, nil, nil);
  742.         HUnlock(data->bits);
  743.         bits = data->bits;
  744.     }
  745.  
  746.     SetGWorld(oldPort, oldDevice);
  747.  
  748.     UnlockPixels(GetGWorldPixMap(data->compressionPage));
  749.  
  750.     result = AddMediaSample(trackMedia, bits, 0L, compressedFrameSize, (TimeValue)1, (SampleDescriptionHandle)data->imageDescriptionH, 1L, 0, nil);
  751. }
  752.  
  753. static void shutdownCurrentVideoCompressor(VideoTrackData *data)
  754. {
  755.     if (data->standardCompressor)
  756.     {
  757.         if (!data->bFirstFrame)
  758.             SCCompressSequenceEnd(data->standardCompressor);
  759.         data->bFirstFrame = true;
  760.         if (data->compressionPage)
  761.         {
  762.             DisposeGWorld(data->compressionPage);
  763.             data->compressionPage = nil;
  764.         }
  765.     }
  766.     else
  767.     {
  768.         if (data->seq)
  769.         {
  770.             CDSequenceEnd(data->seq);
  771.             data->seq = 0;
  772.         }
  773.  
  774.         if (data->bCompressorPrepared)
  775.         {
  776.             DisposeHandle((Handle) data->imageDescriptionH);
  777.             DisposeHandle(data->bits);
  778.             DisposeGWorld(data->compressionPage);
  779.             data->bCompressorPrepared = false;
  780.         }
  781.     }
  782. }
  783.  
  784. static void videoTrackDestructor(REALobject track, void *garbage)
  785. {
  786.     ClassData(videoTrackClass, track, VideoTrackData, data);
  787.     ClassData(trackClass, track, TrackData, trackData);
  788.     Media trackMedia = GetTrackMedia(trackData->theTrack);
  789.  
  790.     shutdownCurrentVideoCompressor(data);
  791.  
  792.     if (data->standardCompressor)
  793.         CloseComponent(data->standardCompressor);
  794.  
  795.     if (data->bEdits)
  796.     {
  797.         TimeValue newDuration = GetMediaDuration(trackMedia);
  798.         if (newDuration > data->oldDuration)
  799.             InsertMediaIntoTrack(trackData->theTrack, -1, data->oldDuration, newDuration - data->oldDuration, 0x10000);
  800.         EndMediaEdits(trackMedia);
  801.     }
  802. }
  803.  
  804. static void trackDestructor(REALobject track, void *garbage)
  805. {
  806.     ClassData(trackClass, track, TrackData, data);
  807.  
  808.     REALUnlockObject(data->movie);
  809. }
  810.  
  811. static int videoTrackSelectCompression(REALobject videoTrack)
  812. {
  813.     ClassData(videoTrackClass, videoTrack, VideoTrackData, data);
  814.  
  815.     shutdownCurrentVideoCompressor(data);
  816.  
  817.     if (!data->standardCompressor)
  818.         data->standardCompressor = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType);
  819.     ComponentResult result;
  820.  
  821.     if (!data->standardCompressor)
  822.         return false;
  823.  
  824.     result = SCRequestSequenceSettings(data->standardCompressor);
  825.  
  826.     if (result < 0 || result == scUserCancelled)
  827.     {
  828.         CloseComponent(data->standardCompressor);
  829.         data->standardCompressor = nil;
  830.         return false;
  831.     }
  832.  
  833.     data->bFirstFrame = true;
  834.  
  835.     return true;
  836. }
  837.  
  838. /*
  839.     Boolean bCodecSelected;
  840.     short codecDepth;
  841.     CodecQ codecQuality;
  842.     CodecQ temporalQuality;
  843.     CodecType cType;
  844.     CompressorComponent codec;
  845.     int keyFrameRate;
  846.  
  847.     Boolean bCompressorPrepared;
  848.     long maxSize;
  849.     Handle bits;
  850.     GWorldPtr compressionPage;
  851.     ImageSequence seq;
  852.     ImageDescription **imageDescriptionH;
  853. */
  854. /*
  855. REALexport pluginExports[] = {
  856.     { nil, movieGetPosition },
  857.     { nil, movieSetPosition },
  858.     { nil, trackGetDuration },
  859.     { nil, movieTrackCount },
  860.     { nil, movieTrack },
  861.     { nil, trackGetEnabled },
  862.     { nil, trackSetEnabled },
  863.     { nil, effectSequenceImageGetter },
  864.     { nil, getQTSMPTEEffect },
  865.     { nil, newQTEffectSequence },
  866.     { nil, qtEffectDestructor },
  867.     { nil, qtEffectSequenceDestructor },
  868.     { nil, getQTCrossFadeEffect },
  869.     { nil, createMovie },
  870.     { nil, newVideoTrack },
  871.     { nil, videoTrackAppendPicture },
  872.     { nil, videoTrackDestructor },
  873.     { nil, trackDestructor },
  874.     { nil, videoTrackSelectCompression },
  875. };
  876.  
  877. short pluginExportCode = sizeof(pluginExports) / sizeof(REALexport);
  878. */
  879. void PluginEntry(void)
  880. {
  881.     long result;
  882.     OSErr error = Gestalt(gestaltQuickTime, &result);
  883.     if (error == noErr)
  884.     {
  885.         if (result >= 0x2100000)
  886.             gQuicktime21Installed = true;
  887.         if (result >= 0x3000000)
  888.             gQuicktime30Installed = true;
  889.     }
  890.  
  891.     REALRegisterClass(&qteffectClass);
  892.     REALRegisterClass(&qteffectSequenceClass);
  893.     REALRegisterClass(&trackClass);
  894.     REALRegisterClass(&videoTrackClass);
  895.     REALRegisterClass(&editableMovieClass);
  896.     REALRegisterClassExtension(&playerExtension);
  897.     REALRegisterClassExtension(&folderItemExtension);
  898.  
  899.     REALRegisterMethod(&GetQTSMPTEEffectMethod);
  900.     REALRegisterMethod(&GetQTCrossFadeEffectMethod);
  901. }
  902.