Forum Archive

Sound and ui modules not playing well together

polymerchm

I am trying to trigger a custom view to redraw, then to play a series of tones (a chord), then retrigger the display, rinse and repeat.

The chords play in sequence, but the display is locked until the last of the tones of the last chord is finish playing. Then it updates to the last of the displays that should have shown. Seem very asynchronous. Is there any simple way (objectiveC is consider semi-simple) to tell when a sound is finished playing.

polymerchm

Reading the IOS bibles, seems I need to have access to the audioPlayeDidFinishPlaying:successfully: method in the delegate. Any chance the delegate is a hidden "feature" of sound or one I can "hack" into?

omz

What does your code for playing the series of tones look like?

polymerchm
def playProgression(button):            
    if os.path.exists('waves'):
        if not model._InstrumentOctave:
            return
        else:
            baseOctave = model._InstrumentOctave
        strings = model._InstrumentTuning

        for chordNumber in range(len(model._ProgFingerings))
 # here is where I inserted code to trigger a redraw of a custom view.  
  # the redraw happens when this loop finished
            thisFingering = model._ProgFingeringsPointers[chordNumber]
            cc = model._ProgFingerings[chordNumber][thisFingering]
            frets = cc[2]
            dead_notes = [item[3] == 'X' for item in cc[0]]
            tones = []
            for fret,string,dead_note in zip(frets,strings,dead_notes):
                if  dead_note:
                    continue
                octave,tone = divmod(string + fret,12)
                tones.append((tone,octave+baseOctave))
            for tone,octave in tones:
                sound.play_effect(getWaveName(tone,octave))
                time.sleep(model.play_arpSpeed*0.25)
            time.sleep(3*model.play_arpSpeed) # rest between chords
# the "chords" play just fine as well as the final sleeps between chords.

JonB

have you tried using the sound.Player.finished_handler?
This seems to be an undocumented feature of the Player class

import sound,ui
v=ui.View()
v.bg_color='red'
v.present()
p=sound.Player('piano:A3')
def g():
    v.bg_color='green'
    p.finished_handler=None
    p.play()
def f():
    v.bg_color='blue'
    p.finished_handler=g
    p.play()

p.finished_handler=f
p.play()
polymerchm

@JonB. YES!!!!! That's what I hoped was out there. WIll try it tomorrow when Im actually awake and functional!!! Where do you find these things?

omz

As an alternative to using Player.finished_handler (which would probably require pretty significant changes in your code), you could also decorate your playProgresion function with ui.in_background, like this:

@ui.in_background
def playProgression(button):
    # ...
JonB

@polymerchm I was checking if Player had an _obj_ptr to see if it could be bridged, and noticed finished_handler in the autocomplete list...

polymerchm

@omz Worked as advertised. I always forget that trick. @JonB: Will try that in other situations. I guess I need to pay careful attention to the autocomplete for other tidbits. Thanks.