#-----------------------------------------------------------------------------
# Name:        VPConsumerService.py
# Purpose:
#
# Author:      Thomas D. Uram
#
# Created:     2003/06/02
# Copyright:   (c) 2002
# Licence:     See COPYING.TXT
#-----------------------------------------------------------------------------
import sys, os
try:    import _winreg
except: pass
import socket

from AccessGrid.Types import Capability
from AccessGrid.AGService import AGService
from AccessGrid.AGParameter import ValueParameter, OptionSetParameter, RangeParameter, TextParameter
from AccessGrid import Platform
from AccessGrid.Platform.Config import AGTkConfig, UserConfig, SystemConfig
from AccessGrid.NetworkLocation import MulticastNetworkLocation

class VPConsumerService( AGService ):

    def __init__( self ):
        AGService.__init__( self )

        self.capabilities = [ Capability( Capability.CONSUMER, Capability.VIDEO ) ]
        self.executable = os.path.join('.','vp')

        #
        # Set configuration parameters
        #
        self.sysConf = SystemConfig.instance()

	self.fasttransitions = OptionSetParameter( "FastTransitions", "enable", [ "enable", "disable" ] )
	self.fasttransitionsport = TextParameter( "FastTransitionsPort", "9000" )

	self.slavemode = OptionSetParameter( "SlaveMode", "disable", ["enable", "disable" ] )

	self.configuration.append( self.fasttransitions )
	self.configuration.append( self.fasttransitionsport )
	self.configuration.append( self.slavemode )
	
        pass


    def __SetRTPDefaults(self, profile):
        """
        Set values used by rat for identification
        """
        if profile == None:
            self.log.exception("Invalid profile (None)")
            raise Exception, "Can't set RTP Defaults without a valid profile."

        if sys.platform == 'linux2':
            try:
                rtpDefaultsFile=os.path.join(os.environ["HOME"], ".RTPdefaults")
                rtpDefaultsText="*rtpName: %s\n*rtpEmail: %s\n*rtpLoc: %s\n*rtpPhone: \
                                 %s\n*rtpNote: %s\n"
                rtpDefaultsFH=open( rtpDefaultsFile,"w")
                rtpDefaultsFH.write( rtpDefaultsText % ( profile.name,
                                       profile.email,
                                       profile.location,
                                       profile.phoneNumber,
                                       profile.publicId ) )
                rtpDefaultsFH.close()
            except:
                self.log.exception("Error writing RTP defaults file: %s", rtpDefaultsFile)

        elif sys.platform == 'win32':
            try:
                #
                # Set RTP defaults according to the profile
                #
                k = _winreg.CreateKey(_winreg.HKEY_CURRENT_USER,
                                    r"Software\Mbone Applications\common")

                # Vic reads these values (with '*')
                _winreg.SetValueEx(k, "*rtpName", 0,
                                   _winreg.REG_SZ, profile.name)
                _winreg.SetValueEx(k, "*rtpEmail", 0,
                                   _winreg.REG_SZ, profile.email)
                _winreg.SetValueEx(k, "*rtpPhone", 0,
                                   _winreg.REG_SZ, profile.phoneNumber)
                _winreg.SetValueEx(k, "*rtpLoc", 0,
                                   _winreg.REG_SZ, profile.location)
                _winreg.SetValueEx(k, "*rtpNote", 0,
                                   _winreg.REG_SZ, str(profile.publicId) )
                _winreg.CloseKey(k)
            except:
                self.log.exception("Error writing RTP defaults to registry")
        
    def Start( self ):
        __doc__ = """Start service"""

	self.log.info("VP: asked to start")

        try:

	    title = ""
            stream = ""

            #
            # Start the service; in this case, store command line args in a list and let
            # the superclass _Start the service
            options = []

	    if self.slavemode.value == "enable":
		options.append( "--slave" )

            if self.streamDescription.name and len(self.streamDescription.name.strip()) > 0:
                options.append( "-C" )
                title = self.streamDescription.name 
                options.append( title )
            if self.streamDescription.encryptionFlag != 0:
                options.append( "-K" )
                options.append( self.streamDescription.encryptionKey )
            # Check whether the network location has a "type" attribute
            # Note: this condition is only to maintain compatibility between
            # older venue servers creating network locations without this attribute
            # and newer services relying on the attribute; it should be removed
            # when the incompatibility is gone
            if self.streamDescription.location.__dict__.has_key("type"):
                if self.streamDescription.location.type == MulticastNetworkLocation.TYPE:
                    options.append( "-t" )
                    options.append( '%d' % ( self.streamDescription.location.ttl ) )

            # Add address/port options (these must occur last; don't add options beyond here)
            stream = '%s/%d' % ( self.streamDescription.location.host,
                                 self.streamDescription.location.port )
            options.append( stream )

	    if not self.RemoteStartStream( title, stream ):

            	self.log.info("Starting VPConsumerService")
            	self.log.info(" executable = %s" % self.executable)
            	self.log.info(" options = %s" % options)
            	self._Start( options )

        except:
            self.log.exception("Exception in VPConsumerService.Start")
            raise Exception("Failed to start service")
    Start.soap_export_as = "Start"

    def Stop( self ):
        """Stop the service"""

	self.log.info("VP: asked to stop")

        # vic doesn't die easily (on linux at least), so force it to stop
	stream = '%s/%d' % ( self.streamDescription.location.host,
                             self.streamDescription.location.port )
	if not self.RemoteStopStream( stream ):
        	AGService.ForceStop(self)

    Stop.soap_export_as = "Stop"


    def ConfigureStream( self, streamDescription ):
        """Configure the Service according to the StreamDescription"""
	
	self.log.info("VP: asked to configure")

        ret = AGService.ConfigureStream( self, streamDescription )
        if ret and self.started:
            # service is already running with this config; ignore
            return

        # if started, stop
        if self.started:
       	    self.Stop()

	# if enabled, start
	if self.enabled:
            self.Start()


    ConfigureStream.soap_export_as = "ConfigureStream"

    def SetIdentity(self, profile):
        """
        Set the identity of the user driving the node
        """
        self.__SetRTPDefaults(profile)
    SetIdentity.soap_export_as = "SetIdentity"

    def RemoteConfigure(self, oldstream):

	if len(oldstream) > 0:
		if not self.RemoteStopStream(oldstream):
			return False

	newstream = "%s/%d" % (self.streamDescription.location.host, 
                               self.streamDescription.location.port)
	if not self.RemoteStartStream(newstream):
		return False

	return True
	
    def RemoteStopStream(self, stream):
	if self.fasttransitions.value != "enable":
		return False

	msg = "stream.stop \"%s\"" % stream
	expected_response = "stoping stream %s\n" % stream

	return (self.RemoteSendCommand( msg ) == expected_response)

    def RemoteStartStream(self, title, stream):
	if self.fasttransitions.value != "enable":
		return False

	msg = "stream.start \"%s\"" % stream
	expected_response = "starting stream %s\n" % stream

	return (self.RemoteSendCommand( msg ) == expected_response)

    def RemoteSendCommand(self, msg):
        try:
		sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
       		sock.connect(('localhost', 9000))

		sock.sendall(msg + "\n")

		response = sock.recv(256)

		sock.close()

		print "RemoteSendCommand: sent: %s" % msg
		print "RemoteSendCommand:  got: %s" % response

		return response
	except socket.error, e:
		self.log.info( "RemoteSendCommand exception %s" % e )


if __name__ == '__main__':

    from AccessGrid.AGService import AGServiceI, RunService

    service = VPConsumerService()
    serviceI = AGServiceI(service)
    RunService(service,serviceI,int(sys.argv[1]))
