Example #1
0
    def _do_notify(self, usn):
        """ Do a notification for the usn specified.

        @param usn: st
        @type usn: string
        """
        log.debug('Sending alive notification for %s', usn)
        response = [
            'NOTIFY * HTTP/%s' % self.http_version,
            'HOST: %s:%d' % (SSDP_ADDR, SSDP_PORT),
            'NTS: ssdp:alive',
        ]
        stcpy = dict(self.advertised[usn].iteritems())
        stcpy['NT'] = stcpy['ST']
        del stcpy['EXT']
        del stcpy['ST']
        response.extend(map(lambda x: ': '.join(x), stcpy.iteritems()))
        append = response.append
        [append('%s: %s' % (k, v)) for k, v in self.additional_headers.items()]
        response.extend(('', ''))
        log.debug('Sending notify message with content %s' % response)
        try:
            self.udp_transport.send_data('\r\n'.join(response), SSDP_ADDR,
                                         SSDP_PORT)
            self.udp_transport.send_data('\r\n'.join(response), SSDP_ADDR,
                                         SSDP_PORT)
        except Exception, e:
            log.info("Failure sending notify with message %s" % str(e))
Example #2
0
 def double_discover(self, search_type=DEFAULT_SEARCH_TYPE):
     """ Sends a MSearch imediatelly. Each call to this method will yield a
     MSearch message, that is, it won't repeat automatically.
     """
     log.info("Doing double discover for %s", search_type)
     self.discover(search_type)
     self.discover(search_type)
Example #3
0
 def load_plugins(self):
     """ Instantiates plugins and loads them using PluginLoader.
     """
     self._instantiate_plugins()
     names = [p.name for p in self.plugins_instances.values() if p.name != "rootplugin"]
     log.info("Detected plugins: %s", ", ".join(names))
     self._load_plugins()
Example #4
0
 def load_plugins(self):
     """ Instantiates plugins and loads them using PluginLoader.
     """
     self._instantiate_plugins()
     names = [p.name for p in self.plugins_instances.values() \
              if p.name!='rootplugin']
     log.info('Detected plugins: %s', ', '.join(names))
     self._load_plugins()
Example #5
0
 def play(self):
     if self.av_uri is not None:
         if (self.player.set_state(gst.STATE_PLAYING) ==
             gst.STATE_CHANGE_FAILURE):
             log.error("error trying to play %s.", self.av_uri)
         self.player_state = 1
     else:
         log.info("av_uri is None, unable to play.")
Example #6
0
 def play(self):
     if self.av_uri is not None:
         if (self.player.set_state(
                 gst.STATE_PLAYING) == gst.STATE_CHANGE_FAILURE):
             log.error("error trying to play %s.", self.av_uri)
         self.player_state = 1
     else:
         log.info("av_uri is None, unable to play.")
Example #7
0
 def lookup_function(self, function_name):
     """ Lookup published SOAP function.
     """
     log.info('Finding service action %s' % function_name)
     for action_name, action in self.service._actions.iteritems():
         if action_name == function_name:
             return action
     log.info('Action %s not founded' % function_name)
     return None
Example #8
0
    def _load_plugin(self, plugin):
        """ Loads a plugin using PluginLoader.

        @param plugin: plugin instance to be loaded
        @type plugin: Plugin
        """
        log.info('Loading plugin %s', plugin.name)
        plugin.plugin_manager = self
        plugin.execute()
    def soap_Previous(self, *args, **kwargs):
        """Advance to the previous track.

        This is a convenient action to advance to the previous track. This
        action is functionally equivalent to Seek(TRACK_NR, CurrentTrackNr-1).
        This action does not cycle back to the last track."""

        log.info('Previous()')
        return {}
Example #10
0
    def _load_plugin(self, plugin):
        """ Loads a plugin using PluginLoader.

        @param plugin: plugin instance to be loaded
        @type plugin: Plugin
        """
        log.info("Loading plugin %s", plugin.name)
        plugin.plugin_manager = self
        plugin.execute()
Example #11
0
 def play(self):
     if self.av_uri is not None:
         if self.player.set_state(gst.STATE_PLAYING) == \
              gst.STATE_CHANGE_FAILURE:
             log.error("gst_renderer error while trying to play")
             return
         self.player_state = 1
     else:
         log.info("av_uri is None, unable to play.")
Example #12
0
 def play(self):
     if self.av_uri is not None:
         if self.player.set_state(gst.STATE_PLAYING) == \
              gst.STATE_CHANGE_FAILURE:
             log.error("gst_renderer error while trying to play")
             return
         self.player_state = 1
     else:
         log.info("av_uri is None, unable to play.")
Example #13
0
 def lookup_function(self, function_name):
     """ Lookup published SOAP function.
     """
     log.info('Finding service action %s' % function_name)
     for action_name, action in self.service._actions.iteritems():
         if action_name == function_name:
             return action
     log.info('Action %s not founded' % function_name)
     return None
Example #14
0
    def soap_Next(self, *args, **kwargs):
        """Advance to the next track.

        This is a convenient action to advance to the next track. This
        action is functionally equivalent to Seek(TRACK_NR, CurrentTrackNr+1).
        This action does not cycle back to the first track."""

        log.info('Next()')
        return {}
Example #15
0
    def double_discover(self, search_type=DEFAULT_SEARCH_TYPE,
    			http_version="1.1", man='"ssdp:discover"', mx=1,
			additionals={}):
        """ Sends a MSearch imediatelly. Each call to this method will yield a
        MSearch message, that is, it won't repeat automatically.
        """
        log.info("Doing double discover for %s, HTTP_VERSION=%s, MAN=%s, \
		 MX=%d, additionals=%s" % (search_type, http_version, man, mx,
		 			   additionals))
        self.discover(search_type, http_version, man, mx, additionals)
Example #16
0
    def double_discover(self,
                        search_type=DEFAULT_SEARCH_TYPE,
                        http_version="1.1",
                        man='"ssdp:discover"',
                        mx=1,
                        additionals={}):
        """ Sends a MSearch imediatelly. Each call to this method will yield a
        MSearch message, that is, it won't repeat automatically.
        """
        log.info("Doing double discover for %s, HTTP_VERSION=%s, MAN=%s, \
		 MX=%d, additionals=%s" % (search_type, http_version, man, mx, additionals))
        self.discover(search_type, http_version, man, mx, additionals)
Example #17
0
    def soap_GetTransportSettings(self, *args, **kwargs):
        """Return information on various settings of instance.

        This action returns information on various settings of the
        specified instance, such as the current play mode and the
        current recording quality mode. This action has no effect on
        state."""

        log.info('GetTransportSettings()')

        return {'PlayMode': 'DIRECT_1',
                                        'ReqQualityMode': 'NOT_IMPLEMENTED'}
Example #18
0
    def soap_Stop(self, *args, **kwargs):
        """Stop progression of current resource.

        This action stops the progression of the current resource that
        is associated with the specified instance."""

        log.info('Stop()')
        self.transport_state = 'TRANSITIONING'
        self.gst_player.stop()
        self.transport_state = 'STOPPED'

        return {}
Example #19
0
    def soap_Seek(self, *args, **kwargs):
        """Seek through the resource controlled.

        This action starts seeking through the resource controlled
        by the specified instance - as fast as possible - to the position,
        specified in the Target argument."""

        (instance_id, unit, target) = args

        self.gst_player.seek(unit, target)

        log.info('Seek()')
        return {}
Example #20
0
    def soap_GetDeviceCapabilities(self, *args, **kwargs):
        """Return information on device capabilities.

        This action returns information on device capabilities of
        the specified instance, such as the supported playback and
        recording formats, and the supported quality levels for
        recording. This action has no effect on state."""

        log.info('GetDeviceCapabilities()')

        return {'PlayMedia': 'NONE',
                                        'RecMedia': 'NOT_IMPLEMENTED',
                                        'ReqQualityMode': 'NOT_IMPLEMENTED'}
Example #21
0
    def _removed_device_event(self, device_info):
        """ Receives a removed device event.

        @param device_info: information about the device

        @type device_info: dict
        """
        udn = device_info['USN'].split('::')[0]
        if udn in self._known_devices:
            log.info('Device is gone: %s' %
                     self._known_devices[udn].friendly_name)

        self._known_devices.pop(udn, None)
        self._callback("removed_device_event", udn)
Example #22
0
    def _publish(self):
        assert self.webserver is not None, 'Device was told not to create '\
                                           'webserver (with False on the '\
                                           'create_webserver parameter) and'\
                                           'device.webserver was not set'\
                                           'manually as it should.'
        log.info('Publishing device %s' % self.friendly_name)
        DeviceXMLBuilder(self).generate_to_file(self._xml_filepath)
        self.webserver.add_static_file(webserver.StaticFile(self.xml_filename,
                                                            self._xml_filepath))

        log.info('Publishing device\'s services')
        for v in self.services.values():
            v.publish(self.webserver)
Example #23
0
    def _removed_device_event(self, device_info):
        """ Receives a removed device event.

        @param device_info: information about the device

        @type device_info: dict
        """
        udn = device_info['USN'].split('::')[0]
        if udn in self._known_devices:
            log.info('Device is gone: %s' %
                     self._known_devices[udn].friendly_name)

        self._known_devices.pop(udn, None)
        self._callback("removed_device_event", udn)
Example #24
0
    def soap_Play(self, *args, **kwargs):
        """Play the resource of instance.

        This action starts playing the resource of the specified
        instance, at the specified speed, starting at the current
        position, according to the current play mode."""

        log.info('Play()')
        log.debug('Playing uri: %r', self.gst_player.av_uri)
        self.transport_state = 'TRANSITIONING'

        self.gst_player.play()

        self.transport_state = 'PLAYING'
        return {}
Example #25
0
    def soap_Pause(self, *args, **kwargs):
        """Pause the resouce of instance.

        This action starts playing the resource of the specified
        instance, at the specified speed, starting at the current
        position, according to the current play mode."""

        log.info('Pause()')

        self.transport_state = 'TRANSITIONING'

        self.gst_player.pause()

        self.transport_state = 'PAUSED_PLAYBACK'
        return {}
Example #26
0
    def soap_GetMediaInfo(self, *args, **kwargs):
        """Return information of current Media.

        This action returns information associated with the current
        media of the specified instance; it has no effect on state."""

        log.info('GetMediaInfo()')

        return {'NrTracks': str(self.number_of_tracks),
                'MediaDuration': str(self.gst_player.query_duration()[0]),
                'CurrentURI': self.av_transport_uri,
                'CurrentURIMetaData': '',
                'NextURI': '', 'NextURIMetaData': '',
                'PlayMedium': 'NETWORK',
                'RecordMedium': '',
                'WriteStatus': ''}
Example #27
0
    def _new_device_event_impl(self, device_info, device):
        """ Real implementation of the new device event handler.

        @param device_info: informations about the device
        @param device: the device object itself

        @type device_info: dict
        @type device: Device
        """
        if not device and self._ssdp_server:
            # Device creation failed, tell SSDPSearch to forget it
            self._ssdp_server.discovered_device_failed(device_info)
            return

        self._known_devices[device.udn] = device
        self._callback("new_device_event", device)
        log.info('Device found: %s' % device.friendly_name)
Example #28
0
    def publish(self, webserver):
        log.info("Publishing service %s" % self.id)

        if not len(self.get_variables()):
            raise InvalidService("The service must have one " "or more state variables")

        res = webserver.CustomResource(self.id)
        if self._create_xml:
            ServiceXMLBuilder(self).generate_to_file(self._xml_filepath)
        f = webserver.StaticFile("scpd.xml", self._xml_filepath)
        res.add_static_file(f)

        for k in ["control", "eventSub", "presentation"]:
            controller = getattr(self, "%s_controller" % k)
            if controller:
                res.add_resource(controller)

        webserver.add_resource(res)
Example #29
0
    def _new_device_event_impl(self, device_info, device):
        """ Real implementation of the new device event handler.

        @param device_info: informations about the device
        @param device: the device object itself

        @type device_info: dict
        @type device: Device
        """
        if not device and self._ssdp_server:
            # Device creation failed, tell SSDPSearch to forget it
            self._ssdp_server.discovered_device_failed(device_info)
            return

        device.additional_headers = device_info['ADDITIONAL_HEADERS']
        self._known_devices[device.udn] = device
        self._callback("new_device_event", device)
        log.info('Device found: %s' % device.friendly_name)
Example #30
0
    def publish(self, webserver):
        log.info('Publishing service %s' % self.id)

        if not len(self.get_variables()):
            raise InvalidService('The service must have one '\
                                        'or more state variables')

        res = webserver.CustomResource(self.id)
        if self._create_xml:
            ServiceXMLBuilder(self).generate_to_file(self._xml_filepath)
        f = webserver.StaticFile('scpd.xml', self._xml_filepath)
        res.add_static_file(f)

        for k in ['control', 'eventSub', 'presentation']:
            controller = getattr(self, '%s_controller' % k)
            if controller:
                res.add_resource(controller)

        webserver.add_resource(res)
Example #31
0
    def soap_SetAVTransportURI(self, *args, **kwargs):
        """Specifies the URI of resource.

        This action specifies the URI of the resource to be controlled
        by the specified AVTransport instance. It is RECOMMENDED that the
        AVTransport service checks the MIME-type of the specified resource
        when executing this action"""

        instance_id = kwargs['InstanceID']
        current_uri = kwargs['CurrentURI']
        current_uri_metadata = kwargs['CurrentURIMetaData']

        self.av_transport_uri = current_uri
        self.number_of_tracks = 1
        self.gst_player.av_uri = current_uri
        self.transport_state = 'STOPPED'

        log.info('SetAVTransportURI(%s, %s, %s)' % (instance_id, current_uri,
                 current_uri_metadata))
        return {}
Example #32
0
    def soap_GetMediaInfo_Ext(self, *args, **kwargs):
        """Return information of current Media and CurrentType argment.

        This action returns information associated with the current
        media of the specified instance; it has no effect on state.The
        information returned is identical to the information returned
        by the GetMediaInfo() action, except for the additionally
        returned CurrentType argument """

        log.info('GetMediaInfo_Ext()')

        return {'CurrentType': 'TRACK_UNAWARE',
                'NrTracks': str(self.number_of_tracks),
                'MediaDuration': str(self.gst_player.query_duration()[0]),
                'CurrentURI': self.av_transport_uri,
                'CurrentURIMetaData': '',
                'NextURI': '', 'NextURIMetaData': '',
                'PlayMedium': 'NETWORK',
                'RecordMedium': '',
                'WriteStatus': ''}
Example #33
0
    def _new_device_event_impl(self, device_info, device):
        """ Real implementation of the new device event handler.

        @param device_info: informations about the device
        @param device: the device object itself

        @type device_info: dict
        @type device: Device
        """

        #        print "control_point _new_device_event_impl udn: " + str(device.udn)

        log.debug('device_info: %s, device: %s', device_info, device)

        if not device and self._ssdp_server:
            # Device creation failed, tell SSDPSearch to forget it
            self._ssdp_server.discovered_device_failed(device_info)
            return

        self._known_devices[device.udn] = device
        self._callback("new_device_event", device)
        log.info('Device found: %s' % device.friendly_name)
Example #34
0
    def _do_notify(self, usn):
        """ Do a notification for the usn specified.

        @param usn: st
        @type usn: string
        """
        log.debug('Sending alive notification for %s', usn)
        response = ['NOTIFY * HTTP/%s' % self.http_version,
		'HOST: %s:%d' % (SSDP_ADDR, SSDP_PORT),
                'NTS: ssdp:alive', ]
        stcpy = dict(self.advertised[usn].iteritems())
        stcpy['NT'] = stcpy['ST']
        del stcpy['EXT']
        del stcpy['ST']
        response.extend(map(lambda x: ': '.join(x), stcpy.iteritems()))
	append = response.append
	[append('%s: %s' % (k, v)) for k, v in self.additional_headers.items()]
        response.extend(('', ''))
	log.debug('Sending notify message with content %s' % response)
	try:
	    self.udp_transport.send_data('\r\n'.join(response), SSDP_ADDR, SSDP_PORT)
            self.udp_transport.send_data('\r\n'.join(response), SSDP_ADDR, SSDP_PORT)
	except Exception, e:
	    log.info("Failure sending notify with message %s" % str(e))
Example #35
0
 def start(self):
     """ Starts the device.
     """
     log.info('Starting device %s' % self.friendly_name)
     log.info('Starting device\'s services')
     for k, v in self.services.items():
         try:
             log.info('Starting service %s' % k)
             v.start()
         except Exception, e:
             log.error('Error starting service %s: %s' % (k, e))
Example #36
0
    def main(self):
        """ Enters the RUNNING state by running the main loop until
        main_quit() is called.
        """
        if self.state != REACTOR_STATE_STOPPED:
            raise ReactorAlreadyRunningException('main() called twice or '\
                'together with main_loop_iterate()')

        self.state = REACTOR_STATE_RUNNING
        log.info('Preparing main loop')
        self._main_call_before_start_funcs()
        log.info('Entering main loop')
        while self.state == REACTOR_STATE_RUNNING:
            try:
                if not self.main_loop_iterate():
                    break
            except:
                break
        log.info('Preparing to exit main loop')
        self._main_call_before_stop_funcs()
        log.info('Exited main loop')
Example #37
0
    def main(self):
        """ Enters the RUNNING state by running the main loop until
        main_quit() is called.
        """
        if self.state != REACTOR_STATE_STOPPED:
            raise ReactorAlreadyRunningException('main() called twice or '\
                'together with main_loop_iterate()')

        self.state = REACTOR_STATE_RUNNING
        log.info('Preparing main loop')
        self._main_call_before_start_funcs()
        log.info('Entering main loop')
        while self.state == REACTOR_STATE_RUNNING:
            try:
                if not self.main_loop_iterate():
                    break
            except:
                break
        log.info('Preparing to exit main loop')
        self._main_call_before_stop_funcs()
        log.info('Exited main loop')
Example #38
0
 def start(self):
     """ Starts the device.
     """
     log.info('Starting device %s' % self.friendly_name)
     log.info('Starting device\'s services')
     for k, v in list(self.services.items()):
         try:
             if self._force_event_reload:
                 v._set_force_event_reload(self._force_event_reload)
             else:
                 if self._event_reload_time:
                     v._set_event_reload_time(self._event_reload_time)
             log.info('Starting service %s' % k)
             v.start()
         except Exception as e:
             log.error('Error starting service %s: %s' % (k, str(e)))
     self._publish()
     self.SSDP.register_device(self)
     self.webserver.start()
     self.SSDP.start()
     self.SSDP.announce_device()
     log.info('Finished starting device %s' % self.friendly_name)
Example #39
0
 def start(self):
     """ Starts the device.
     """
     log.info('Starting device %s' % self.friendly_name)
     log.info('Starting device\'s services')
     for k, v in self.services.items():
         try:
             if self._force_event_reload:
                 v._set_force_event_reload(self._force_event_reload)
             else:
                 if self._event_reload_time:
                     v._set_event_reload_time(self._event_reload_time)
             log.info('Starting service %s' % k)
             v.start()
         except Exception, e:
             log.error('Error starting service %s: %s' % (k, str(e)))
Example #40
0
 def start(self):
     """ Starts the device.
     """
     log.info('Starting device %s' % self.friendly_name)
     log.info('Starting device\'s services')
     for k, v in self.services.items():
         try:
             if self._force_event_reload:
                 v._set_force_event_reload(self._force_event_reload)
             else:
                 if self._event_reload_time:
                     v._set_event_reload_time(self._event_reload_time)
             log.info('Starting service %s' % k)
             v.start()
         except Exception, e:
             log.error('Error starting service %s: %s' % (k, e))
Example #41
0
    def publish(self, webserver):
        log.info('Publishing service %s' % self.id)

        if not len(self.get_variables()):
            raise InvalidService('The service must have one '\
                                        'or more state variables')

        res = webserver.CustomResource(self.id)
        if self._create_xml:
            ServiceXMLBuilder(self).generate_to_file(self._xml_filepath)
        f = webserver.StaticFile('scpd.xml', self._xml_filepath)
        res.add_static_file(f)

        for k in ['control', 'eventSub', 'presentation']:
            log.info('Publishing service, controller %s' % k)
            controller = getattr(self, '%s_controller' % k)
            if controller:
                log.info('Publishing service, controller, add_resource %s' %
                         controller)
                res.add_resource(controller)

        webserver.add_resource(res)
Example #42
0
 def publish_plugins(self, webserver):
     log.info('Publishing plugins for ContentDirectory')
     for v in self.plugins_instances.values():
         v.publish(webserver)
Example #43
0
 def unload_plugins(self):
     """ Unload all plugins.
     """
     for p in self.plugins_instances.values():
         log.info('Unloading plugin %s', p.name)
         p.unload()
Example #44
0
class Device(BaseDevice):
    """ Class that represents a device.

    When used with default settings, usage should be minimized to
    instantiation, start() and stop().

    The special setting is a create_webserver keyword that can be passed during
    construction. If False, it disables the automatic creation of the internal
    webserver for serving device files, so, the user should create his own
    webserver and set Device.webserver to it.
    """

    def __init__(self, *args, **kwargs):
        """ Constructor for the Device class.

        @param device_type: device type as described on the device reference
        @param friendly_name: a friendly name

        Optional parameters follow below:

        @param udn: uuid for the device. If not specified will be
                    automatically generated.
        @param parent: parent device
        @param manufacturer: manufacturer
        @param manufacturer_url: manufacturer url
        @param model_description: model description
        @param model_name: model name
        @param model_number: model number
        @param model_url: model url
        @param serial_number: serial number
        @param upc: upc
        @param presentation_url: presentation url
        @param create_webserver: see class description for more information.
                                 Default value is True and you should normally
                                 don't pass anything
        @param force_listen_url: forces the webserver to listen on a specific
                                 address. If it's not possible to listen on
                                 that address, another random one will be
                                 generated and used automatically.

        @type device_type: string
        @type friendly_name: string
        @type udn: string
        @type parent: Device
        @type manufacturer: string
        @type manufacturer_url: string
        @type model_description: string
        @type model_name: string
        @type model_number: string
        @type model_url: string
        @type serial_number: string
        @type upc: string
        @type presentation_url: string
        @type create_webserver: bool
        @type force_listen_url: url to use for webserver
        """
        create_webserver = kwargs.pop('create_webserver', True)
        force_listen_url = kwargs.pop('force_listen_url', '')
        udp_listener = kwargs.pop('udp_listener', '')
        BaseDevice.__init__(self, *args, **kwargs)
        self._generate_xml()
        self.SSDP = SSDPServer(self.friendly_name, self.xml_filename, udp_listener=udp_listener)
        self.webserver = None
        if create_webserver:
            self._create_webserver(force_listen_url)

    def add_service(self, service):
        """ Adds a service to the device.
        """
        assert self.location, 'service does not have a location attribute yet'\
                              '. It must have a location set before adding '\
                              'services. If you passed create_webserver=Fal'\
                              'se, you must create the webserver in your '\
                              'own fashion and set self.location to the '\
                              'listening URL before adding services. This '\
                              'problem may also occur if you pass an '\
                              'invalid force_listen_url parameter.'
        service.url_base = self.location
        BaseDevice.add_service(self, service)

    def _create_webserver(self, force_listen_url=''):
        if force_listen_url:
            p = network.parse_url(force_listen_url)
            self.webserver = webserver.WebServer(host=p.hostname, port=p.port)
        else:
            self.webserver = webserver.WebServer()

        self.location = self.webserver.get_listen_url()

    def _generate_xml(self):
        self.xml_filename = '%s-root-device.xml' % self.friendly_name
        self.xml_filename = self.xml_filename.replace(' ', '')
        self._xml_filepath = path.join(config.manager.brisa_home, 'tmp_xml')
        if not path.exists(self._xml_filepath):
            mkdir(self._xml_filepath)
        self._xml_filepath = path.join(self._xml_filepath, self.xml_filename)

    def _publish(self):
        assert self.webserver is not None, 'Device was told not to create '\
                                           'webserver (with False on the '\
                                           'create_webserver parameter) and'\
                                           'device.webserver was not set'\
                                           'manually as it should.'
        log.info('Publishing device %s' % self.friendly_name)
        DeviceXMLBuilder(self).generate_to_file(self._xml_filepath)
        self.webserver.add_static_file(webserver.StaticFile(self.xml_filename,
                                                            self._xml_filepath))

        log.info('Publishing device\'s services')
        for v in self.services.values():
            v.publish(self.webserver)

    def start(self):
        """ Starts the device.
        """
        log.info('Starting device %s' % self.friendly_name)
        log.info('Starting device\'s services')
        for k, v in self.services.items():
            try:
                log.info('Starting service %s' % k)
                v.start()
            except Exception, e:
                log.error('Error starting service %s: %s' % (k, e))
        self._publish()
        self.SSDP.register_device(self)
        self.webserver.start()
        self.SSDP.start()
        log.info('Finished starting device %s' % self.friendly_name)
Example #45
0
class Device(BaseDevice):
    """ Class that represents a device.

    When used with default settings, usage should be minimized to
    instantiation, start() and stop().

    The special setting is a create_webserver keyword that can be passed during
    construction. If False, it disables the automatic creation of the internal
    webserver for serving device files, so, the user should create his own
    webserver and set Device.webserver to it.
    """
    def __init__(self, *args, **kwargs):
        """ Constructor for the Device class.

        @param device_type: device type as described on the device reference
        @param friendly_name: a friendly name

        Optional parameters follow below:

        @param udn: uuid for the device. If not specified will be
                    automatically generated.
        @param parent: parent device
        @param manufacturer: manufacturer
        @param manufacturer_url: manufacturer url
        @param model_description: model description
        @param model_name: model name
        @param model_number: model number
        @param model_url: model url
        @param serial_number: serial number
        @param upc: upc
        @param presentation_url: presentation url
        @param create_webserver: see class description for more information.
                                 Default value is True and you should normally
                                 don't pass anything
        @param force_listen_url: forces the webserver to listen on a specific
                                 address. If it's not possible to listen on
                                 that address, another random one will be
                                 generated and used automatically.
	@param additional_ssdp_headers: can be used to add more field in the
                                        notify message or http responses.

        @type device_type: string
        @type friendly_name: string
        @type udn: string
        @type parent: Device
        @type manufacturer: string
        @type manufacturer_url: string
        @type model_description: string
        @type model_name: string
        @type model_number: string
        @type model_url: string
        @type serial_number: string
        @type upc: string
        @type presentation_url: string
        @type create_webserver: bool
        @type force_listen_url: bool
        @type additional_ssdp_headers: dict
        """
        create_webserver = kwargs.pop('create_webserver', True)
        force_listen_url = kwargs.pop('force_listen_url', '')
        additional_ssdp_headers = kwargs.pop('additional_ssdp_headers', {})
        BaseDevice.__init__(self, *args, **kwargs)
        self._generate_xml()
        self.SSDP = SSDPServer(self.friendly_name,
                               self.xml_filename,
                               additional_headers=additional_ssdp_headers)
        self.webserver = None
        if create_webserver:
            self._create_webserver(force_listen_url)
        self._event_reload_time = None
        self._force_event_reload = None
        self.extra_elts = []

    def add_extra_elts(self, elts):
        """ Append extra elements to the device description, such as DLNA
        descriptive elements. Extra elements must be added before start().

        @param elts: list of Element objects
        @type elts: list
        """
        self.extra_elts = elts[:]

    def add_service(self, service):
        """ Adds a service to the device.
        """
        assert self.location, 'service does not have a location attribute yet'\
                              '. It must have a location set before adding '\
                              'services. If you passed create_webserver=Fal'\
                              'se, you must create the webserver in your '\
                              'own fashion and set self.location to the '\
                              'listening URL before adding services. This '\
                              'problem may also occur if you pass an '\
                              'invalid force_listen_url parameter.'
        service.url_base = self.location
        service.parent_udn = self.udn
        BaseDevice.add_service(self, service)

    def set_event_reload_time(self, time):
        """ Sets a event reload time for all the services.

        @param time: event reload time in seconds
        @type time: int 
        """
        self._event_reload_time = time

    def force_event_reload(self, force):
        """ Forces event reload.

        @param force: forces event reload
        @type force: bool 
        """
        self._force_event_reload = force

    def __add__(self, obj):
        if issubclass(obj.__class__, Device):
            log.debug("Adding device %s as embedded for %s", obj, self)
            self.add_device(obj)
        elif issubclass(obj.__class__, BaseService):
            log.debug("Adding service %s as service for %s", obj, self)
            self.add_service(obj)
        else:
            log.warning("Ignored invalid addition: %s + %s", self, obj)
        return self

    def _create_webserver(self, force_listen_url=''):
        if force_listen_url:
            p = network.parse_url(force_listen_url)
            self.webserver = webserver.WebServer(host=p.hostname, port=p.port)
        else:
            self.webserver = webserver.WebServer()

        self.location = self.webserver.get_listen_url()

    def _generate_xml(self):
        self.xml_filename = '%s-root-device.xml' % self.friendly_name
        self.xml_filename = self.xml_filename.replace(' ', '')
        self._xml_filepath = path.join(config.manager.brisa_home, 'tmp_xml')
        if not path.exists(self._xml_filepath):
            mkdir(self._xml_filepath)
        self._xml_filepath = path.join(self._xml_filepath, self.xml_filename)

    def _publish(self):
        assert self.webserver is not None, 'Device was told not to create '\
                                           'webserver (with False on the '\
                                           'create_webserver parameter) and'\
                                           'device.webserver was not set'\
                                           'manually as it should.'
        log.info('Publishing device %s' % self.friendly_name)
        DeviceXMLBuilder(self,
                         self.extra_elts).generate_to_file(self._xml_filepath)
        self.webserver.add_static_file(
            webserver.StaticFile(self.xml_filename, self._xml_filepath))

        log.info('Publishing device\'s services')
        for v in self.services.values():
            v.publish(self.webserver)

    def start(self):
        """ Starts the device.
        """
        log.info('Starting device %s' % self.friendly_name)
        log.info('Starting device\'s services')
        for k, v in self.services.items():
            try:
                if self._force_event_reload:
                    v._set_force_event_reload(self._force_event_reload)
                else:
                    if self._event_reload_time:
                        v._set_event_reload_time(self._event_reload_time)
                log.info('Starting service %s' % k)
                v.start()
            except Exception, e:
                log.error('Error starting service %s: %s' % (k, str(e)))
        self._publish()
        self.SSDP.register_device(self)
        self.webserver.start()
        self.SSDP.start()
        self.SSDP.announce_device()
        log.info('Finished starting device %s' % self.friendly_name)
Example #46
0
 def publish_plugins(self, webserver):
     log.info("Publishing plugins for ContentDirectory")
     for v in self.plugins_instances.values():
         v.publish(webserver)
Example #47
0
 def unload_plugins(self):
     """ Unload all plugins.
     """
     for p in self.plugins_instances.values():
         log.info("Unloading plugin %s", p.name)
         p.unload()