I am using my Raspberry Pi to play songs. I am trying to control the mplayer through a simple python programme. I have chosen python because I new to coding and have set up some simple imput driven menus to choose songs.
I found this code here to play the song :-
import os
SOUND = 'music.mp3'
command = 'mplayer %s 1>/dev/null 2>&1' % SOUND
os.system(command)
But I can't work out how to stop it part way through a track and return to my simple python menu to choose another option. Please help . . .
You can use subprocess.Popen and kill the process whenever you want to end the song:
from subprocess import Popen
SOUND = 'music.mp3'
proc = Popen(['mplayer', '%s', '1>/dev/null', '2>&1',SOUND])
import time
time.sleep(3)
proc.kill()
Related
I am currently making a program in python to open minecraft servers. I've already done a window where you can choose a server in a list and launch it or make a backup. When you launch it, a new terminal open (with os.system('gnome-terminal...')) and the java program starts. Is there a way to send some text (like commands) to this java program from the first terminal ?
Here is my code
I've tried many things with subprocess but without a satisfying result.
EDIT:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import gtk
import re
import os
import time
active_button = 0
servers = [["Server 1","/home/myname/Desktop/server1","server.jar"],
["Serveur 2","/home/myname/Desktop/server2","server.jar"]]
def button_selection(button, num):
global active_button
state=button.state
if state >= 1:
active_button = int(num)
def validation(widget):
path = servers[active_button][1]
server = servers[active_button][2]
command = """gnome-terminal --working-directory="%s" -e 'java -jar %s'""" % (path, server)
print(command)
os.system(command)
def save(widget):
path = servers[active_button][1]
server = servers[active_button][2]
print "cp -a '%s' /home/myname/Documents/backups_minecraft_servers/%s" % (path+"/world", time.strftime("%d_%m_%Y-%T"))
os.system("cp -a '%s' /home/myname/Documents/backups_minecraft_servers/%s" % (path+"/world", time.strftime("%d_%m_%Y-%T")))
print("Backup finished")
def main():
window = gtk.Window()
vbox = gtk.VBox()
hbox = gtk.HBox()
validate = gtk.Button("Validate")
validate.connect("clicked", validation)
backup = gtk.Button("Backup")
backup.connect("clicked", save)
hbox.pack_start(validate)
hbox.pack_start(vbox)
hbox.pack_start(backup)
buttons = [gtk.RadioButton(None, servers[0][0])]
vbox.pack_start(buttons[0])
for server in servers[1:]:
buttons.append(gtk.RadioButton(buttons[0], server[0]))
vbox.pack_start(buttons[-1])
for i in range(len(buttons)):
buttons[i].connect("toggled", button_selection, i)
window.add(hbox)
window.show_all()
gtk.main()
if __name__=="__main__":
main()
First off, don't ever use os.system. Always use the subprocess module for launching new processes, as it handles many of the edge cases much better. subprocess.check_call can do everything os.system can do, and much more, and it checks for errors, something os.system doesn't do.
Secondly, don't use gnome-terminal to create an interactive terminal to run your subprocess in! Create a pseudoterminal (pty) instead; that way your program can maintain control over the behavior of the child. Underneath the hood, that's how a program like gnome-terminal works itself: it creates a pty for the shell and the programs launched by the shell to run in, and then it reads from the pty and renders the results graphically.
Your program can create a pty for each child program you want to run, and then your program can communicate with the child program exactly like how gnome-terminal can. You can do this with the pty module in the Python standard library, but you might want to consider using the pexpect package instead as it simplifies the process substantially.
If you don't need a full terminal, you can do this even more simply by just opening a pipe to the child process. The subprocess module in the standard library provides the Popen class which can be used to do this.
In your specific case I would recommend pexpect. It's easy to use and will "do the right thing" for this kind of job.
I have multiple python files to run. How would I launch all those files within one .py script? This is what I came up with but it shows the screen action and really doesn't begin the other stuff unless I exit out of it. Here's the code, not much:
import os
print("Launching Bot, just for you.")
print("Loading up shard 0")
try:
os.system("screen python3.5 run_0.py > /dev/null")
except:
print("Shard 0 failed")
print("Loading up shard 1")
try:
os.system("screen python3.5 run_1.py > /dev/null")
except:
print("Shard 1 failed")
print("Done running shards...")
I was doing some research and they said to use subprocess but when I used it, it didn't run my command properly. (I don't have a copy of that code, I lost it).
The problem is that I want to run the python script and it works fine but I have to close the screen to start the other one and I just want it to run the command w/o showing the output. Can you help?
You should use import subprocess in a python file. You can then start other instance of other programs with :
subprocess.Popen([sys.executable, "newprogram.py"])
You can mix that with multiprocessing package to launch one thread by new program
p = multiprocessing.Process(target= mp_worker , args=( ))
p.start()
where mp_worker launches the other program.
I am very much a noob with Python and Linux commands but I'm trying to wrap my head around it.
My application is bigger than this sample but I am trying to get this working before expanding.
I am using mplayer in slave mode to play a video clip but I want to automatically kill it when the clip is done. So my idea is to start mplayer in slave mode then command 'get_time_length', store that value, sleep for that value, kill it and return to the main routine.
import os
import commands
import glob
#Global Commands
glcmd = 'get_time_length'
print("Preparing for kiosk mode! Press CTRL+C to exit")
try:
while 1:
path = '/media/*/button1/*'
os.system('mplayer -fs -quiet -slave path')
line = os.popen(glcmd).readline().strip() #Get the duration from mplayer
duration = line.split('=')[1] #Get just the length of video in Seconds
print(duration)
sleep(duration) #Wait until the video is done
os.system('quit')
The problem that I am having is that once the video clip starts playing, it never runs any commands during play. I'm also not sure if my syntax is right in order to retrieve the command line but I at least want to figure out how to be able to send commands with to mplayer with my script while a video is playing.
Thanks!
You can use the subprocess lib as recommended in the docs which say about os.popen Deprecated since version 2.6: This function is obsolete, all you need to do is use check_call the program will end when the video does.
from subprocess import check_call
path = '/media/*/button1/*'
check_call(['mplayer',"-fs", '-quiet' ,'-slave',path])
If you wanted to communicate somehow you would use subprocess.Popen, this will print all the output in a loop and terminate the process if the user enter ctrl-c:
from time import sleep
from subprocess import Popen, PIPE
path = '/media/*/button1/*'
try:
p = Popen(['mplayer', '-quiet' ,'-slave', path],stdout=PIPE, stdin=PIPE)
for line in iter(p.stdout.readline,""):
print(line)
except KeyboardInterrupt:
p.terminate()
If you wanted to send commands you would write to p.stdin
I am trying to use the Python 2.7 subprocess library to programmatically add songs to the VLC player queue.
From here and here, I am able to launch VLC Player and play a song (or queue songs from the outset);
from subprocess import Popen
vlcpath = r'C:\Program Files (x86)\VideoLAN\VLC\vlc.exe'
musicpath1 = r'path\to\song1.mp3'
musicpath2 = r'path\to\song2.mp3'
p = Popen([vlcpath,musicpath1]) # launch VLC and play song
p = Popen([vlcpath,musicpath1,musicpath2]) # launch VLC and play/queue songs
The problem is that I do not know the entire queue playlist at launch. I want to be able to add songs to the queue of the VLC process already running. How do I accomplish this, please?
From here, I think the appropriate command line entry is:
vlc.exe --started-from-file --playlist-enqueue "2.wmv"
But I do not know the syntax to execute this in subprocess. I tried a couple of things, but couldn't get either to work:
calling Popen again (opens a new process)
calling p.communicate (I thought this is how to enter stdin commands)
To run the command: vlc.exe --started-from-file --playlist-enqueue "2.wmv"
using subprocess module on Windows:
from subprocess import Popen
cmd = 'vlc.exe --started-from-file --playlist-enqueue "2.wmv"'
p = Popen(cmd) # start and forget
assert not p.poll() # assert that it is started successfully
To wait for the command to finish:
from subprocess import check_call
check_call(cmd) # start, wait until it is done, raise on non-zero exit status
But how do I run that command a second time on the same p process?
Your code starts a new instance of VLC, rather than running that on
top of the p that was already open. I found that if I run the vlc.exe --started-from-file --playlist-enqueue "2.wmv" command multiple times manually (in a command prompt window), it correctly launches vlc (the
first time) and then adds to queue (on subsequent calls). So I think I
just need to be able to run the code you suggested multiple times "on
top of itself"
Each Popen() starts a new process. Each time you run the command manually in the command-line it starts a new process. It might be upto the current vlc configuration on your system whether it keeps multiple vlc instances or you are running a different command (different command-line arguments).
ok, so my google-fu really kind of sucks and I was unable to find an answer, hopefully you folks can help me ^_^
ok, so what I thought would be a simple script is seemingly not communicating with its subprocess correctly, I'm running this line by line. I'm also using the mpg123 player, this is a Linux system (well, Raspberry Pi)
from subprocess import Popen, PIPE, STDOUT
p = Popen(["mpg123", "-C", "test.mp3"], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
#wait a few seconds to enter this, "q" without a newline is how the controls for the player work to quit out if it were ran like "mpg123 -C test.mp3" on the command line
p.communicate(input='q')[0]
I can run stdout.read() on it just fine, but using communicate for input just makes it hang and p.stdin.write('q') does seemingly nothing at all. This is python related though I have a feeling I'm also not looking in the right place in the mpg123 documentation. Please be kind as I'm exceptionally new to this ^_^
Check what arguments your mpg123 version understands. The following works on my machine:
#!/usr/bin/env python3
import time
from subprocess import Popen, PIPE, DEVNULL, STDOUT
p = Popen(["mpg123", "-K", "test.mp3"], stdin=PIPE, stdout=DEVNULL, stderr=STDOUT)
# wait a little
time.sleep(3)
# send command "Skip song", wait for the player to exit
p.communicate(b'n')[0]
It starts playing the file, waits ~3 seconds, and exits.
This is an awful solution, but it works in a pinch. I'm using this as a patch because for some reason, I cannot get Python libraries to play properly on my Raspberry Pi.
If you start mpg123 in remote mode (mpg123 -R), you can send commands to it far more easily:
proc = sp.Popen(["mpg123", "-R"], stdin=sp.PIPE)
Then, you can send commands to its stdin attribute.
Note:
The commands are different. To pause, it's "pause", not " " for example. Run mpg123 -R in a console, then send it the help command to see a list of commands.
The commands need to be newline terminated.
From the docs:
-R, --remote
Activate generic control interface. mpg123 will then read and execute commands from stdin. Basic usage is ''load '' to play some file and the obvious ''pause'', ''command. ''jump '' will jump/seek to a given point (MPEG frame number). Issue ''help'' to get a full list of commands and syntax.