[comp.sys.next] trouble understanding delegates and the Soundkit

pts@mendel.acc.Virginia.EDU (Paul T. Shannon) (07/27/90)

I'm dipping a first, cautious toe into the waters of objective c.  My 
project is simply to play a pre-recorded sound using the soundkit.  
The short program below works, but the program sometimes terminates before 
the sound is complete, and therefore the sound gets clipped.  Various 
inelegant approaches skirt around the problem:  

   1. a busy loop after the play message, wasting time until the sound is done
   2. using the c function SNDWait (0) works (though I'm not sure why: is the 
      '0' tag the same as that used, at a low level, by the first sound to be 
      sent the play message?).

So, in trying to do it the right way, I've experimented with creating
a delegate for the sound, which will receive the 'didplay' message.

If this is the right approach, can anyone suggest what to do next?  How do
I establish a method for the soundDelegate so that I can subsequently ask
it to wait until it receives the 'didplay' message?

And if this is the wrong approach, will someone please point me in the
right direction?  

 - Paul Shannon
   pts@virginia.edu
/*----------------------------------------------------------------------------*/
main (int argc, char **argv)
{

  id aSound = [Sound new];
  id soundDelegate = [Object new];
  int success; 

  [aSound setDelegate: soundDelegate];

  success = [aSound readSoundfile: "/NextLibrary/Sounds/Basso.snd"];
  printf ("success of readSoundfile: s\n",  SNDSoundError (success));
  success = [aSound play];

  return 0;

} 
/*----------------------------------------------------------------------------*/

aozer@next.com (Ali Ozer) (07/28/90)

In article <1990Jul27.021809.7097@murdoch.acc.Virginia.EDU>
pts@mendel.acc.Virginia.EDU (Paul T. Shannon) writes:
>
>... My project is simply to play a pre-recorded sound using the soundkit.  
>The short program below works, but the program sometimes terminates before 
>the sound is complete, and therefore the sound gets clipped.  ...
>
>  id aSound = [Sound new];
>  id soundDelegate = [Object new];
>  int success; 
>
>  [aSound setDelegate: soundDelegate];
>  success = [aSound readSoundfile: "/NextLibrary/Sounds/Basso.snd"];
>  success = [aSound play];
>
>  return 0;

The play method returns immediately and the sound continues to play after
the method has returned. The simplest solution to your problem above
would be to invoke waitUntilStopped right after play:

	[aSound play];
	[aSound waitUntilStopped];

This will cause the program to wait until the sound is done. In
an interactive app the better solution would be to have the sound
continue playing in the background so you can still receive events.  Then
rather than calling waitUntilStopped, you will want to just call play
and set up a delegate only if you wish to know when the sound finishes playing.

Rather than creating an instance of generic Object (like you have above),
you need to either create a subclass and give it a didPlay:
method, or add the didPlay: method to an existing object.

Such a delegate might look like the MyObject class below.

If you wanted your program to simply exit once the sound stopped playing,
you could call exit(0) in didPlay:, for instance. (Of course this would be
(1) overkill and (2) not too elegant for the example you have, but it
should work. The waitUntilStopped solution is enough in your program.)

@interface MyObject:Object {}
- didPlay:sound;
@end

@implementation MyObject

- didPlay:sound
{
    printf ("sound stopped playing...\n");
    return self;
}

@end

Ali Ozer, Ali_Ozer@NeXT.com