Hi all, I have to control/manage/automatize a player (music) and I managed to do in the following way.
I posting here to get feedback and also I liked the solution, so it can be useful for others. ;-) Firstly, I chose the mplayer as the player because of multi-platform and multi-filetypes support. Also, it supports control commands in the stdin. I have done the same technique using mpg123 as well. The idea: Run a class (subclass of threading.Thread) that its main loop stay polling other process (mplyer or mpg123) and sends commands to them, also getting data as current music, time elapsed and total time. Keep in mind that it is my first time playing/coding with threads :-) Ok! Show me the code! http://pastebin.com/9nhf6FK0 The same below (who knows how long last a web service) :-) # file: player.py import threading from subprocess import Popen, PIPE from datetime import datetime class MPG123Player(threading.Thread): daemon = True # added to make Ctrl-C and Ctrl-D work when running python -i player.py def __init__(self, music=''): self.music = music threading.Thread.__init__(self) self._kill_me = False self.player = self.init_player() def finish_it(self): self._kill_me = True def init_player(self): return Popen(['mpg123', '--remote', self.music], shell=False, stdout=PIPE, stdin=PIPE) def run(self): '''Thread method that is called when a Thread is started, this is the "main loop" of it''' try: self.player_loop() finally: self.quit() def play(self, music=''): music = music or self.music if music: cmd = 'LOAD ' + music self.player_cmd(cmd) def stop(self): self.player_cmd('STOP') def player_cmd(self, cmd): '''Protocol to talk to the mpg123 ''' self.player.stdin.write(cmd + '\n') def quit(self): self.player.terminate() def player_loop(self): player = self.player self.play() while not self._kill_me: status = player.stdout.readline() '''here we have to keep reading the stdout, because if we don't read from it this buffer get full and the mpg123 stops working. I give from it because of this issue, mplayer.py has a better approach ''' #print status if status.startswith('@F'): cmd_name, cur_frame, frames_left, cur_seconds, seconds_left = status.split() if cmd_name == '@F' and cur_seconds == '0.00': self.total_seconds = float(seconds_left) cur_seconds = float(cur_seconds) self.cur_seconds = cur_seconds class Mplayer(threading.Thread, BasePlayer): daemon = True # added to make Ctrl-C and Ctrl-D work when running python -i player.py def __init__(self, music=''): threading.Thread.__init__(self) def init_player(self): # it is using mplayer.py - https://github.com/baudm/mplayer.py return mplayer.Player(stderr=subprocess.PIPE) # but the basic idea is run the mplayer with this options, but # mplayer.py has some convenient api # #return Popen(['mplayer', '-slave', '-idle', #'-msglevel', 'global=4', # '-quiet', 'nodefault-bindings', '-noconfig', 'all', # self.music], shell=False, stdout=PIPE, stdin=PIPE, # stderr=subprocess.STDOUT) def run(self): try: self.player_loop() finally: self.quit() def play(self, music=''): music = music or self.music if music: cmd = self.player.loadfile(music) def stop(self): self.player.stop() def quit(self): self.player.quit() #self.player.terminate() def player_loop(self): player = self.player while not self._kill_me: self.total_seconds = player.length or 0.0 self.cur_seconds = player.time_pos or 0.0 if (self.total_seconds - self.cur_seconds) <= 0.05: # if it's about to finish the music dispatch the logic to get # the next music print '[%s] ended:' % datetime.now(), player.filename player = Mplayer('/path/to/a/file/199.mp3') #player = MPG123Player('199.mp3') player.start() # you can play with the player using python console # python -i player.py # >>> player.play('file') # >>> player.stop() # I put this file in my application/myapp/modules/player.py # and in my controllers I can from player import player # def index() # return '%s of %s' % (player.cur_seconds, player.total_seconds) [], -- Luciano Pacheco blog.lucmult.com.br

