Package screenlets :: Package plugins :: Module Mplayer
[hide private]
[frames] | no frames]

Source Code for Module screenlets.plugins.Mplayer

  1  # This program is free software: you can redistribute it and/or modify 
  2  # it under the terms of the GNU General Public License as published by 
  3  # the Free Software Foundation, either version 3 of the License, or 
  4  # (at your option) any later version. 
  5  #  
  6  # This program is distributed in the hope that it will be useful, 
  7  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
  8  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  9  # GNU General Public License for more details. 
 10  #  
 11  # You should have received a copy of the GNU General Public License 
 12  # along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 13   
 14  #  Mplayer module (c) Whise (Helder Fraga) 2008 <helder.fraga@hotmail.com> 
 15   
 16   
 17  import sys, os, fcntl, gobject, time, re 
 18  
 
 19  STATUS_TIMEOUT = 1000 
 20  
 
 21  #
 
 22  #  Provides simple piped I/O to an mplayer process.
 
 23  #
 
24 -class Mplayer:
25 26 pymp, mplayerIn, mplayerOut = None, None, None 27 inputHandler, eofHandler, statusQuery = 0, 0, 0 28 paused = False 29 streamTitle = "" 30 streamTitleChangeListeners = [] 31 32 # 33 # Initializes this Mplayer with the specified Pymp. 34 #
35 - def __init__(self, pymp):
36 self.pymp = pymp
37 38 # 39 # Plays the specified target. 40 #
41 - def play(self, target):
42 43 mpc = "mplayer -slave -quiet " + target + " 2>/dev/null" 44 45 self.mplayerIn, self.mplayerOut = os.popen2(mpc) #open pipe 46 fcntl.fcntl(self.mplayerOut, fcntl.F_SETFL, os.O_NONBLOCK) 47 48 self.startInputHandler() 49 self.startEofHandler() 50 self.startStatusQuery()
51 52 # 53 # Issues command to mplayer. 54 # 55
56 - def record(self, target, savefile):
57 58 mpc = "mplayer -slave -quiet " + target + " -ao pcm:file=" + savefile 59 60 self.mplayer_record_In, self.mplayer_record_Out = os.popen2(mpc) #open pipe 61 fcntl.fcntl(self.mplayer_record_Out, fcntl.F_SETFL, os.O_NONBLOCK)
62 63 64 # 65 # Issues command to mplayer. 66 # 67
68 - def cmd(self, command):
69 70 if not self.mplayerIn: 71 return 72 73 try: 74 self.mplayerIn.write(command + "\n") 75 self.mplayerIn.flush() #flush pipe 76 except StandardError: 77 return
78 79 # 80 # Toggles pausing of the current mplayer job and status query. 81 #
82 - def pause(self):
83 if not self.mplayerIn: 84 return 85 86 if self.paused: #unpause 87 self.startStatusQuery() 88 self.paused = False 89 90 else: #pause 91 self.stopStatusQuery() 92 self.paused = True 93 94 self.cmd("pause")
95 96 # 97 # Seeks the amount using the specified mode. See mplayer docs. 98 #
99 - def seek(self, amount, mode=0):
100 pass
101 102 # 103 # Cleanly closes any IPC resources to mplayer. 104 #
105 - def close(self):
106 self.stopStatusQuery() #cancel query 107 self.stopEofHandler() #cancel eof monitor 108 self.stopInputHandler() #cancel input monitor 109 110 if self.paused: #untoggle pause to cleanly quit 111 self.pause() 112 113 self.cmd("quit") #ask mplayer to quit 114 115 try: 116 self.mplayerIn.close() #close pipes 117 self.mplayerOut.close() 118 except StandardError: 119 pass 120 121 self.mplayerIn, self.mplayerOut = None, None 122 #self.pymp.control.setProgress(-1) #reset bar 123 def close_record(self): 124 125 try: 126 self.mplayer_record_In.write("quit\n") 127 self.mplayer_record_In.flush() #flush pipe 128 except StandardError: 129 return 130 131 #self.cmd("quit") #ask mplayer to quit 132 133 try: 134 135 self.mplayer_record_In.close() #close pipes_record_ 136 self.mplayer_record_Out.close() 137 except StandardError: 138 pass 139 140 self.mplayer_record_In, self.mplayer_record_Out = None, None
141 # 142 # Triggered when mplayer's stdout reaches EOF. 143 #
144 - def handleEof(self, source, condition):
145 146 self.stopStatusQuery() #cancel query 147 148 self.mplayerIn, self.mplayerOut = None, None 149 150 # if self.pymp.playlist.continuous: #play next target 151 # self.pymp.playlist.next(None, None) 152 # else: #reset progress bar 153 # self.pymp.control.setProgress(-1) 154 155 return False
156 157 # 158 # Triggered when mplayer's stdout reaches EOF. 159 #
160 - def handleInput(self, source, condition):
161 try: 162 for line in self.mplayerOut: 163 self.lookForStreamTitle(line) 164 finally: 165 return True
166 167 # 168 # Triggered when mplayer prints something stdout. 169 #
170 - def lookForStreamTitle(self, line):
171 matches = re.search("(?<=StreamTitle=\')(.*)(\';StreamUrl=)", line) 172 if matches: 173 self.streamTitle = matches.group(1) 174 for listener in self.streamTitleChangeListeners: 175 keepListener = listener(self, self.streamTitle) 176 if not keepListener: 177 self.streamTitleChangeListeners.remove(listener)
178 179 # 180 # Queries mplayer's playback status and upates the progress bar. 181 #
182 - def queryStatus(self):
183 184 self.cmd("get_percent_pos") #submit status query 185 self.cmd("get_time_pos") 186 187 time.sleep(0.05) #allow time for output 188 189 line, percent, seconds = None, -1, -1 190 191 while True: 192 try: #attempt to fetch last line of output 193 line = self.mplayerOut.readline() 194 except StandardError, detail: 195 break 196 197 if not line: break 198 199 if line.startswith("ANS_PERCENT_POSITION"): 200 percent = int(line.replace("ANS_PERCENT_POSITION=", "")) 201 202 if line.startswith("ANS_TIME_POSITION"): 203 seconds = float(line.replace("ANS_TIME_POSITION=", "")) 204 205 #self.pymp.control.setProgress(percent, seconds) 206 return True
207 208 # 209 # Add a listener that will be called every time a change in stream title is detected. 210 # The signature of the callback should be: 211 # def callback(source, newStreamTitle) 212 #
213 - def addStreamTitleChangeListener(self, callback):
214 self.streamTitleChangeListeners.append(callback)
215 216 # 217 # Removes a stream title change listener. 218 #
219 - def removeStreamTitleChangeListener(self, callback):
220 self.streamTitleChangeListeners.remove(callback)
221 222 # 223 # Inserts the status query monitor. 224 #
225 - def startStatusQuery(self):
226 self.statusQuery = gobject.timeout_add(STATUS_TIMEOUT, self.queryStatus)
227 228 # 229 # Removes the status query monitor. 230 #
231 - def stopStatusQuery(self):
232 if self.statusQuery: 233 gobject.source_remove(self.statusQuery) 234 self.statusQuery = 0
235 236 # 237 # Inserts the EOF monitor. 238 #
239 - def startEofHandler(self):
240 self.eofHandler = gobject.io_add_watch(self.mplayerOut, gobject.IO_HUP, self.handleEof)
241 242 # 243 # Removes the EOF monitor. 244 #
245 - def stopEofHandler(self):
246 if self.eofHandler: 247 gobject.source_remove(self.eofHandler) 248 self.eofHandler = 0
249 250 # 251 # Inserts the input monitoy. 252 #
253 - def startInputHandler(self):
254 self.inputHandler = gobject.io_add_watch(self.mplayerOut, gobject.IO_IN, self.handleInput)
255 256 # 257 # Removes the EOF monitor. 258 #
259 - def stopInputHandler(self):
260 if self.inputHandler: 261 gobject.source_remove(self.inputHandler) 262 self.inputHandler = 0
263 264 #End of file 265