[comp.sys.mac.programmer] tough Sound Manager questions

rcook@eagle.wesleyan.edu (04/30/91)

Inside Mac and the tech notes say that you should only hold on to a channel
while it is making a sound.  This seems reasonable; you just put a callback in
that sets a flag to delete the channel at the next available opportunity.
Nevertheless, I have some questions about this method.  (I am only concerned
with sampled sounds, though that really shouldn't matter, should it?)

1)  What happens if you are playing a long sound and your program decides to
call sysBeep?  Since before 6.0.7 you can only have one channel open, does your
channel get trashed?  If it does get trashed, what happens when your callback
comes along and tries to dispose of your channel?

2)  Suppose you are clever and somehow make sure that your program newver calls
SysBeep when it has a channel going.  What if some sort of background task uses
the all powerful Notification Manager to flash the apple menu and make a sound
while one of yours is playing?

3)  What if you are writing a game where you need to play a sound after just
about every keystroke, and even in between keystrokes, so that you need to play
a new sound before the last one is finished?  Do you use SndDoImmediate
commands, SndDoCommand, or just SndPlay?  Could you possibly have more than one
callbackCmd in the queue at the same time?  I looked at the Sound Manager
source code example on Apple.com and it uses SndPlay (and works a hell of a lot
better than my attempt :-), though once it did manage to go silent for a few
seconds, but then sprang back to life, with no problems since.

This source code I mention is very well commented and quite valuable to the Mac
programming community, but when you play a new sampled sound when an old one is
still playing, the old one stops and the new one starts immediately.  In my
case, this is what I wanted, but what if you wanted the first one to finish
before starting the second?  Do you have to remove the call back command that
is (I assume) sitting in the queue before you put a new buffer command in the
queue followed by a new call back command?  Will IM-VI explain all this
accurately, unambiguously, and clearly?

I don't think these are easy questions to answer.  I hope someone out there
can.  If you want, I'll post back the most informative of the e-mail I receive
on the subject.  Thanks.

rc
 
------------------------
Randall Cook
rcook@eagle.wesleyan.edu
------------------------

REEKES@applelink.apple.com (Jim Reekes) (05/01/91)

In article <1991Apr29.163227.42312@eagle.wesleyan.edu>, rcook@eagle.wesleyan.edu writes:

> What happens if you are playing a long sound and your program 
> decides to call sysBeep?  Since before 6.0.7 you can only have one 
> channel open, does your channel get trashed?

Sometimes, but it depends on the machine and the System version 
your running.  That's why I recommended (I wrote the replacement 
chapter for Inside Mac) to dispose of your channel ASAP.  If you 
refer to my sample code "SoundApp" you'll see that I even avoid the 
Dialog Manager calling SysBeep by replacing the ErrorSound routine 
to only flash the menubar.

> If it does get trashed, what happens when your callback comes along 
> and tries to dispose of your channel?

If it does get trashed, you often crash the system.  If your 
callBack comes along at all, you might crash when you call 
SndDisposeChannel.

> What if some sort of background task uses the all powerful 
> Notification Manager to flash the apple menu and make a sound while 
> one of yours is playing?

While your application is the foreground app, you can avoid the 
Dialog Manager calling SysBeep by using ErrorSound as I just 
described.  If you wanted to, you could even patch SysBeep.  But, 
this will only prevent beeps from happening while your application 
is in the foreground, which is exactly why I recommend to dispose 
of channels while switching into the background.  I haven't seen 
any apps calling SysBeep from the background.  Although, it is 
possible to play your own sound using the Notification Mgr.  I 
think QuickMail does this.  That might be a problem.

> What if you are writing a game where you need to play a sound after 
> just about every keystroke, and even in between keystrokes, so that 
> you need to play a new sound before the last one is finished?

You can stop the current sound by calling flushCmd and quietCmd 
using SndDoImmediate.  Then use the bufferCmd with SndDoCommand to 
queue up the next sound.  Don't use SndPlay because of it 
limitations as noted in Inside Mac's replacement chapter (you can 
generally only use it once on a channel).

> Could you possibly have more than one callbackCmd in the queue at 
> the same time?

You can any number of callBackCmds in a channel.  They are just 
markers that will call your CallBackProc when they become the 
current command.  In order to tell which callBackCmd is happening, 
you can use the command's param1 and param2 fields to contain any 
value you want.  You can use the callBackCmd to impliment a double 
buffer technique which works great.  Other callBackCmds can be used 
to signal when you're all done with the sound and then dispose of 
the channel.

> I looked at the Sound Manager source code example on Apple.com and 
> it uses SndPlay (and works a hell of a lot better than my attempt 
> :-), though once it did manage to go silent for a few seconds, but 
> then sprang back to life, with no problems since. This source code 
> I mention is very well commented and quite valuable to the Mac 
> programming community,

Thanks, I wrote SoundApp.  It is much more than _just_ a Sound 
Manager example.  It shows how to write good Macintosh code, and is 
full of useful tips.  I'm also very big on commenting and using a 
style that is readable.

> but when you play a new sampled sound when an old one is still 
> playing, the old one stops and the new one starts immediately.  In 
> my case, this is what I wanted, but what if you wanted the first 
> one to finish before starting the second?  Do you have to remove 
> the call back command that is (I assume) sitting in the queue 
> before you put a new buffer command in the queue followed by a new 
> call back command?  Will IM-VI explain all this accurately, 
> unambiguously, and clearly?

As for the silence, it might be that I am doing some house cleaning 
of the old sound and channel, then started up a new sound and 
channel.  That can be avoided if you want to special case it.  If 
you're going to start a new sound while a channel is already open, 
then just send the flushCmd and quietCmd, then start the new sound.  
If you want the new sound to play *after* the current sound has 
completed, then don't send the flushCmd and quietCmd.  Just queue 
the new sound using SndDoCommand and a bufferCmd.  As for an 
existing callBackCmd waiting in the queue, that could be avoided by 
keeping a global count of the callBacks that suppose to be 
processed.  For example, decrement this count every time in the 
CallBackProc.  Once the count goes to zero, dispose of the channel.  
So, if you have one sound and callBackCmd already queued and want 
to add another sound with a callBackCmd, just increment the global 
count when you send the new bufferCmd.  If you flush the channel, 
then set the count to zero.

> Will IM-VI explain all this accurately, unambiguously, and clearly?

Well, the new Sound Mgr chapter of IM-VI is a great chapter.  It is 
accurate, and hopefully not ambiguous.  You should note that it is 
talking about the Sound Manager of System 7.  As for the Sound Mgr 
of System 6.0.x, you should continue to refer to my replacement 
version of the chapter for the limitations and bugs.  System 6.0.7 
is unique.

It is basically what Inside Mac VI is documenting, but has a couple 
limitations and bugs.  I'm trying to put a Tech Note together about 
all the Sound Manager issues.  Bugs are not the sort of thing that 
should be documented in Inside Mac, unless IM could be updated with 
every System release.  As for design, the best solution is sample 
code.  Inside Mac might be able to provide tips and suggestions, 
but I feel this is beyond the scope of what IM is trying to 
accomplish.

Jim Reekes E.O., Macintosh Toolbox Engineering
(working on the Sound Manager)