pythonpython-2.7subprocesspython-multithreadingomxplayer

How can I play random audio files based on current time in Python 2.7?


Background: I'm using as Raspberry Pi rev 2 B to run a nature sound white noise generator of sorts that will randomly play audio tracks of varying length based on the time of night/morning. Some tracks are only a minute, some are several hours long. I'm looking for a way to check the time and change which type of sounds play based on time.

Current issue: I can start the appropriate audio for the time when the program first executes, but the timeloop execution stops polling once omxplayer starts up.

I have tried to call OMXPlayer without interrupting the time checker that determines what kind of audio to play, but once the audio playback starts I have been unable to continue checking time. Even if the play_audio() function wasn't recursive I would still like a way for the time checker to continue executing while the audio plays

#!/usr/bin/env python
import datetime, time, os, subprocess, random
from timeloop import Timeloop
from datetime import timedelta
from time import sleep
from omxplayer.player import OMXPlayer
from pathlib import Path

tl = Timeloop()
running_cycle = "off" # default value for the time cycle currently running

#function to check current time cycle
def check_time () :
    dt_now = datetime.datetime.now()
    t_now = dt_now.time()
    t_night = datetime.time(hour=2,minute=0)
    t_twilight = datetime.time(hour=4,minute=45)
    t_morning = datetime.time(hour=7,minute=0)
    t_end = datetime.time(hour=10,minute=0)
    if t_night <= t_now < t_twilight:
        return "night"
    elif t_twilight <= t_now < t_morning:
        return "twilight"
    elif t_morning <= t_now < t_end:
        return "morning"
    else:
        return "off"

# function that plays the audio
def play_audio (time_cycle):
    subprocess.call ("killall omxplayer", shell=True)
    randomfile = random.choice(os.listdir("/home/pi/music/nature-sounds/" + time_cycle))
    file = '/home/pi/music/nature-sounds/' + time_cycle + '/' + randomfile
    path = Path(file)
    player = OMXPlayer(path)
    play_audio (time_cycle)

# function that determines whether to maintain current audio cycle or play another
def stay_or_change():
    global running_cycle
    current_cycle = check_time()
    if running_cycle != current_cycle:
        if current_cycle == "off" :
            player.quit()
        else:
            running_cycle = current_cycle
            print "Now playing: " + running_cycle + " @{}".format(time.ctime())
            play_audio(running_cycle)

#starts timeloop checker to play audio - works until stay_or_change() calls play_audio
@tl.job(interval=timedelta(seconds=10))
def job_10s():
    print "10s job - running cycle: " + running_cycle + " -  current time: {}".format(time.ctime())
    stay_or_change() 

# starts the timeloop
if __name__ == "__main__":
    tl.start(block=True)

I have also tried running OMXPlayer with subprocess.run() but it still seems to hang up after the player starts. I'm completely open to any recommendations for background threading media players, process daemons, or time based execution methods.

I'm new to Python.


Solution

  • I had the recursion all wrong so it got caught in an infinite loop and the timeloop function wasn't really viable for this solution. Instead I had a function that played the sound, and then called the function that checked the time and plays from the appropriate sub-directory (or play nothing and wait).

    Here's what I managed to come up with:

    #!/usr/bin/env python
    import datetime, time, os, subprocess, random
    from datetime import timedelta
    from time import sleep
    from omxplayer.player import OMXPlayer
    
    def check_time () :
        dt_now = datetime.datetime.now()
        t_now = dt_now.time()
        t_night = datetime.time(hour=0,minute=0)
        t_twilight = datetime.time(hour=5,minute=45)
        t_morning = datetime.time(hour=7,minute=45)
        t_end = datetime.time(hour=10,minute=0)
        if t_night <= t_now < t_twilight:
            return "night"
        elif t_twilight <= t_now < t_morning:
            return "twilight"
        elif t_morning <= t_now < t_end:
            return "morning"
        else:
            return "off"
    
    def play_audio (time_cycle):
        randomfile = random.choice(os.listdir("/home/pi/music/nature-sounds/" + time_cycle))
        file = '/home/pi/music/nature-sounds/' + time_cycle + '/' + randomfile
        print "playing track: " + randomfile
        cmd = 'omxplayer --vol -200 ' + file
        subprocess.call (cmd, shell=True)
        what_to_play()
    
    def what_to_play():
        current_cycle = check_time()
        if current_cycle == "off" :
            print "sounds currently off - @{}".format(time.ctime())
            time.sleep(30)
            what_to_play()
        else:
            print "Now playing from " + current_cycle + " @{}".format(time.ctime())
            play_audio(current_cycle)
    
    what_to_play()