screenlets.plugins.Mplayer

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