Search code examples
pythonsubprocessglob

Passing argument to mpg123 with subprocess in a python script


I have a Python3 script that responds to input from a rotary dial phone (via GPIO pins on a raspberry pi.) If I dial a 1, my script uses subprocess to tell mpg123 to play a file called 1.mp3. 2 plays 2.mp3, and so on up to 7. This is working:

filename = "/media/"+str(number)+".mp3"
player = subprocess.Popen(["mpg123",  filename, "-q"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

If I dial 8, the magic 8-ball, the script should behave differently. I want it to call mpg123 with the "little shuffle" flag, -z. From the command line, I know how to make that call:

 mpg123 -z /media/mp3s/*

I want to use this exact syntax in my python3 script, but it isn't working.

 if number ===8:
         player = subprocess.Popen(["mpg123", "-z", "/media/mp3s/*"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

Nothing happens. Script just waits patiently for the next non-8 input.

As a Plan B, I thought maybe I could pass a list of files to mpg123 with glob.glob:

filelist = glob.glob('/media/mp3s/*.mp3')
print(filelist)
player = subprocess.Popen(["mpg123", "-z", "--list", filelist], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

This crashes the script because TypeError: Can't convert 'list' object to str implicitly (Though it does successfully print out the list of files before it dies.) I think I must be very close with at least one approach, but I can't figure out the last little bit of syntax. Any ideas appreciated.**


Alright - I figured out a way to make it work, using mpg123's builtin directory specifying flag, -B. I am still curious about how to get one or both of my other approaches to work. For the record, this works:

player = subprocess.Popen(["mpg123", "-Bz", "/media/mp3s/"],.......


Solution

  • Your solution is probably better, however I thought I would point out the problem with your plan B:

    filelist = glob.glob('/media/mp3s/*.mp3')
    print(filelist)
    player = subprocess.Popen(["mpg123", "-z", "--list", filelist], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    

    The problem here is you are passing filelist as an item to the list. So you would get a list containing a list:

    ["mpg123", "-z", "--list", [ '/media/mp3s/1.mp3', '/media/mp3s/2.mp3' ]]
    

    However what you wanted is this:

    ["mpg123", "-z", "--list", '/media/mp3s/1.mp3', '/media/mp3s/2.mp3']
    

    To get these you need to join the lists together:

    player = subprocess.Popen(["mpg123", "-z", "--list"] + filelist, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    

    Not tested, but I believe this should work.