Hello. I would like to share my experience with a new Director feature (DVD),
so that other people can avoid some of the pitfalls that I encountered. Yes,
it contains a rant, but it also contains my solution and some example code
that I used. So I hope you find it helpful and forgive my cross-post (lingo-l,
dirgames-l.) I am not touting it as the best solution, but it's one that
worked for me.

I had to create a presentation that went live on Tuesday night. It was
primarily a slide show but on occasion I wanted to 'cut to video', taking over
the screen to show a few different titles from the DVD in the drive, then go
back to my Director content.

This was my first time using the DVD functionality. I found it rather
frustrating that I could not find any good examples of DVD playback Lingo, on
the MM site or on 3rd party sites. I'm not saying they don't exist, just that
I couldn't seem to find any; all I saw were review sites saying that MX04 has
DVD playback, and 'tutorial' sites which simply tell you to use the Event
Manager. So I read the help file and took a first stab at it. (This was before
I upgraded to 10.1 -- the help got a *little* better after that.)

* * * First attempt

I was able to use the 'play' command to show one of the titles on my DVD, but
trying to use the DVDeventNotification handler to 'catch' the 'title done
playing' event failed -- oh gee, wait, there wasn't one ;) -- so I tried to
use the 'rateChange', figuring the disc had spun down -- but it was a kludge
and did not work well for me. (I hadn't yet discovered the 'mediaStatus'
property.)

So I tried using the Event Manager. I was frustrated that the "DVD Event
Manager MIAW" was a .dcr -- what, if I can see how it works, I might learn
something? (Or, is it required to be a .dcr so it can be an Xtra, something
logical like that?) I was confused because I had already created a DVD cast
member, but I couldn't select it from the dropdown menu in the Event Manager,
I had to make a new one. Fine, whatever. I also had trouble playing video in
the MIAW and it was hard to mark my clips' in and out times accurately --
there was some kind of disjoin between the playback controls and the video.
(This stuff improved a little after the 10.1 patch but it still wasn't
perfect.) Anyway, I used the Event Manager, and it auto-generated a DVD cast
member with a member script, plus it inserted a generic DVD behavior script
which it attached to the sprite on the stage.

(I figure that the addition of the behaviors is probably why the Event Manager
didn't recognize my pre-existing DVD cast member. But still, that's lame.)

Once I had a look at the code it generated, it because a little more apparent
how things worked. I realized that the code uses timeouts and an internal
event list so it can pretty much operate independantly of the DVD itself,
'know' when a title, chapter, segment are over with, etc... and pretty much
issue one-way commands to the DVD except to check the known properties
(currentTime, title, chapter, chaptercount, duration, etc) to stay on-track.

I was expecting to use a 'push' model (e.g. the DVD will send me events when
things happen/change), but I should have known to use a 'pull' model -- keep
my own timing and ask things (pull down info) of the DVD when I needed to.

Using these scripts as a model, I modified the DVD castmember's script
containing the proplist with the 'settings' so I wouldn't have to use the DVD
Event Manager anymore. When I wanted to play a second clip later on, I found
it easier to just duplicate the castmember and change the castmember script
attached to it. I cleaned the script up, breaking up the one huge proplist
assignment statement into multiple lines so it'd be a bit more human-readable
and understandable.

* * * Preloading

When I 'cut to video' in my presentation, it took a long time -- much too long
-- to get the DVD playing on the screen because the disc had to spin up first.
So, in the spirit of 'preloading', I wondered if there was ANY way to tell the
DVD in the drive to 'spin up', and be 'paused' on the first second of the
title in question, but NOT show the DVD member yet on the stage, until I was
ready for it?

My solution was, to disable the fullscreen and autostart properties. Then, I
tried putting it on-stage, but scaled way down; I turned full-screen mode
off, then scaled the sprite to 4 px by 3 px, and stuck it in a corner. Thought
about positioning it off-stage, but whatever. (I wasn't sure whether the DVD's
direct-to-stage window had to be blitted 'to the screen' at some inherent
level before it would actually spin the disc up, etc.) Haven't tried yet
either, be my guest.  :)

Most of the content outside of the DVD segments were just cross-fading slides,
so I substituted the delay that spinning up the DVD would take for the last
'wait N seconds' tempo channel event , etc. (I dragged the start frame of the
DVD sprite to coincide with the frame where the 'wait 5 seconds' tempo channel
event would normally go.)

That way, when the playback head hit that frame, the DVD spun up, which took a
couple of seconds. But at least there was something on the screen while this
happened... you could always make it a 'please wait a moment...' image if you
didn't have anything else that would work well. Then, a few frames later, I
sent a message to the sprite telling it to start playing back the DVD.

This worked well enough but if you were really wanting to be precise, you
could keep track of 'the ticks', then issue the 'play the dvd now' code, then
check the ticks afterward to see how much time (if any) was left that you
wanted to pause on that slide, and loop until that time amount (delay seconds
* 60 + originalTicks > the ticks) had gone by.

The DVD did indeed spin up, and was paused, showed up in the corner where I
stuck it (unobtrusive), etc. The problem was, the playback head didn't move
because the generic DVD behavior loops on the same frame until the DVD is
done. So I hacked the DVD code up a little bit and added my own condition,
'#loopWhilePaused'.

* * * Code Changes

Here are the changes that I made to the code. There are three scripts
involved:  the castmember script, the generic DVD behavior script, and my
'play the video now' script, which I just stuck in the score script channel.

Changes to the castmember script (which contains the specific start/stop
times, event times, etc):

* I modified the 'initMemberLists()' function so it was a series of individual
assignment statements, e.g.:

  -- The following property lists contain the settings for this DVD member.
  pProperties = [:]
  pProperties[#name] = "the dvd"
  pProperties[#DefaultVolume] = 50
  pProperties[#fullscreen] = 0
  pProperties[#AutoStart] = 0

  pProperties[#loopWhilePaused] = 1 -- THIS IS A DEFAULT VALUE
 -- pProperties[#loopWhilePaused] = 0 -- THIS IS **NOT** A DEFAULT VALUE
-- set it to 0 if you want playback head to keep moving.
--  this is needed for my code to work
(etc, etc)

* Note the addition of the '#loopwhilepaused' property above.

* I added this function, just trying to do it 'right':
--------------------------------
-- thom added this 2004-10-02
on setFullScreenMode me,towhat
  me.pProperties[#fullscreen] = towhat
end
-- grr, use 'me' when you're setting a property, people,
-- not just the small p naming convention...
--------------------------------

Here is the one change I made to the generic DVD behavior:

on exitFrame(me)
  -- added by Thom 2004-10-02
  -- default value
  doNotLoop = FALSE
  if (me.pProperties[#loopWhilePaused] = FALSE) then
    if (me.pSprite.mediaStatus = #paused) then
      doNotLoop = TRUE
    end if
  end if

  -- following line modified to add 'and doNotLoop = FALSE':
  if (me.pPlayingInXtra = FALSE and doNotLoop = FALSE) then
    -- end of added / modified code
    _movie.go(_movie.frame)
  end if
(etc etc)

-----------------------------------

Finally, here is the script I used to say 'play the DVD video now':

on exitFrame me
-- call the function I added to the castmember script
  sendSprite(sprite(1), #setFullScreenMode, TRUE)

-- Now that it's full screen, we need to re-init the size
  sendSprite(sprite(1), #initSize)

-- Pretend like we're the flash controller, and someone just
-- mouse-upped the 'play' button:
  sendSprite(sprite(1), #releasePlay)
end

-----------------------------------

If anyone has a different or better suggestion about how they made this work,
I'd love to know what they did. (And yes, I realize that directly messaging a
particular sprite by its channel number is not a very dynamic way to handle
messaging; I'm just trying not to confuse the issue here. ;)

Anyway, having this information would have saved me a couple of hours of
messing around. So I hope this is helpful to someone.


Thom Brooks
Adler Planetarium and Astronomy Museum
Chicago, IL
[To remove yourself from this list, or to change to digest mode, go to 
http://www.penworks.com/lingo-l.cgi  To post messages to the list, email [EMAIL 
PROTECTED]  (Problems, email [EMAIL PROTECTED]). Lingo-L is for learning and helping 
with programming Lingo.  Thanks!]

Reply via email to