• Aucun résultat trouvé

Just One Tune at a Time

Dans le document ActionScript 3.0 Design Patterns (Page 137-142)

Since the advent of MP3 and MP3 players, music has migrated from the CD to MP3 players and devices like Apple’s iPod. Imagine cranking up your iPod to listen to your favorite tunes, and instead of one at a time, they all start playing simulta-neously. The software that runs your iPod won’t let that happen, and you shouldn’t Figure 3-6. Alert message on the stage

let it happen to your applications either. Here’s another situation where a Singleton can come in handy.

To get started, we need to take a look at how we can play an MP3 file in Flash CS3.

We won’t even consider the idea of importing an MP3 file into the main Timeline and bloating our SWF file. Rather, we need to take a quick look at how ActionScript 3.0 deals with sound and externally accessed MP3 files.

The classes relating to sound can be found in theflash.mediapackage. Of the five sound-related classes, we’ll need only the Sound and SoundChannel classes. We’re going to access an external file (the MP3 file), so we’ll need theflash.net.URLRequest class as well. The necessary minimum sequence can be seen in the following pseudocode:

var mySound:Sound = new Sound( );

var myChannel:SoundChannel = new SoundChannel;

var myTune:URLRequest= new URLRequest(string);

mySound.load(myTune);

myChannel=mySound.play( );

Using the following script, we can create the actual method:

public function playMe(song:String):void {

_tuneUp=new Sound( );

_tuneIn=new URLRequest(song);

_tuneUp.load(_tuneIn);

_goChannel=_tuneUp.play( );

}

The function has a single parameter, which is a string variable that will be the name of the song (MP3 file). You might want to think of the song parameter as a URL, because that’s actually what it is. However, it makes perfect sense to reference it as a song because the individual MP3 files are individual tunes. Given the way the func-tion’s designed, there’s a place for only a single sound. Because the method resides in a Singleton class, there’s also going to be only a single instance, guaranteeing that only one tune at a time will be played.

However, before we go further, we need to consider how the SoundChannel class works. As soon as theSound.play( )method is assigned to theSoundChannelinstance, the song starts playing. If, using the same instance of the Sound and SoundChannel classes, you load and play another MP3 file, it’s going to start playing as well. As far as the instances are concerned, there’s no contraction because they’ve done their job and set the first MP3 file merrily on its way. So they’re finished. Using exactly the same instance, they’re willing to do it again with another MP3 file even if the first one’s still playing. The two will overlap, and because that’s one of the things we want to prevent, the code will have to find whether there’s aSoundChannelinstance with an assigned value around. This is done by testing theSoundChannelinstance for anullvalue. If anullvalue is found, the script just goes ahead and activates the code

for playing the selected tune. If it finds a non-nullvalue, it means it better stop any current sounds associated with the SoundChannel instance before loading up and playing a new MP3 file. In that way, you ensure that you won’t have multiple tunes playing simultaneously. The moral to this particular application is this:

Just because you use a Singleton design pattern does not mean that your application will work with the single outcome you want. You must design your Singleton to ensure that the single outcome you want takes place in the way you want.

With the moral in mind, you can now create your Singleton for making sure that only one MP3 file is allowed to play at once. Enter the script shown in Example 3-12 in an ActionScript file, and save it asTuner.as.

Example 3-12. Tuner.as package

{

import flash.net.URLRequest;

import flash.media.Sound;

import flash.media.SoundChannel;

public class Tuner

The first thing to note about this Singleton script is that it imports packages and classes. Up to this point, all of the imports were done in the scripts that called the Singleton class. However, whenever a method or property has a reference, including abstract ones, to a class in a package, it needs to import that class. Likewise, you’ll see that the class (DoMusic) that implements the Singleton class (Tuner) requires no further import of the objects associated with the packages and classes already imported in the Singleton class.

Because this application simply makes sure that only one MP3 file is played at any time, the Singleton implementation is very simple. Example 3-13 shows the code for this class:

Save Example 3-13 asDoMusic.asin the same folder asTuner.as. Open a Flash docu-ment file, typeDoMusicin the Class document window in the Properties panel, and save it as Music.fla in the folder with the two ActionScript files. Finally, place any

}

//Stop Play

public function stopMe ( ):void {

if (_goChannel != null) {

_goChannel.stop ( );

} } } }

class PrivateClass {

public function PrivateClass ( ) {

trace ("PrivateClass called");

} }

Example 3-13. DoMusic.as package

{

import flash.display.Sprite;

public class DoMusic extends Sprite { public function DoMusic( ) {

var playOne:Tuner = Tuner.getInstance( );

//Use any MP3 file you have available playOne.playMe("blues.mp3");

} } }

Example 3-12. Tuner.as

MP3 file in the same folder, and rename itblues.mp3. (You may keep the MP3 file’s original name and change the reference name in the script from blues.mp3 to the name of your MP3 file—just make sure that the reference name and the filename are the same.) When you test your movie, you should hear your MP3 file play.

In a more realistic example, the application is likely to have several sound selections from which to choose, and the Singleton ensures that only one plays at one time.

Because the method for playing an MP3 file is abstracted in the Singleton class, if another tune is called through the Singleton, it employs the single instance of the class to start the new tune. This particular Singleton takes care of the sound “house-keeping” by making sure that any currently playing SoundChannel instances are stopped, and so it does more than just ensure that only a single instance of the class is instantiated. Example 3-14 provides the necessary code. Save the file as DoMusicBtn.as in the same folder as theTuner.as file.

EExample 3-14. DoMusicBtn.as package

{

import flash.events.MouseEvent;

import flash.display.Sprite;

public class DoMusicBtn extends Sprite {

_playOne.addEventListener (MouseEvent.CLICK,doOne);

_playTwo.addEventListener (MouseEvent.CLICK,doTwo);

_stopSong.addEventListener (MouseEvent.CLICK,doStop);

} //Methods

function doOne (e:MouseEvent):void {

To test this particular implementation, you will need a slightly more elaborate Flash document file. The following steps show what you need to do.

1. Open a new Flash document and save it in the same folder as yourTuner.as file.

2. Using the Oval tool, draw an oval with a radius of 15 on the stage. Select the oval, and then press the F8 button to open the Convert to Symbol dialog box.

Type inSongPlayin the Name window, and select Button for the Type. Click the Export for ActionScript checkbox in the Linkage group. The class name should showSongPlay and the base class will showflash.display.SimpleButton. Click OK. Delete the button from the stage. (It still remains in the Library.)

3. Open the Properties panel, and, in the Document class window, type in DoMusicBtn. Save the file once more.

4. In the folder where you’ve saved the ActionScript (.as) and Flash document files (.fla), add two MP3 files using the file names shown in Example 3-14. (You can change the names in your MP3 files or the names in Example 3-14.)

5. Test the application by pressing Ctrl + Enter (Command + Return on the Mac).

You should see three buttons appear. The two buttons on the left let you select one of the two MP3 files, and the one on the right will stop whatever is currently play-ing. If you click either of the buttons on the left while a tune is still playing, it’ll stop the tune and start play from the beginning of the selected tune.

Dans le document ActionScript 3.0 Design Patterns (Page 137-142)