AUD: The Trouble With Handles BGE 2.77

Alright, so I’m trying to get a TV to work in the game engine. I’ve got a list of three videos as .mp4 files and three .mp3 audio clips that match them. The idea is to change the channel on the TV, moving to both the next video and audio clip in the list. I can get the video that’s currently playing to change by changing a property and getting it to reload on the next frame. But the audio hasn’t been so easy. So far I tried

if own['soundPlay'] == True:
    
    if own['soundLoaded'] == False:
        if own['stopAudio'] == False:
            TVSound = aud.Factory.file(bge.logic.expandPath('//' + audioName))
            bge.logic.hList = {'TVS': device.play(TVSound)}
            bge.logic.hList["TVS"].loop_count = -1
            bge.logic.hList["TVS"].volume = 0.25
            bge.logic.hList["TVS"].position = 0.00
            bge.logic.hList["TVS"].pause()
                
        if own['stopAudio'] == True:
            bge.logic.hList["TVS"].stop()        
        
    if own['soundLoaded'] == True:
        bge.logic.hList["TVS"].resume()

Which did work… On initialization. The problem was the audio would only pause, then resume itself. And if I forced own['stopAudio'] == False a second time, only then would it load the next song. Except that song would be one position up or down in the list offset from the video, playing song 3 for video 2, or song 1 for video 2 for example. For some reason the handle.stop() command isn’t working as intended. The other problem is that if I try to use handle.stop() outside of the if own['soundPlay'] == True statement it won’t recognize it as a valid handle. So then I tried

if own['soundPlay'] == True:
    
    if own['soundLoaded'] == False:
        TVSound = aud.Factory.file(bge.logic.expandPath('//' + audioName))
        TVS = device.play(TVSound)
        TVS.loop_count = -1
        TVS.volume = 0.25
        TVS.position = 0.00
        TVS.pause()
                
        if own['stopAudio'] == True:
            TVS.stop()        
        
    if own['soundLoaded'] == True:
        handle.resume()

And now the audio just won’t load at all. It just gives me the error

File "TVThingy.py", line 109 in <module> aud.error: AUD_OpenALDevice: Source couldn't be generated.

Line 109 by the way is the TVS = device.play(TVSound) line.

dictionaries in python are not ordered, you need a list for that, and just index as the channel number

you also need to store the aud factory and video texture in a permanent place, like the logic module (eeww).

this blend works perfectly for play pause, maybe i can mod it to work with the channels, should be easy. it includes an AV sync code too.
video_sync_upbge020.blend (382.7 KB)

@VulpesHilarianu Just so you know @Daedalus_MDW’s blend file is made in UPBGE so you would have to get a version of UPBGE 0.20+

@Daedalus_MDW The thread title says BGE LMAO friend :v: :wink:

I noticed that within the VideoTexture system that it has a function called video.refresh(bool) to allow it to check if the video needs to be reloaded on every frame. I can’t find a function like that in AUD, but does it exist? And if not, what would be the simplest method to build a system to recall and reload it’s state every frame like what video.refresh(bool) does for VideoTexture?

I could be wrong on this :thinking:

But I think AUD sounds are loaded in every time you play them unless they are defined as kept :arrow_down:

aud.device().play(“SOUND”, 0)

  • By default 0 is 0 since that says not to keep the sound in RAM.
  • If you want to keep the sound set 0 to 1.
  • This will keep the sound in RAM to reduce wasting CPU on fetching the sound but instead wastes more memory on RAM instead.

Just my opinion maybe, but AUD can sod off until the end of time. You’re better off having a separate empty for each sound. On swapping videos, delete the previous empty and spawn in the new one.
Everything you need then is a string. Like,

songs = {videoName:nameOfEmpty}
newSound = scene.addObject(songs[videoName], TV)
newSound.actuators["sound"].volume = TV["volume"]
#yadda yadda yadda
1 Like

That’s what I thought about doing, but there’s a large chance it would desync with the video. There’s also the issue of logic bricks getting quite messy if you’re using more than two or three.

Ah, that did work. With some concessions. The fixed code is as follows:

if own['soundLoaded'] == False:
    
    TVSound = aud.Factory.file(bge.logic.expandPath("//" + audioName))
    bge.logic.hList = {'TVF': device.play(TVSound, True)}        
    bge.logic.hList["TVF"].loop_count = -1
    bge.logic.hList["TVF"].volume = 0.25
    bge.logic.hList["TVF"].pause()
    
    if own['startupTimer'] == 120:    
        own['soundLoaded'] = True
        
if own['soundLoaded'] == True:
    bge.logic.hList["TVF"].resume()
    if keyboard.events[bge.events.ONEKEY] == ACTIVE:
        bge.logic.hList["TVF"].stop()
        print("Stop audio")
        own['soundLoaded'] = False

I had to force it to recognize an input from the user instead of the script resolving it itself, but hey. It works.

1 Like

@VulpesHilarianu Glad I could help :v: :sunglasses:

@Liebranca :peace_symbol: