Wiley.Mobile.Python.Rapid.prototyping.of.applications.on.the.mobile.platform.Dec.2007 (779889), страница 16
Текст из файла (страница 16)
The play()function may be given a callback function as a parameter, whichis named sound callback() here. The callback function is calledwhenever the sound state changes. The function is given three parameters: prev state, current state and err. We can check thecurrent state of the sound with the variable current state.
It equalsaudio.EOpen, if the sound has finished, or audio.EPlaying if thesound is playing.In the above example, we want the play() function to wait untilthe sound has finished. We use the e32.Ao lock object to wait untilthe callback function receives a notification that the sound has finished,after which it releases the lock using the signal() function. As a result,"PlayMP3 returns.." is printed out only after the sound has beenplayed in full.You could easily extend the previous examples into a fully fledgedMP3 player. For example, you can add a popup dialog that lets you pause,stop and fast forward the playing song. The rest of this section introducessome useful functions to do this.
The next step might be to add simpleplaylist functionality to the player. For this purpose, you might want tohave a look at Chapter 6, which introduces data handling.5.1.3Playing MIDI FilesEven though MP3 files are abundant nowadays, the MP3 format is notsuitable for every purpose. To demonstrate how to play other sound80SOUND, INTERACTIVE GRAPHICS AND CAMERAformats besides MP3, Example 25 uses a Musical Instrument DigitalInterface (MIDI) file.As the name suggests, a MIDI file contains commands that musicalinstruments transmit to control various attributes of music, such as playingnotes and adjusting an instrument’s sound in various ways.Playing MIDI files works in exactly the same way as playing MP3 files.As in the previous example, your sound file should be placed on yourmemory card.Example 25: MIDI playerimport audiomidi = audio.Sound.open("E:\\Sounds\\mysound.mid")def playMIDI():midi.play()print "PlayMIDI returns.."playMIDI()As you can see, the audio module takes care of handling differenttypes of sounds automatically, so you can open any sound file that issupported by your phone in a similar way.
A blocking MIDI player wouldlook exactly like the blocking MP3 player in Example 24.5.1.4 Additional Information on Playing SoundsBesides the callback parameter that was demonstrated in Example 24,you can specify how many times the sound should be played.
For instance,if you specify play(times = 20), the sound will play 20 times. If youwant to repeat the same sound forever, use play(audio.KMdaRepeatForever). If you want to leave some silence between subsequent plays,use the interval parameter to specify the interval in microseconds.Some phones do not support simultaneous playing of audio files.
Ifyou try to call the play() function in such a phone while a sound isplaying, an exception is raised. You can prevent this from happening byalways calling stop() before playing a sound. Also note that you haveto call stop() explicitly before your script exits or the sound will keepplaying in the background even after your program has ended.5.1.5 Recording SoundsNow we turn your phone into a lo-fi music studio by showing howto record sounds with the audio module.
Although a phone supportsplaying a wide range of different sound formats, it can typically recordonly WAV and AMR files.SOUND81Sounds are recorded using the same audio.Sound object that wasused for playback. In Example 26, we make a simple program that letsyou record and play a single sound.Example 26: Sound recorderimport appuifw, audio, osMENU = [u"Play sound", u"Record sound", u"Delete sound"]SOUNDFILE = u"E:\\sound.wav"sound = Nonewhile True:index = appuifw.popup_menu(MENU, u"Select operation")if sound:sound.stop()sound = audio.Sound.open(SOUNDFILE)if index == 0:sound.play()elif index == 1:sound.record()appuifw.query(u"Press OK to stop recording", "query")sound.stop()elif index == 2:os.remove(SOUNDFILE)else:breakThe program starts by displaying a popup menu, as shown in Figure 5.1,that lets the user choose the desired operation. If you attempt to playa sound before one has been recorded, the program crashes as the fileSOUNDFILE cannot be found.
Chapter 6 gives you some ideas on howto handle situations like this properly.The function sound.record() starts recording. The recording continues until sound.stop() is called. Since we want the user to decidewhen to stop, we present a dialog that blocks the execution until the userselects OK.If the sound file already exists when recording starts, the new soundis appended to the end of the existing file. You can hear this easily byrepeating the ‘Record sound’ operation several times and then listeningto the sound. If you want to start recording from scratch, the previous filemust be deleted first.
This can be done with the os.remove() function,which deletes the file whose name is given in the parameter. This functionis called if the user chooses the ’Delete sound’ operation from the menu.Note that you need to import the os module to use this function.As the program operates within an infinite loop, the popup menu isshown again once an operation finishes. Note that sound.play() onlystarts the playing and does not wait for it to finish, so a new dialog maybe shown although the sound is still playing.
We stop playing, however,once the next operation has been chosen, as it is not a good idea to82SOUND, INTERACTIVE GRAPHICS AND CAMERAFigure 5.1 Sound recorderexecute several record() and play() operations simultaneously onthe same sound object. The program exits when you cancel the popupmenu.Recording Animal SoundsExample 27 extends the previous sound recorder by recording sounds toseveral sound files instead of only one.
The example lets you record andplay sounds of animals, namely the sound of a dog, a cat and a cow. Ifyou have a toddler, this might be a good way to introduce the wonderfulworld of mobile programming.Example 27: Animal soundsimport appuifw, audioanimals = [u"dog", u"cat", u"cow"]def record_animal_sounds():for animal in animals:noise = audio.Sound.open("e:\\" + animal + ".wav")if appuifw.query(u"Record sound of a " + animal, "query"):noise.record()appuifw.query(u"Press OK to stop recording", "query")noise.stop()noise.close()def select_sound():global funny_noiseSOUND83funny_noise = Nonewhile True:index = appuifw.popup_menu(animals, u"Select sound:")if funny_noise:funny_noise.stop()if index == None:breakelse:play_animal_sound(u'e:\\ + animals[index] + '.wav')def play_animal_sound(soundfile):global funny_noisefunny_noise = audio.Sound.open(soundfile)funny_noise.play()record_animal_sounds()select_sound()This time, you have to record sounds of the three animals when thescript starts.
This is handled by the function record animal sounds()which loops over the list of animals, animals. After this, the functionselect sound() presents a menu that lets you choose a sound toplay.Note that the sounds are saved to the root of the memory card, that is,the E: drive. If you do not have a memory card, you can change the path,for instance, to C:\\Python.The playing of a sound is handled by the function play animalsound(). Note that here we declare the variable funny noise asglobal.
This variable contains the sound object that is now playing. Iffunny noise was not global, we would not be able access it after thefunction play animal sound() returns, so stopping the sound wouldbe impossible. As the variable is declared global, it stays alive even afterthe function returns, so we can stop the sound once the user choosesthe next sound to be played. This example exits when you cancel theplayback dialog.Recording a Phone CallInteresting things happen when you record or play a sound during aphone call. Calling play() plays the sound to the speech channel,meaning that those participating in the phone call can hear it. Callingrecord() starts recording the telephone call.See Chapter 7 for more information about using the telephone.5.1.6 Other Useful Functions of the Audio ModuleA range of additional functions are provided by the audio module:84•SOUND, INTERACTIVE GRAPHICS AND CAMERAstate() returns the current state of the Sound object.
The differentstates are returned as constants:◦ ENotReady – the Sound object has been constructed but noaudio file is open.◦EOpen – an audio file is open but no playing or recording operation is in progress.◦EPlaying – an audio file is playing.◦ERecording – an audio file is being recorded.•max volume() returns the maximum volume of the device.•set volume(volume) sets the volume of the device. If the givenvolume is negative, the volume is set to zero which mutes the device.If the volume is greater than the maximum volume, the maximumvolume is used.•current volume() returns the current volume level.•duration() returns the duration of the file in microseconds.•set position(microseconds) sets the position of the playhead.•current position() returns the current playhead position inmicroseconds.5.2 Keyboard KeysIn this section, we introduce you to the keys of the phone keyboard.Although there is nothing particularly difficult in registering the click of akey, there are several things worth noticing.First, a single physical key may produce different results based on thekeyboard mode: for instance, a key might produce an upper or lowercase ‘a’ depending whether some other key is active.
Second, there areseveral different key events: the user can select a key, hold it down andrelease it – all these events can be registered separately.With the help of the next three examples, we show three differentapproaches to programming keyboard keys.
Each example takes a slightlydifferent approach, but basically they all do the same thing:•If the user presses the up-arrow key (navigation key up), a note dialogtells us that the up-arrow key was pressed, as shown in Figure 5.2.•If the user presses keyboard key 2, a note dialog tells us that key 2was pressed.KEYBOARD KEYS(a)85(b)Figure 5.2Up arrow is pressedEven though all three approaches are used here to accomplish thesame task, each of them is best suited to handle a particular use case:•The first approach (Section 5.2.1) is handy when you need to handlethe clicks of only a few specific keys.•The second approach (Section 5.2.2) is suitable if you need morecomplicated processing of several keys.•The third approach (Section 5.2.3) is a generalization of the secondand allows you to detect whether a key is clicked or continuouslyheld down.Before we present the approaches, note one important prerequisite:when you want to register any key event (except the left and right softkeys),you need to assign the appuifw.Canvas object to the application body,appuifw.app.body.Canvas is a UI element that provides a drawable area on the screenand provides support for handling keyboard key events.
The Canvasobject can be instantiated as follows:canvas = appuifw.Canvas()appuifw.app.body = canvasThis creates a Canvas object named canvas which is then assignedto the application body. As you may remember, Figure 4.1 illustrates86SOUND, INTERACTIVE GRAPHICS AND CAMERAthe application body with respect to the other parts of the standard S60application UI.The Canvas() function, which creates the corresponding object, takestwo optional parameters: redraw callback and event callback.We can assign a callback function to both of these parameters.