Package x2go :: Module pulseaudio
[frames] | no frames]

Source Code for Module x2go.pulseaudio

  1  # -*- coding: utf-8 -*- 
  2   
  3  # Copyright (C) 2010-2014 by Mike Gabriel <mike.gabriel@das-netzwerkteam.de> 
  4  # 
  5  # Python X2Go is free software; you can redistribute it and/or modify 
  6  # it under the terms of the GNU Affero General Public License as published by 
  7  # the Free Software Foundation; either version 3 of the License, or 
  8  # (at your option) any later version. 
  9  # 
 10  # Python X2Go is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 13  # GNU Affero General Public License for more details. 
 14  # 
 15  # You should have received a copy of the GNU Affero General Public License 
 16  # along with this program; if not, write to the 
 17  # Free Software Foundation, Inc., 
 18  # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 
 19  # 
 20  # Other contributors: 
 21  #       none so far 
 22   
 23  """\ 
 24  X2GoPulseAudio class - a Pulseaudio daemon guardian thread. 
 25   
 26  """ 
 27   
 28  __NAME__ = 'x2gopulseaudio-pylib' 
 29   
 30  from defaults import X2GOCLIENT_OS as _X2GOCLIENT_OS 
 31  if _X2GOCLIENT_OS == 'Windows': 
 32      import win32process 
 33      import win32con 
 34      import win32event 
 35   
 36  # modules 
 37  import os 
 38  import threading 
 39  import gevent 
 40  import copy 
 41  import socket 
 42   
 43  from defaults import LOCAL_HOME as _LOCAL_HOME 
 44   
 45  # Python X2Go modules 
 46  import log 
 47   
 48  import exceptions 
49 -class OSNotSupportedException(exceptions.StandardError): pass
50 """ Exception denoting that this operating system is not supported. """ 51
52 -class X2GoPulseAudio(threading.Thread):
53 """ 54 This class controls the Pulse Audio daemon. 55 """ 56
57 - def __init__(self, path=None, client_instance=None, logger=None, loglevel=log.loglevel_DEFAULT):
58 """\ 59 Initialize a Pulse Audio daemon instance. 60 61 @param path: full path to pulseaudio.exe 62 @type path: C{str} 63 @param client_instance: the calling L{X2GoClient} instance 64 @type client_instance: L{X2GoClient} instance 65 @param logger: you can pass an L{X2GoLogger} object to the L{X2GoClientXConfig} constructor 66 @type logger: C{obj} 67 @param loglevel: if no L{X2GoLogger} object has been supplied a new one will be 68 constructed with the given loglevel 69 @type loglevel: C{int} 70 71 @raise OSNotSupportedException: on non-Windows platforms Python X2Go presumes that pulseaudio is already launched 72 73 """ 74 if _X2GOCLIENT_OS not in ("Windows"): 75 raise OSNotSupportedException('classes of x2go.pulseaudio module are for Windows only') 76 77 if logger is None: 78 self.logger = log.X2GoLogger(loglevel=loglevel) 79 else: 80 self.logger = copy.deepcopy(logger) 81 self.logger.tag = __NAME__ 82 83 self.path = path 84 self.client_instance = client_instance 85 self._keepalive = None 86 87 threading.Thread.__init__(self) 88 self.daemon = True 89 self.start()
90
91 - def run(self):
92 """\ 93 This method is called once the C{X2GoPulseAudio.start()} method has been called. To tear 94 down the Pulseaudio daemon call the L{X2GoPulseAudio.stop_thread()} method. 95 96 """ 97 self._keepalive = True 98 cmd = 'pulseaudio.exe' 99 cmd_options = [ 100 '-n', 101 '--exit-idle-time=-1', 102 '-L "module-native-protocol-tcp port=4713"', 103 '-L "module-esound-protocol-tcp port=16001"', 104 '-L module-waveout', 105 ] 106 cmd_options = " %s" % " ".join(cmd_options) 107 108 if not os.path.isdir(os.path.join(_LOCAL_HOME, '.pulse', '%s-runtime' % socket.gethostname())): 109 os.makedirs(os.path.join(_LOCAL_HOME, '.pulse', '%s-runtime' % socket.gethostname())) 110 self.logger('starting PulseAudio server with command line: %s%s' % (cmd, cmd_options), loglevel=log.loglevel_DEBUG) 111 112 si = win32process.STARTUPINFO() 113 p_info = win32process.CreateProcess(None, 114 '%s\\%s %s' % (self.path, cmd, cmd_options), 115 None, 116 None, 117 0, 118 win32con.CREATE_NO_WINDOW|win32process.NORMAL_PRIORITY_CLASS, 119 None, 120 None, 121 si, 122 ) 123 (hProcess, hThread, processId, threadId) = p_info 124 125 gevent.sleep(5) 126 rc = win32event.WaitForMultipleObjects([hProcess], 127 1, 128 1, # wait just one millisec 129 ) 130 _is_alive = ( rc != win32event.WAIT_OBJECT_0 ) 131 if self.client_instance and not _is_alive: 132 if os.environ.has_key('CLIENTNAME'): 133 self.client_instance.HOOK_pulseaudio_not_supported_in_RDPsession() 134 else: 135 self.client_instance.HOOK_pulseaudio_server_startup_failed() 136 137 while self._keepalive and _is_alive: 138 gevent.sleep(1) 139 rc = win32event.WaitForMultipleObjects([hProcess], 140 1, 141 1, # wait just one millisec 142 ) 143 _is_alive = ( rc != win32event.WAIT_OBJECT_0 ) 144 if self.client_instance and not _is_alive: 145 self.client_instance.HOOK_pulseaudio_server_died() 146 147 self.logger('terminating running PulseAudio server', loglevel=log.loglevel_DEBUG) 148 149 # there is no real kill command on Windows... 150 self.logger('PulseAudio process ID to terminate: %s' % processId, loglevel=log.loglevel_DEBUG) 151 try: 152 win32process.TerminateProcess(hProcess, 0) 153 except win32process.error: 154 pass
155
156 - def stop_thread(self):
157 """\ 158 Tear down a running Pulseaudio daemon. 159 160 """ 161 self.logger('stop_thread() method has been called', loglevel=log.loglevel_DEBUG) 162 self._keepalive = False
163