def Seek(self, **kwargs): if not (self._transport_state == "PLAYING" or self._transport_state == "STOPPED"): raise UPnPServiceError(701) unit = kwargs["Unit"] if unit != "REL_TIME" and unit != "ABS_TIME": self.fire(log(logging.DEBUG, "Seek called"), "logger") raise UPnPServiceError(710) target = kwargs["Target"] self.fire(log(logging.DEBUG, "Seek to " + target + " called"), "logger") target = duration_to_secs(target) self.fire(Event.create("seek", target), self.parent.provider.channel) return []
def SetNextAVTransportURI(self, **kwargs): self.fire(log(logging.DEBUG, 'Next AV Transport URI set to ' + kwargs["NextURI"]), "logger") self.fire(Event.create("prepare_next", kwargs["NextURI"], kwargs["NextURIMetaData"]), self.parent.provider.channel) return []
def SetVolume(self, **kwargs): self.fire(log(logging.DEBUG, 'SetVolume to ' + kwargs["DesiredVolume"]), "logger") self.fire(Event.create("set_volume", int(kwargs["DesiredVolume"]) / 100.0), self.parent.provider.channel) return []
def SetNextAVTransportURI(self, **kwargs): self.fire( log(logging.DEBUG, 'Next AV Transport URI set to ' + kwargs["NextURI"]), "logger") self.fire( Event.create("prepare_next", kwargs["NextURI"], kwargs["NextURIMetaData"]), self.parent.provider.channel) return []
def SetVolume(self, **kwargs): self.fire( log(logging.DEBUG, 'SetVolume to ' + kwargs["DesiredVolume"]), "logger") self.fire( Event.create("set_volume", int(kwargs["DesiredVolume"]) / 100.0), self.parent.provider.channel) return []
def _create_event_from_request \ (self, session, evt_class, args, kwargs, channel): if not self._check_event(evt_class, channel): return None try: names = evt_class.split(".") clazz = reduce(getattr, names[1:], sys.modules[names[0]]) except AttributeError: self.fire(log(logging.ERROR, "Unknown event class in event URL: " + evt_class)) return None try: evnt = clazz(*args, session=session, **kwargs) except Exception: self.fire(log(logging.ERROR, "Cannot create event: " + str(sys.exc_info()[1]))) return None evnt.channels = (channel,) return evnt
def __init__(self, path, channel=channel): super(UPnPDeviceServer, self).__init__(channel=channel) self._started = False # Build a web (HTTP) server for handling requests. This is # the server that will be announced by SSDP, so it has # no fixed port number. self.web_server = BaseServer(("", 0), channel="upnp-web").register(self) # Dispatcher for "/upnp-web". disp = ScopeDispatcher(channel="upnp-web").register(self.web_server) # Dummy root controller prevents requests for nested resources # from failing. DummyRoot().register(disp) # Initially empty list of providers self._devices = [] # The configuration id, incremented every time the # configuration changes self.config_id = 1 # Open the database for uuid persistence try: # Some people encounter problems on some boxes when opening # the db file self._uuid_db = anydbm.open(os.path.join(path, 'upnp_uuids'), 'c') except: self.fire( log( logging.WARN, "Could not determine type db type of " + os.path.join(path, 'upnp_uuids'))) try: os.remove(os.path.join(path, 'upnp_uuids')) self._uuid_db = anydbm.open \ (os.path.join(path, 'upnp_uuids'), 'c') except: self.fire( log(logging.WARN, "Giving up on " + os.path.join(path, 'upnp_uuids')))
def __init__(self, path, channel=channel): super(UPnPDeviceServer, self).__init__(channel=channel) self._started = False # Build a web (HTTP) server for handling requests. This is # the server that will be announced by SSDP, so it has # no fixed port number. self.web_server = BaseServer(("", 0), channel="upnp-web").register(self) # Dispatcher for "/upnp-web". disp = ScopeDispatcher(channel="upnp-web").register(self.web_server) # Dummy root controller prevents requests for nested resources # from failing. DummyRoot().register(disp) # Initially empty list of providers self._devices = [] # The configuration id, incremented every time the # configuration changes self.config_id = 1 # Open the database for uuid persistence try: # Some people encounter problems on some boxes when opening # the db file self._uuid_db = anydbm.open(os.path.join(path, 'upnp_uuids'), 'c') except: self.fire(log(logging.WARN, "Could not determine type db type of " + os.path.join(path, 'upnp_uuids'))) try: os.remove(os.path.join(path, 'upnp_uuids')) self._uuid_db = anydbm.open \ (os.path.join(path, 'upnp_uuids'), 'c') except: self.fire(log(logging.WARN, "Giving up on " + os.path.join(path, 'upnp_uuids')))
def _on_registered(self, component, parent): if component != self: return @handler("upnp_notification", channel=parent.notification_channel) def _on_notification_handler(self, state_vars): self._on_notification(state_vars) self.addHandler(_on_notification_handler) state_vars = dict() for name, method in getmembers \ (self.parent, lambda x: ismethod(x) and hasattr(x, "_evented_by")): state_vars[name] = method() if len(state_vars) > 0: self._on_notification(state_vars) self.fire(log(logging.DEBUG, "Subscribtion for " + str(self._callbacks) + " on " + self.parent.notification_channel + " created"), "logger")
def GetMediaInfo(self, **kwargs): self.fire(log(logging.DEBUG, "GetMediaInfo called"), "logger") return [("NrTracks", self._provider.tracks), ("MediaDuration", "NOT_IMPLEMENTED" \ if self._provider.current_track_duration is None \ else secs_to_duration \ (self._provider.current_track_duration)), ("CurrentURI", self._provider.source), ("CurrentURIMetaData", "NOT_IMPLEMENTED" \ if self._provider.source_meta_data is None \ else self._provider.source_meta_data), ("NextURI", self._provider.next_source), ("NextURIMetaData", "NOT_IMPLEMENTED" \ if self._provider.next_source_meta_data is None \ else self._provider.next_source_meta_data), ("PlayMedium", "NONE"), ("RecordMedium", "NOT_IMPLEMENTED"), ("WriteStatus", "NOT_IMPLEMENTED")]
def __init__(self, name, initial_config=None, defaults={}): """ :param initial_config: the initial configuration past on to the constructor of the :class:`Configuration` sub-component :param defaults: the defaults passed to the constructor of the :class:`Configuration` sub-component """ super(Application, self).__init__() self._app_name = name self._app_dir = defaults.setdefault \ ('app_dir', os.path.expanduser('~/.%s' % name)) self._config_dir = defaults.setdefault('config_dir', self._app_dir) self._log_dir = defaults.setdefault('log_dir', self._app_dir) if not initial_config: initial_config = DEFAULT_CONFIG if not os.path.exists(self._app_dir): os.makedirs(self._app_dir) if not os.path.exists(self._config_dir): os.makedirs(self._config_dir) self._config = Configuration \ (os.path.join(self._config_dir, 'config'), initial_config, defaults).register(self) # Create Logger Component using the values from the configuration log_opts = dict() for opt in self._config.options("logging"): log_opts[opt] = self._config.get("logging", opt) logtype = log_opts.get("type", "stderr") loglevel = log_opts.get("level", "INFO") loglevel = logging.getLevelName(loglevel) logfile = log_opts.get("file", None) if logfile and not os.path.abspath(logfile): logfile = os.path.join(self._config_dir, logfile) self._log = Logger(logfile, name, logtype, loglevel, handler_args=log_opts).register(self) self.fire(log(logging.INFO, 'Application ' + name + " started"), "logger")
def GetPositionInfo(self, **kwargs): rel_pos = self._provider.current_position() self.fire(log(logging.DEBUG, "GetPositionInfo called"), "logger") info = [("Track", self._provider.current_track), ("TrackDuration", "NOT_IMPLEMENTED" \ if self._provider.current_track_duration is None \ else secs_to_duration \ (self._provider.current_track_duration)), ("TrackMetaData", "NOT_IMPLEMENTED" \ if self._provider.source_meta_data is None \ else self._provider.source_meta_data), ("TrackURI", self._provider.source), ("RelTime", "NOT_IMPLEMENTED" if rel_pos is None \ else secs_to_duration(rel_pos)), ("AbsTime", "NOT_IMPLEMENTED" if rel_pos is None \ else secs_to_duration(rel_pos)), ("RelCount", 2147483647 if rel_pos is None else rel_pos), ("AbsCount", 2147483647 if rel_pos is None else rel_pos)] return info
def _control(self, *args): payload = parseSoapRequest(self.request)[2] action_ns, action = splitQTag(payload.tag) action_args = dict() for node in payload: action_args[node.tag] = node.text method = getattr(self, action, None) if method is None or not getattr(method, "_is_upnp_service", False): self.fire(log(logging.INFO, 'Action ' + action + " not implemented"), "logger") return UPnPError(self.request, self.response, 401) try: out_args = method(**action_args) except UPnPServiceError as error: return UPnPError(self.request, self.response, error.code) result = Element("{%s}%sResponse" % (action_ns, action)) for name, value in out_args: arg = SubElement(result, name) arg.text = unicode(value) return buildSoapResponse(self.response, result)
def __init__(self, channel=channel): ''' Constructor ''' super(SSDPSender, self).__init__(channel=channel) # Setup the common entries in the dictionary that will be usd to # fill the UPnP templates. self._message_env['BOOTID'] = self._boot_id self._message_env['SERVER'] = SERVER_HELLO try: self.hostaddr = gethostbyname(gethostname()) if self.hostaddr.startswith("127.") and not "." in gethostname(): try: self.hostaddr = gethostbyname(gethostname() + ".") except: pass except Exception as e: self.fire(log(logging.ERROR, "Failed to get host address: %s(%s)" \ % (type(e), str(e))), "logger")
def __init__(self, name, initial_config=None, defaults={}): """ :param initial_config: the initial configuration past on to the constructor of the :class:`Configuration` sub-component :param defaults: the defaults passed to the constructor of the :class:`Configuration` sub-component """ super(Application, self).__init__() self._app_name = name self._app_dir = defaults.setdefault \ ('app_dir', os.path.expanduser('~/.%s' % name)) self._config_dir = defaults.setdefault ('config_dir', self._app_dir) self._log_dir = defaults.setdefault('log_dir', self._app_dir) if not initial_config: initial_config = DEFAULT_CONFIG if not os.path.exists(self._app_dir): os.makedirs(self._app_dir) if not os.path.exists(self._config_dir): os.makedirs(self._config_dir) self._config = Configuration \ (os.path.join(self._config_dir, 'config'), initial_config, defaults).register(self); # Create Logger Component using the values from the configuration log_opts = dict() for opt in self._config.options("logging"): log_opts[opt] = self._config.get("logging", opt) logtype = log_opts.get("type", "stderr") loglevel = log_opts.get("level", "INFO") loglevel = logging.getLevelName(loglevel) logfile = log_opts.get("file", None) if logfile and not os.path.abspath(logfile): logfile = os.path.join(self._config_dir, logfile) self._log = Logger(logfile, name, logtype, loglevel, handler_args=log_opts).register(self) self.fire(log(logging.INFO, 'Application ' + name + " started"), "logger")
def _on_notification(self, state_vars): root = Element(QName(UPNP_EVENT_NS, "propertyset")) for name, value in state_vars.items(): prop = SubElement(root, QName(UPNP_EVENT_NS, "property")) val = SubElement(prop, QName(UPNP_EVENT_NS, name)) if isinstance(value, bool): val.text = "1" if value else "0" else: val.text = unicode(value) misc.set_ns_prefixes(root, { "": UPNP_EVENT_NS }) # Keep body as str for safe request handling body = "<?xml version='1.0' encoding='utf-8'?>" \ + ElementTree.tostring(root, encoding="utf-8") self.fire(log(logging.DEBUG, "Notifying " + self._callbacks[self._used_callback] + " about " + str(state_vars)), "logger") self.fire(request("NOTIFY", self._callbacks[self._used_callback], body, { "CONTENT-TYPE": "text/xml; charset=\"utf-8\"", "NT": "upnp:event", "NTS": "upnp:propchange", "SID": self.sid, "SEQ": self._seq })) self._seq += 1
def GetTransportInfo(self, **kwargs): self.fire(log(logging.DEBUG, "GetTransportInfo called"), "logger") return [("CurrentTransportState", self._transport_state), ("CurrentTransportStatus", "OK"), ("CurrentSpeed", "1")]
def GetCurrentConnectionIDs(self, **kwargs): self.fire(log(logging.DEBUG, "GetCurrentConnectionIDs called"), "logger") return [("GetCurrentConnectionIDs", self.CurrentConnectionIDs())]
def GetProtocolInfo(self, **kwargs): self.fire(log(logging.DEBUG, "GetProtocolInfo called"), "logger") types = self.parent._provider.supportedMediaTypes() return [("Source", ""), ("Sink", ",".join(types))]
def _on_renewal(self, timeout): self._expiry_timer.interval = timeout self._expiry_timer.reset() self.fire(log(logging.DEBUG, "Subscribtion for " + str(self._callbacks) + " on " + self.parent.notification_channel + " renewed"), "logger")
def Stop(self, **kwargs): self.fire(log(logging.DEBUG, "Stop called"), "logger") self.fire(Event.create("stop"), self.parent.provider.channel) return []
def Pause(self, **kwargs): self.fire(log(logging.DEBUG, "Pause called"), "logger") self.fire(Event.create("pause"), self.parent.provider.channel) return []
def GetVolume(self, **kwargs): self.fire(log(logging.DEBUG, "GetVolume called"), "logger") return [("CurrentVolume", str(int(self._provider.volume * 100)))]
def _on_provider_updated_handler(self, provider, changed): self.fire( log(logging.DEBUG, str(provider) + " changed: " + str(changed)), "logger")
def _on_subs_end(self): self.unregister() self.fire(log(logging.DEBUG, "Subscribtion for " + str(self._callbacks) + " on " + self.parent.notification_channel + " cancelled"), "logger")