May 92 - MACINTOSH Q & A
MACINTOSH Q & A
MACINTOSH DEVELOPER TECHNICAL SUPPORT
Q Our application uses the movie poster as a still frame in a cell, similar to using a
PICT. If a user sizes the cell width so that it's narrower than the poster, even though
we clip the drawing to the cell size, QuickTime posters draw their full width, writing
over whatever is in the way. Pictures clip through DrawPicture; why doesn't
ShowMoviePoster stay within the clipping region?
A ShowMoviePoster, as well as the movie and preview showing calls, uses the movie
clipping characteristics rather than the destination port's clipping region. You must
set the movie's clipping region to obtain the results you want. An easier way to do this
is to get the picture for the poster by calling GetMoviePosterPict, and then simply use
DrawPicture to display the poster. Because this is just a picture, the clipping region
of the port is honored. This way you don't need different code for movies and pictures.
Q Our QuickTime application gets a Sound Manager error -201 after playing movies in
succession, apparently because sound channels used in the previous movies have not
been reclaimed. How does QuickTime decide to deallocate sound channels? It doesn't
seem to happen in my "while (!IsMovieDone(theMovie) && !Button())" play loop.
A Sound channels are released by active movies when they notice that some other
movie needs them. This is currently done only at MoviesTask time. Before entering
your loop to play a single movie, you can do one or both of the following:
• Preroll the movie you're about to play and check the error. If preroll
returns -201, call MoviesTask(0,0) to give the other active movies a chance
to give up their sound channels. A subsequent preroll of theMovie should
return noErr.
• Call SetMovieActive(otherMovies, FALSE). Deactivate the movies that you
aren't playing to force them to give up their resources.
Q When I select all frames in QuickTime and then do an MCCut or MCClear, the
standard controller gets larger and redraws itself at the top of the movie. Is this a
situation I should be prepared to handle or a bug? Does the controller behave strangely
when the selectionTime of a movie is -1 or when the duration of the movie is 0?
A The behavior you're observing is to be expected if the controller is attached to the
movie. In this case, the controller goes to wherever the bottom left corner of the movie
box takes it. If the movie loses all its "visible" parts, the movie controller will jump
to the top of the window. The only way to get around this is to detach the controller
when the movie box is empty; this is also something to keep in mind for the cases when
the movie contains only sound, since pure sound movies have no dimensions. You can
find sample code showing how to do this on the Developer CD Series disc, in the
SimpleInMovies example that accompanies the QuickTime article in develop Issue 7.
Q Stepping through QuickTime movie video frames in the order they appear in the
movie is simple using GetMovieNextInterestingTime, except for getting the first
frame. If I set the time to 0 and rate to 1, I get the second frame, not the first. In
addition, the video may start later than at 0. How do you suggest finding this first
frame of video?
A To get the first frame under the conditions you describe, you have to pass the flag
nextTimeEdgeOK = $2000 to GetMovieNextInterestingTime. What this flag does is
make the call return the current interesting time instead of the next, if the current
time is an interesting time. You need to do this because there's no way to go negative
and then ask for the next interesting time.Q I save PICTs to my document's data fork by
writing the contents of the PicHandle. To save movies, do I convert the movie to a
handle, and then save that as I would with PICTs? I just want the file references, not
the data itself.
A To save movies that are suitable for storage in a file, use PutMovieIntoHandle. The
result of this call can be saved in the data fork of your files, and then you can call
NewMovieFromHandle to reconstruct the movie for playback or editing.
You should also read the documentation regarding the Movie Toolbox FlattenMovie
procedure, which creates a file that contains the 'moov' resource and the data all in the
data fork. The advantage here is that the movie file you create using FlattenMovie can
be read by any other QuickTime-capable application.
Q How can I identify the sender of an Apple event?
A If your application is just sending a reply, it should not be creating an Apple event
or calling AESend. Instead, the Apple event handler should stuff the response
information into the reply event, as shown on page 6-50 of Inside Macintosh Volume
VI. The Apple Event Manager takes care of addressing and sending the event.
To find the target ID or process serial number of the sender of an Apple event, use
AEGetAttributePtr to extract the address attribute, as follows:
retCode := AEGetAttributePtr(myAppleEvent, keyAddressAttr,
typeWildCard, senderType,
@senderBuffer,
sizeof(senderBuffer), senderSize)
The senderBuffer can later be used with AECreateDesc to create an address to be passed
to AESend. The buffer should be at least as large as data type TargetID. See Inside
Macintosh Volume VI, page 5-22, for a description of TargetID.
Q When I resize my real-time animation window in System 6, I call UpdateGWorld
with the new size, and after that any drawing into the GWorld has no effect. This same
code works perfectly in System 7. What could cause this?
A You probably can't draw anything into your GWorld after using UpdateGWorld to
resize it because of the clipping region of your GWorld. In system software versions
before 7.0, UpdateGWorld always resizes the GWorld's clipping region proportional to
the amount that the GWorld itself is resized. Unfortunately, NewGWorld initializes the
clipping region of the GWorld to the entire QuickDraw coordinate plane, [T:-32767
L:-32767 B:32767 R:32767]. If UpdateGWorld resizes any of these coordinates so
that they fall outside this range, the coordinates wrap around to the other end of the
signed integer space, and that makes the clipping region empty. Empty clipping regions
stop any drawing from happening.
The change in System 7 is that UpdateGWorld explicitly checks for the clipping region
[T:- 32767 L:-32767 B:32767 R:32767]. If it finds this, it doesn't resize the
clipping region. Otherwise, UpdateGWorld acts the same way that it did before System
7.
One of our mottos is, "Never give QuickDraw a chance to do the wrong thing." In
keeping with that, we always explicitly set the clipping region of a GWorld whenever
we change the size of the GWorld. So after calling NewGWorld, set its clipping region to
be coincident with its portRect. After calling UpdateGWorld to resize the GWorld, set
its clipping region to be coincident with its new portRect. That way, you'll always have
a known environment and you won't have to worry about the change that was made in
System 7--and you'll be less susceptible to bugs in this area in the future.Q
UpdateGWorld doesn't seem to respond to the ditherPix flag unless color depth changes.
The return flag after changing my color table is 0x10000, indicating that color
mapping happened but not dithering. Is this a bug?
A Yes, this is a bug. UpdateGWorld ignores dithering if no depth change is made. It
probably won't be changed in the near future. The workaround is as follows:
1. Create a new pixMap with the new color table.
2. Call CopyBits to transfer your image to the newly created pixMap with
dithering from the original GWorld's pixMap.
3. Update the GWorld with the new color table without using ditherPix.
4. Use CopyBits from the newly created pixMap without dithering back to the
GWorld.
This will give you the same effect as UpdateGWorld with ditherPix.
Q Can I create, open, write, and close a file completely at interrupt time? I need to be
compatible with both System 6 and System 7.
A All these operations (and more) can be done completely at interrupt time. Any call
that can be made asynchronously can be safely made at interrupt time, provided it's
made asynchronously. Glancing through Inside Macintosh Volume IV, we can see that
this includes just about all of the File Manager, except for the calls to mount and
unmount volumes, which must be made at a time when it is safe to move or purge
memory.
One caveat: Making a call asynchronously here means really making it
asynchronously; making the call and then sitting in a little loop waiting for the
ioResult field to change does not qualify. Either you must use completion routines to
determine when a call has completed, or you must check the ioResult from time to
time, never waiting for it at interrupt time (and in this case, a deferred task does
qualify as being at interrupt time).
Q How can I tell whether a window is a Balloon Help window?
A First, call the Help Manager procedure HMIsBalloon to determine whether a balloon
is being displayed at all. Then call HMGetBalloonWindow to get the help window's
window pointer, and compare that to the window pointer of the window you've got.
Note that if HMIsBalloon returns TRUE and HMGetBalloonWindow returns a window
pointer of NIL, it means that the balloon "window" that's displayed really isn't a
window at all; this will happen, for instance, if the balloon is being displayed on top of
a pulled-down menu (we call this "to boldly go where no window has gone before").
Q How can I tell whether a font is monospaced or proportional? The FontRec record's
fontType field doesn't correctly tell me whether the font is fixed width as Inside
Macintosh Volume V says it should. All system fonts appear to have the same fontType
regardless of whether they're fixed or proportional. Currently I test whether the
width of the characters "m" and "i" are equal and if they are, I consider the font to be
fixed width. Is there an easier (and faster!) way?
A The Font Manager documentation is not explicit enough about the fact that bit 13
(0x2000) of the fontType field is useless. The Font Manager doesn't check the setting
of this bit, nor does QuickDraw (or any printer driver). As you observed, monospaced
fonts like Monaco or Courier don't have the bit set; the bit is meaningless. In addition,
the fontType field is available only for 'FONT' and 'NFNT' resources; it does not exist in
'sfnt' resources, and you would have to check separately for the resource type of the
font. Your idea of comparing the widths of "m" and "i" (or any other characters that
are extremely unlikely to have the same widths in a proportionally spaced font) is
indeed the only reasonable way of figuring out whether a font is monospaced.Q The
TrueType system extension (INIT) apparently renders glyphs differently with System
6 than with System 7. For example, our "abc" string in 160-point Helvetica ® is
almost half as many pixels under System 7, so the styled text no longer lines up with
the bitmapped graphics underneath. Any way to avoid this?
System 6
System 7
A Your System 6 configuration probably has the specific Helvetica Bold TrueType
outlines available, while this Helvetica Bold TrueType version is missing in your
System 7. When the Font Manager gets a request for Helvetica, txSize 160, txFace
bold, it looks in the font association table of the Helvetica FOND (font family record;
see page 37 of Inside Macintosh Volume IV). First, it looks for the right size (yes,
there's a TrueType outline font: size requirement fulfilled), then it looks for the style