Package screenlets :: Package plugins :: Module Mplayer

[hide private]
[frames] | no frames]

# Source Code for Module screenlets.plugins.Mplayer

      1  # This application is released under the GNU General Public License
      2  # v3 (or, at your option, any later version). You can find the full
      3  # text of the license under http://www.gnu.org/licenses/gpl.txt.
      4  # By using, editing and/or distributing this software you agree to
      5  # the terms and conditions of this license.
      6  # Thank you for using free software!
      7
      8  #  Mplayer module (c) Whise (Helder Fraga) 2008 <helder.fraga@hotmail.com>
      9
     10
     11  import sys, os, fcntl, gobject, time, re
     12

     13  STATUS_TIMEOUT = 1000
     14

     15  #

     16  #  Provides simple piped I/O to an mplayer process.

     17  #

     18 -class Mplayer:
     19

     20          pymp, mplayerIn, mplayerOut = None, None, None
     21          inputHandler, eofHandler, statusQuery = 0, 0, 0
     22          paused = False
     23          streamTitle = ""
     24          streamTitleChangeListeners = []
     25

     26          #

     27          #  Initializes this Mplayer with the specified Pymp.

     28          #

     29 -        def __init__(self, pymp):
     30                  self.pymp = pymp
     31

     32          #

     33          #   Plays the specified target.

     34          #

     35 -        def play(self, target):
     36

     37                  mpc = "mplayer -slave -quiet " + target + " 2>/dev/null"
     38

     39                  self.mplayerIn, self.mplayerOut = os.popen2(mpc)  #open pipe
     40                  fcntl.fcntl(self.mplayerOut, fcntl.F_SETFL, os.O_NONBLOCK)
     41

     42                  self.startInputHandler()
     43                  self.startEofHandler()
     44                  self.startStatusQuery()
     45

     46          #

     47          #  Issues command to mplayer.

     48          #
     49
     50 -        def record(self, target, savefile):
     51

     52                  mpc = "mplayer -slave -quiet " + target + " -ao pcm:file=" + savefile
     53

     54                  self.mplayer_record_In, self.mplayer_record_Out = os.popen2(mpc)  #open pipe
     55                  fcntl.fcntl(self.mplayer_record_Out, fcntl.F_SETFL, os.O_NONBLOCK)
     56

     57

     58          #

     59          #  Issues command to mplayer.

     60          #
     61

     62 -        def cmd(self, command):
     63

     64                  if not self.mplayerIn:
     65                          return
     66

     67                  try:
     68                          self.mplayerIn.write(command + "\n")
     69                          self.mplayerIn.flush()  #flush pipe
     70                  except StandardError:
     71                          return
     72

     73          #

     74          #  Toggles pausing of the current mplayer job and status query.

     75          #

     76 -        def pause(self):
     77                  if not self.mplayerIn:
     78                          return
     79

     80                  if self.paused:  #unpause
     81                          self.startStatusQuery()
     82                          self.paused = False
     83

     84                  else:  #pause
     85                          self.stopStatusQuery()
     86                          self.paused = True
     87

     88                  self.cmd("pause")
     89

     90          #

     91          #  Seeks the amount using the specified mode.  See mplayer docs.

     92          #

     93 -        def seek(self, amount, mode=0):
     94                  pass
     95

     96          #

     97          #  Cleanly closes any IPC resources to mplayer.

     98          #

     99 -        def close(self):
    100                  self.stopStatusQuery()  #cancel query
    101                  self.stopEofHandler()  #cancel eof monitor
    102                  self.stopInputHandler() #cancel input monitor
    103

    104                  if self.paused:  #untoggle pause to cleanly quit
    105                          self.pause()
    106

    107                  self.cmd("quit")  #ask mplayer to quit
    108

    109                  try:
    110                          self.mplayerIn.close()   #close pipes
    111                          self.mplayerOut.close()
    112                  except StandardError:
    113                          pass
    114

    115                  self.mplayerIn, self.mplayerOut = None, None
    116                  #self.pymp.control.setProgress(-1)  #reset bar
    117
            def close_record(self):

    118

    119                  try:
    120                          self.mplayer_record_In.write("quit\n")
    121                          self.mplayer_record_In.flush()  #flush pipe
    122                  except StandardError:
    123                          return
    124

    125                  #self.cmd("quit")  #ask mplayer to quit

    126

    127                  try:
    128
    129                          self.mplayer_record_In.close()   #close pipes_record_
    130                          self.mplayer_record_Out.close()
    131                  except StandardError:
    132                          pass
    133

    134                  self.mplayer_record_In, self.mplayer_record_Out = None, None
    135          #

    136          #  Triggered when mplayer's stdout reaches EOF.

    137          #

    138 -        def handleEof(self, source, condition):
    139

    140                  self.stopStatusQuery()  #cancel query
    141

    142                  self.mplayerIn, self.mplayerOut = None, None
    143

    144          #       if self.pymp.playlist.continuous:  #play next target

    145          #               self.pymp.playlist.next(None, None)

    146          #       else:  #reset progress bar

    147          #               self.pymp.control.setProgress(-1)

    148

    149                  return False
    150

    151          #

    152          #  Triggered when mplayer's stdout reaches EOF.

    153          #

    154 -        def handleInput(self, source, condition):
    155                  try:
    156                      for line in self.mplayerOut:
    157                          self.lookForStreamTitle(line)
    158                  finally:
    159                          return True
    160

    161          #

    162          #  Triggered when mplayer prints something stdout.

    163          #

    164 -        def lookForStreamTitle(self, line):
    165                  matches = re.search("(?<=StreamTitle=\')(.*)(\';StreamUrl=)", line)
    166                  if matches:
    167                          self.streamTitle = matches.group(1)
    168                          for listener in self.streamTitleChangeListeners:
    169                                  keepListener = listener(self, self.streamTitle)
    170                                  if not keepListener:
    171                                          self.streamTitleChangeListeners.remove(listener)
    172

    173          #

    174          #  Queries mplayer's playback status and upates the progress bar.

    175          #

    176 -        def queryStatus(self):
    177

    178                  self.cmd("get_percent_pos")  #submit status query
    179                  self.cmd("get_time_pos")
    180

    181                  time.sleep(0.05)  #allow time for output
    182

    183                  line, percent, seconds = None, -1, -1
    184

    185                  while True:
    186                          try:  #attempt to fetch last line of output
    187                                  line = self.mplayerOut.readline()
    188                          except StandardError, detail:
    189                                  break
    190

    191                          if not line: break
    192

    193                          if line.startswith("ANS_PERCENT_POSITION"):
    194                                  percent = int(line.replace("ANS_PERCENT_POSITION=", ""))
    195

    196                          if line.startswith("ANS_TIME_POSITION"):
    197                                  seconds = float(line.replace("ANS_TIME_POSITION=", ""))
    198

    199                  #self.pymp.control.setProgress(percent, seconds)

    200                  return True
    201

    202          #

    203          #  Add a listener that will be called every time a change in stream title is detected.

    204          #  The signature of the callback should be:

    205          #       def callback(source, newStreamTitle)

    206          #

    207 -        def addStreamTitleChangeListener(self, callback):
    208                  self.streamTitleChangeListeners.append(callback)
    209

    210          #

    211          #  Removes a stream title change listener.

    212          #

    213 -        def removeStreamTitleChangeListener(self, callback):
    214                  self.streamTitleChangeListeners.remove(callback)
    215

    216          #

    217          #  Inserts the status query monitor.

    218          #

    219 -        def startStatusQuery(self):
    220                  self.statusQuery = gobject.timeout_add(STATUS_TIMEOUT, self.queryStatus)
    221

    222          #

    223          #  Removes the status query monitor.

    224          #

    225 -        def stopStatusQuery(self):
    226                  if self.statusQuery:
    227                          gobject.source_remove(self.statusQuery)
    228                  self.statusQuery = 0
    229

    230          #

    231          #  Inserts the EOF monitor.

    232          #

    233 -        def startEofHandler(self):
    234                  self.eofHandler = gobject.io_add_watch(self.mplayerOut, gobject.IO_HUP, self.handleEof)
    235

    236          #

    237          #  Removes the EOF monitor.

    238          #

    239 -        def stopEofHandler(self):
    240                  if self.eofHandler:
    241                          gobject.source_remove(self.eofHandler)
    242                  self.eofHandler = 0
    243

    244          #

    245          #  Inserts the input monitoy.

    246          #

    247 -        def startInputHandler(self):
    248                  self.inputHandler = gobject.io_add_watch(self.mplayerOut, gobject.IO_IN, self.handleInput)
    249

    250          #

    251          #  Removes the EOF monitor.

    252          #

    253 -        def stopInputHandler(self):
    254                  if self.inputHandler:
    255                          gobject.source_remove(self.inputHandler)
    256                  self.inputHandler = 0
    257

    258  #End of file
    259