1. --!parent
  2. --!encoding=utf-8
  3.  
  4. -- ************************************************************************
  5. -- Software: VideoSync
  6. -- Version:  0.1
  7. -- Date:     2016-04-25
  8. -- Author:   Valentin Schmidt
  9. --
  10. -- Requirements/Dependencies:
  11. -- - Xtra "AVMedia"
  12. --
  13. -- Loads and plays synced videos.
  14. -- Videos can optionally be synced to a master audio (otherwise pass VOID
  15. -- as parameter <audioSyncFile> to constructor).
  16. --
  17. -- ************************************************************************
  18.  
  19.  
  20. property _axList
  21. property _videosLoaded
  22. property _audio
  23.  
  24. property _cbReadyHandler
  25. property _cbReadyTarget
  26.  
  27. ----------------------------------------
  28. -- Constructor
  29. -- @param {list} videoList
  30. -- @param {string|VOID} audioSyncFile
  31. -- @param {symbol} cbReadyHandler
  32. -- @param {object} cbReadyTarget - optional, default = _movie
  33. --
  34. -- <videoList> is a list of propLists, with each propList having properties:
  35. -- - #filename: path to video file
  36. -- - #rect: rect of corresponding video player on the screen
  37. -- - #mask: windowMask of corresponding video player (optional, default=0)
  38. --
  39. -- <audioSyncFile> is the path to an audioFile used as master clock (pass VOID
  40. -- if not syncing to audio).
  41. --  
  42. -- <cbReadyHandler> (of object <cbReadyTarget>) is the callback that will be notified
  43. -- as soon as all videos (and master audio) are loaded and ready to be played.
  44. ----------------------------------------
  45. on new (me, videoList, audioSyncFile, cbReadyHandler, cbReadyTarget)
  46.   if voidP(cbReadyTarget) then cbReadyTarget=_movie
  47.  
  48.   me._cbReadyHandler = cbReadyHandler
  49.   me._cbReadyTarget = cbReadyTarget
  50.  
  51.   me._axList = []
  52.   me._videosLoaded = 0
  53.  
  54.   if stringP(audioSyncFile) then
  55.     me._audio = xtra("AVMedia").new()
  56.     me._audio.audioOpen(audioSyncFile)
  57.   end if
  58.  
  59.   repeat with videoProps in videoList
  60.     ax = xtra("AVMedia").new()
  61.    
  62.     ax.videoSetReadyStatusChangeCallback(#_videoReady, me)
  63.    
  64.     fn = videoProps[#filename]
  65.     rect = videoProps[#rect]
  66.     mask = videoProps[#mask]
  67.     if voidP(mask) then mask = 0
  68.    
  69.     ax.videoOpen(fn, rect, mask)
  70.    
  71.     if not voidP(me._audio) then
  72.       ax.videoSyncToAudio()
  73.     end if
  74.    
  75.     me._axList.add(ax)
  76.    
  77.   end repeat
  78.  
  79.   return me
  80. end
  81.  
  82. ----------------------------------------
  83. --
  84. ----------------------------------------
  85. on destroy (me)
  86.   --
  87. end
  88.  
  89. ----------------------------------------
  90. -- Starts synced playback
  91. ----------------------------------------
  92. on play (me)
  93.   repeat with v in me._axList
  94.     -- float rate, intOrVOID time, intOrVOID hostTime, *timescale
  95.     v.videoSetRate(1.0, VOID, 0)
  96.   end repeat
  97.   if not voidP(me._audio) then
  98.     me._audio.audioPlay()
  99.   end if
  100. end
  101.  
  102. ----------------------------------------
  103. -- CALLBACK
  104. ----------------------------------------
  105. on _videoReady (me)
  106.   me._videosLoaded = me._videosLoaded + 1
  107.   if (me._videosLoaded>=count(me._axList)) then
  108.     call(me._cbReadyHandler, me._cbReadyTarget) -- all videos are ready
  109.   end if
  110. end
  111.  
[raw code]