Ejemplo n.º 1
0
    def disconnect(self, remove_from_list=True, send_bye_msg=False):
        """ Disconnect the client.
        
        @keyword remove_from_list: whether to remove the client from the client
                                   list or not (default is true)
        @keyword send_bye_msg: whether to send a bye message before
                               disconnecting                                       
        """

        # send bye message

        if send_bye_msg and self.__sock is not None:
            log.info("send 'bye' to %s" % self)
            msg = build_message(message.CONN_BYE, None)
            sent = 0
            retry = 0
            while sent < len(msg) and retry < 10:
                try:
                    sent += self.__sock.send(msg)
                except socket.error, e:
                    log.warning("failed to send 'bye' to %s (%s)" % (self, e))
                    break
                time.sleep(0.02)
                retry += 1
            if sent < len(msg):
                log.warning("failed to send 'bye' to %s" % self)
            else:
                # give client some time to close connection:
                time.sleep(0.1)
Ejemplo n.º 2
0
 def run(self):
     """Activate the manager.
     
     This method starts the player adapter, runs a main loop (GLib) and
     blocks until SIGINT or SIGTERM arrives or until stop() gets called. If
     this happens the player adapter gets stopped and this method returns.
     
     If `player_dbus_name` or `poll_fn` has been passed to __init__(), then
     the player adapter does not get started until the player is running
     (according to checks based on the DBus name or poll function). Also the
     adapter gets stopped automatically if the player is not running
     anymore. However, the manager keeps running, i.e. the player adapter
     may get started and stopped multiple times while this method is
     running.
     
     """
     if self.__observer is None: # start pa directly
         ready = _start_pa(self.__pa)
     else: # observer will start pa
         ready = True
         
     if ready and not self.__stopped: # not stopped since creation 
         log.info("start main loop")
         try:
             self.__ml.run()
         except Exception, e:
             log.exception("** BUG ** %s", e)
         else:
             log.info("main loop stopped")
Ejemplo n.º 3
0
    def run(self):
        """Activate the manager.
        
        This method starts the player adapter, runs a main loop (GLib) and
        blocks until SIGINT or SIGTERM arrives or until stop() gets called. If
        this happens the player adapter gets stopped and this method returns.
        
        If `player_dbus_name` or `poll_fn` has been passed to __init__(), then
        the player adapter does not get started until the player is running
        (according to checks based on the DBus name or poll function). Also the
        adapter gets stopped automatically if the player is not running
        anymore. However, the manager keeps running, i.e. the player adapter
        may get started and stopped multiple times while this method is
        running.
        
        """
        if self.__observer is None:  # start pa directly
            ready = _start_pa(self.__pa)
        else:  # observer will start pa
            ready = True

        if ready and not self.__stopped:  # not stopped since creation
            log.info("start main loop")
            try:
                self.__ml.run()
            except Exception, e:
                log.exception("** BUG ** %s", e)
            else:
                log.info("main loop stopped")
Ejemplo n.º 4
0
 def run(self):
     """Activate the manager.
     
     This method starts the player adapter, runs a main loop (GLib) and
     blocks until SIGINT or SIGTERM arrives or until stop() gets called. If
     this happens the player adapter gets stopped and this method returns.
     
     @note: If the keyword 'player_dbus_name' has been set in __init__(),
         then the player adapter does not get started until an application
         owns the bus name given by 'player_dbus_name'. It automatically
         gets started whenever the DBus name has an owner (which means the
         adapter's player is running) and it gets stopped when it has no
         owner. Obvisously here the player adapter may get started and
         stopped repeatedly while this method is running.
     
     """
     if self.__observer is None: # start pa directly
         ready = _start_pa(self.__pa)
     else: # observer will start pa
         ready = True
         
     if ready and not self.__stopped: # not stopped since creation 
         
         log.info("start main loop")
         try:
             self.__ml.run()
         except Exception, e:
             log.exception("** BUG ** %s", e)
         log.info("main loop stopped")
Ejemplo n.º 5
0
 def disconnect(self, remove_from_list=True, send_bye_msg=False):
     """ Disconnect the client.
     
     @keyword remove_from_list: whether to remove the client from the client
                                list or not (default is true)
     @keyword send_bye_msg: whether to send a bye message before
                            disconnecting                                       
     """
     
     # send bye message
     
     if send_bye_msg and self.__sock is not None:
         log.info("send 'bye' to %s" % self)
         msg = build_message(message.CONN_BYE, None)
         sent = 0
         retry = 0
         while sent < len(msg) and retry < 10:
             try:
                 sent += self.__sock.send(msg)
             except socket.error, e:
                 log.warning("failed to send 'bye' to %s (%s)" % (self, e))
                 break
             time.sleep(0.02)
             retry += 1
         if sent < len(msg):
             log.warning("failed to send 'bye' to %s" % self)
         else:
             # give client some time to close connection:
             time.sleep(0.1)
Ejemplo n.º 6
0
def _stop_pa(pa):
    """Stop the given player adapter with error handling."""
    
    log.info("stop player adapter")
    try:
        pa.stop()
    except Exception, e:
        log.exception("** BUG ** %s", e)
Ejemplo n.º 7
0
def _stop_pa(pa):
    """Stop the given player adapter with error handling."""

    log.info("stop player adapter")
    try:
        pa.stop()
    except Exception, e:
        log.exception("** BUG ** %s", e)
Ejemplo n.º 8
0
def _start_pa(pa):
    """Start the given player adapter with error handling."""

    log.info("start player adapter")
    try:
        pa.start()
    except StandardError, e:
        log.error("failed to start player adapter (%s)" % e)
        return False
Ejemplo n.º 9
0
def _start_pa(pa):
    """Start the given player adapter with error handling."""
    
    log.info("start player adapter")
    try:
        pa.start()
    except StandardError, e:
        log.error("failed to start player adapter (%s)" % e)
        return False
Ejemplo n.º 10
0
 def stop(self):
     """Manually shut down the manager.
     
     Stops the manager's main loop and player adapter. As a result a
     previous call to run() will return now.
     """
     
     log.info("stop manager manually")
     self.__stopped = True
     self.__ml.quit()
Ejemplo n.º 11
0
 def stop(self):
     """Shut down the manager.
     
     Stops the manager's main loop and player adapter. As a result a
     previous call to run() will return now. This should be used by player
     adapters when there is a crucial error and restarting the adapter won't
     fix this.
     
     """
     log.info("manager stopped internally")
     self.__stopped = True
     self.__ml.quit()
Ejemplo n.º 12
0
Archivo: net.py Proyecto: gkfabs/remuco
    def disconnect(self, remove_from_list=True, send_bye_msg=False):
        """ Disconnect the client.
        
        @keyword remove_from_list: whether to remove the client from the client
                                   list or not (default is true)
        @keyword send_bye_msg: whether to send a bye message before
                               disconnecting                                       
        """
        
        # send bye message
        
        if send_bye_msg and self.__sock is not None:
            log.info("send 'bye' to %s" % self)
            msg = build_message(message.CONN_BYE, None)
            sent = 0
            retry = 0
            while sent < len(msg) and retry < 10:
                try:
                    sent += self.__sock.send(msg)
                except socket.error as e:
                    log.warning("failed to send 'bye' to %s (%s)" % (self, e))
                    break
                time.sleep(0.02)
                retry += 1
            if sent < len(msg):
                log.warning("failed to send 'bye' to %s" % self)
            else:
                # give client some time to close connection:
                time.sleep(0.1)
        
        # disconnect
        
        log.debug("disconnect %s" % self)
        
        if remove_from_list and self in self.__clients:
            self.__clients.remove(self)
        
        for sid in self.__sids:
            GObject.source_remove(sid)
        
        self.__sids = ()

        if (self.__sid_out > 0):
            GObject.source_remove(self.__sid_out)
            self.__sid_out = 0
        
        if self.__sock is not None:
            try:
                self.__sock.shutdown(socket.SHUT_RDWR)
            except socket.error as e:
                pass
            self.__sock.close()
            self.__sock = None
Ejemplo n.º 13
0
 def stop(self):
     """Shut down the manager.
     
     Stops the manager's main loop and player adapter. As a result a
     previous call to run() will return now. This should be used by player
     adapters when there is a crucial error and restarting the adapter won't
     fix this.
     
     """
     log.info("manager stopped internally")
     self.__stopped = True
     self.__ml.quit()
Ejemplo n.º 14
0
def get_system_shutdown_command():
        
    path = os.path.join(xdg_config, "remuco", "shutdown-system")
    
    if not os.path.isfile(path):
        log.info("system shutdown command (%s) does not exist" % path)
        return None
    
    if not os.access(path, os.X_OK):
        log.info("system shutdown command (%s) is not executable" % path)
        return None
    
    return path
Ejemplo n.º 15
0
def _start_pa(pa):
    """Start the given player adapter with error handling."""
    
    log.info("start player adapter")
    try:
        pa.start()
    except StandardError as e:
        log.error("failed to start player adapter (%s)" % e)
        return False
    except Exception as e:
        log.exception("** BUG ** %s", e)
        return False
    else:
        log.info("player adapter started")
        return True
Ejemplo n.º 16
0
    def __cleanup(self):
        """Trash obsolete config and cache data from older versions."""
        def obsolete(fn):
            """Check if a config or cache item may be trashed."""
            obs = isdir(fn)
            obs |= basename(fn) in ("shutdown-system", "volume")
            obs &= not basename(fn).startswith("old-")
            return obs

        for dname, dtype in ((self.dir, "config"), (self.cache, "cache")):
            trash = join(dname, "old-%s.backup" % _TS)
            fnames = [f for f in glob(join(dname, "*")) if obsolete(f)]
            if fnames:
                log.info("moving old %s data to %s" % (dtype, trash))
                if not exists(trash):
                    os.makedirs(trash)
                for fn in fnames:
                    shutil.move(fn, trash)
Ejemplo n.º 17
0
    def __init__(self, root_dirs, mime_types, show_extensions, show_hidden):

        self.__mime_types = mime_types
        self.__show_extensions = show_extensions
        self.__show_hidden = show_hidden

        if not sys.getfilesystemencoding() in ("UTF8", "UTF-8", "UTF_8"):
            log.warning("file system encoding is not UTF-8, this may cause " +
                        "problems with file browser features")

        root_dirs = root_dirs or []

        # mimetype dependent root dirs
        if "auto" in root_dirs:
            root_dirs.remove("auto")
            if mime_types:
                for mtype in mime_types:
                    if mtype in media_dirs:
                        root_dirs += media_dirs[mtype]
                    mtype = mtype.split("/")[0]  # use main mimetype
                    if mtype in media_dirs:
                        root_dirs += media_dirs[mtype]

        root_dirs = self.__trim_root_dirs(root_dirs) or [user_home]

        # map root dirs to names
        self.__roots = {}
        for dir in root_dirs:
            name = os.path.basename(dir)
            if name == dir:  # == "/"
                name = "Root"
            else:
                name = name.capitalize()
            counter = 2
            name_x = name
            while name_x in self.__roots:
                name_x = "%s (%d)" % (name, counter)
                counter += 1
            self.__roots[name_x] = dir

        log.info("file browser root dirs: %s " % self.__roots)

        if not mimetypes.inited:
            mimetypes.init()
Ejemplo n.º 18
0
    def __init__(self, root_dirs, mime_types, show_extensions, show_hidden):
        
        self.__mime_types = mime_types
        self.__show_extensions = show_extensions
        self.__show_hidden = show_hidden
        
        if not sys.getfilesystemencoding() in ("UTF8", "UTF-8", "UTF_8"):
            log.warning("file system encoding is not UTF-8, this may cause " + 
                        "problems with file browser features")
        
        root_dirs = root_dirs or []
        
        # mimetype dependent root dirs
        if "auto" in root_dirs:
            root_dirs.remove("auto")
            if mime_types:
                for mtype in mime_types:
                    if mtype in media_dirs:
                        root_dirs += media_dirs[mtype]
                    mtype = mtype.split("/")[0] # use main mimetype
                    if mtype in media_dirs:
                        root_dirs += media_dirs[mtype]
            
        root_dirs = self.__trim_root_dirs(root_dirs) or [user_home]
        
        # map root dirs to names
        self.__roots = {}
        for dir in root_dirs:
            name = os.path.basename(dir)
            if name == dir: # == "/"
                name = "Root"
            else:
                name = name.capitalize()
            counter = 2
            name_x = name
            while name_x in self.__roots:
                name_x = "%s (%d)" % (name, counter)
                counter += 1
            self.__roots[name_x] = dir
            
        log.info("file browser root dirs: %s " % self.__roots)

        if not mimetypes.inited:
            mimetypes.init()
Ejemplo n.º 19
0
 def __cleanup(self):
     """Trash obsolete config and cache data from older versions."""
     
     def obsolete(fn):
         """Check if a config or cache item may be trashed."""
         obs  = isdir(fn)
         obs |= basename(fn) in ("shutdown-system", "volume")
         obs &= not basename(fn).startswith("old-")
         return obs
     
     for dname, dtype in ((self.dir, "config"), (self.cache, "cache")):
         trash = join(dname, "old-%s.backup" % _TS)
         fnames = [f for f in glob(join(dname, "*")) if obsolete(f)]
         if fnames:
             log.info("moving old %s data to %s" % (dtype, trash))
             if not exists(trash):
                 os.makedirs(trash)
             for fn in fnames:
                 shutil.move(fn, trash)
Ejemplo n.º 20
0
    def __init__(self, pa, dbus_name=None, poll_fn=None):
        """Create a new manager.
        
        @param pa:
            the PlayerAdapter to manage
        @keyword dbus_name:
            if the player adapter uses DBus to communicate with its player set
            this to the player's well known bus name (see run() for more
            information)
        @keyword poll_fn:
            if DBus is not used, this function may be set for periodic checks
            if the player is running, used to automatically start and stop the
            player adapter
        
        When neither `dbus_name` nor `poll_fn` is given, the adapter is started
        immediately, assuming the player is running and the adapter is ready to
        work.
        
        """
        self.__pa = pa
        self.__pa.manager = self
        self.__stopped = False
        self.__observer = None
        
        global _ml
        if _ml is None:
            _ml = gobject.MainLoop()
            signal.signal(signal.SIGINT, _sighandler)
            signal.signal(signal.SIGTERM, _sighandler)
        self.__ml = _ml

        if dbus_name:
            log.info("start dbus observer")
            self.__observer = _DBusObserver(pa, dbus_name)
        elif poll_fn:
            log.info("start polling observer")
            self.__observer = _PollingObserver(pa, poll_fn)
        else:
            # nothing to do
            pass
Ejemplo n.º 21
0
    def __init__(self, pa, dbus_name=None, poll_fn=None):
        """Create a new manager.
        
        @param pa:
            the PlayerAdapter to manage
        @keyword dbus_name:
            if the player adapter uses DBus to communicate with its player set
            this to the player's well known bus name (see run() for more
            information)
        @keyword poll_fn:
            if DBus is not used, this function may be set for periodic checks
            if the player is running, used to automatically start and stop the
            player adapter
        
        When neither `dbus_name` nor `poll_fn` is given, the adapter is started
        immediately, assuming the player is running and the adapter is ready to
        work.
        
        """
        self.__pa = pa
        self.__pa.manager = self
        self.__stopped = False
        self.__observer = None

        global _ml
        if _ml is None:
            _ml = gobject.MainLoop()
            signal.signal(signal.SIGINT, _sighandler)
            signal.signal(signal.SIGTERM, _sighandler)
        self.__ml = _ml

        if dbus_name:
            log.info("start dbus observer")
            self.__observer = _DBusObserver(pa, dbus_name)
        elif poll_fn:
            log.info("start polling observer")
            self.__observer = _PollingObserver(pa, poll_fn)
        else:
            # nothing to do
            pass
Ejemplo n.º 22
0
    def __init__(self, root_dirs, mime_types, show_extensions=False,
                 show_hidden=False, use_user_dirs=True):
        
        self.__mime_types = mime_types or _AllMimeTypes()
        self.__show_extensions = show_extensions
        self.__show_hidden = show_hidden
        
        if not sys.getfilesystemencoding() in ("UTF8", "UTF-8", "UTF_8"):
            log.warning("file system encoding is not UTF-8, this may cause " + 
                        "problems with file browser features")
        
        root_dirs = root_dirs or []
        
        if use_user_dirs:
            root_dirs += self.__get_mime_dirs(mime_types)
            
        root_dirs = self.__trim_dirs(root_dirs)
        
        if not root_dirs:
            root_dirs = (os.getenv("USERPROFILE", os.path.sep), )
        
        # map root dirs to names
        self.__roots = {}
        for dir in root_dirs:
            name = os.path.basename(dir)
            if name == dir: # == "/"
                name = "Root"
            else:
                name.capitalize()
            counter = 2
            name_x = name
            while name_x in self.__roots:
                name_x = "%s (%d)" % (name, counter)
                counter += 1
            self.__roots[name_x] = dir
            
        log.info("file browser root dirs: %s " % self.__roots)

        if not mimetypes.inited:
            mimetypes.init()
Ejemplo n.º 23
0
Archivo: net.py Proyecto: gkfabs/remuco
 def __init__(self, clients, pinfo, msg_handler_fn, config):
     """ Create a new server.
     
     @param clients:
         a list to add connected clients to
     @param pinfo:
         player info (type data.PlayerInfo)
     @param msg_handler_fn:
         callback function for passing received messages to
     @param config:
         adapter configuration
                              
     """
     self.__clients = clients
     self.__msg_handler_fn = msg_handler_fn
     self.__pinfo_msg = build_message(message.CONN_PINFO, pinfo)
     self.__sid = None
     
     self._pinfo = pinfo
     self._config = config
     self._sock = None
     
     # set up socket
     
     try:
         self._sock = self._create_socket()
         self._sock.settimeout(_Server.SOCKET_TIMEOUT)
     except (IOError, socket.error) as e:
         # TODO: socket.error may be removed when 2.5 support is dropped
         log.error("failed to set up %s server (%s)" % (self._get_type(), e))
         return
     
     log.info("created %s server" % self._get_type())
     
     # watch socket
     
     self.__sid = GObject.io_add_watch(self._sock,
         GObject.IO_IN | GObject.IO_ERR | GObject.IO_HUP, self.__handle_io)
Ejemplo n.º 24
0
    def __check_version(self):
        """Check version of the configuration.
        
        Resets the config on a major change and rewrites the config on any
        change. The last ensures that added options (minor change) are present
        in the configuration file.
        
        """
        try: # check version
            version = self.__cp.get(SEC, KEY_CONFIG_VERSION)
        except (ValueError, AttributeError, NoOptionError):
            version = "0.0"

        major = version.split(".")[0]

        if major != CONFIG_VERSION_MAJOR:
            # on major change, reset configuration
            log.info("config major version changed -> reset config")
            self.__cp = ConfigParser.SafeConfigParser(DEFAULTS)
            
        # remove old, now unused options:
        
        rewrite = False
        items = self.__cp.items(SEC)
        for key, val in items:
            if not (key in DEFAULTS or key.startswith("custom-") or
                    key == KEY_CONFIG_VERSION):
                # obsolete option -> remove
                self.__cp.remove_option(SEC, key)
                rewrite = True

        # force a rewrite if something has changed
        
        if version != CONFIG_VERSION or rewrite:
            # on any change (major or minor), rewrite config
            log.debug("config structure changed -> force rewrite")
            self.__cp.set(SEC, KEY_CONFIG_VERSION, CONFIG_VERSION)
            self.__save()
Ejemplo n.º 25
0
class _Server(object):

    SOCKET_TIMEOUT = 2.5

    def __init__(self, clients, pinfo, msg_handler_fn, config):
        """ Create a new server.
        
        @param clients:
            a list to add connected clients to
        @param pinfo:
            player info (type data.PlayerInfo)
        @param msg_handler_fn:
            callback function for passing received messages to
        @param config:
            adapter configuration
                                 
        """
        self.__clients = clients
        self.__msg_handler_fn = msg_handler_fn
        self.__pinfo_msg = build_message(message.CONN_PINFO, pinfo)
        self.__sid = None

        self._pinfo = pinfo
        self._config = config
        self._sock = None

        # set up socket

        try:
            self._sock = self._create_socket()
            self._sock.settimeout(_Server.SOCKET_TIMEOUT)
        except (IOError, socket.error), e:
            # TODO: socket.error may be removed when 2.5 support is dropped
            log.error("failed to set up %s server (%s)" %
                      (self._get_type(), e))
            return

        log.info("created %s server" % self._get_type())

        # watch socket

        self.__sid = gobject.io_add_watch(
            self._sock, gobject.IO_IN | gobject.IO_ERR | gobject.IO_HUP,
            self.__handle_io)
Ejemplo n.º 26
0
    def __init__(self, pa, player_dbus_name=None, run_check_fn=None):
        """Create a new Manager.
        
        @param pa:
            the PlayerAdapter to manage
        @keyword player_dbus_name:
            if the player adapter uses DBus to communicate with its player set
            this to the player's well known bus name (see run() for more
            information)
        @keyword run_check_fn:
            optional function to call to check if the player is running, used
            for automatically starting and stopping the player
        
        When neither `player_dbus_name` nor `run_check_fn` is given, the
        adapter is started immediately, assuming the player is running and
        the adapter is ready to work.
        
        """
        self.__pa = pa
        self.__pa.manager = self
        
        self.__stopped = False
        
        self.__ml = _init_main_loop()

        self.__observer = None
        
        if player_dbus_name:
            log.info("start dbus observer")
            self.__observer = _DBusObserver(pa, player_dbus_name)
            log.info("dbus observer started")
        elif run_check_fn:
            log.info("start custom observer")
            self.__observer = _CustomObserver(pa, run_check_fn)
            log.info("custom observer started")
        else:
            # nothing to do
            pass
Ejemplo n.º 27
0
# =============================================================================

def _start_pa(pa):
    """Start the given player adapter with error handling."""
    
    log.info("start player adapter")
    try:
        pa.start()
    except StandardError, e:
        log.error("failed to start player adapter (%s)" % e)
        return False
    except Exception, e:
        log.exception("** BUG ** %s", e)
        return False
    else:
        log.info("player adapter started")
        return True

def _stop_pa(pa):
    """Stop the given player adapter with error handling."""
    
    log.info("stop player adapter")
    try:
        pa.stop()
    except Exception, e:
        log.exception("** BUG ** %s", e)
    else:
        log.info("player adapter stopped")

# =============================================================================
# Polling Observer
Ejemplo n.º 28
0
        if exists(self.file):
            try:
                cp.read(self.file)
            except ConfigParser.Error, e:
                log.warning("failed to read config %s (%s)" % (self.file, e))

        # reset on version change
        if cp.get(ConfigParser.DEFAULTSECT,
                  "config-version") != _CONFIG_VERSION:
            sections = cp.sections()  # keep already existing player sections
            cp = ConfigParser.RawConfigParser(_DEFAULTS, _odict)
            for sec in sections:
                cp.add_section(sec)
            if exists(self.file):
                bak = "%s.%s.backup" % (self.file, _TS)
                log.info("reset config (major changes, backup: %s)" % bak)
                shutil.copy(self.file, bak)

        # remove unknown options in all sections
        for sec in cp.sections() + [ConfigParser.DEFAULTSECT]:
            for key, value in cp.items(sec):
                if key not in _DEFAULTS and not key.startswith("x-"):
                    cp.remove_option(sec, key)

        # add not yet existing options to default section
        for key, value in _DEFAULTS.items():
            if not cp.has_option(ConfigParser.DEFAULTSECT, key):
                cp.set(ConfigParser.DEFAULTSECT, key, value)

        # update version
        cp.set(ConfigParser.DEFAULTSECT, "config-version", _CONFIG_VERSION)
Ejemplo n.º 29
0
            cp.add_section(self.player)
        if exists(self.file):
            try:
                cp.read(self.file)
            except ConfigParser.Error, e:
                log.warning("failed to read config %s (%s)" % (self.file, e))

        # reset on version change
        if cp.get(ConfigParser.DEFAULTSECT, "config-version") != _CONFIG_VERSION:
            sections = cp.sections() # keep already existing player sections
            cp = ConfigParser.RawConfigParser(_DEFAULTS, _odict)
            for sec in sections:
                cp.add_section(sec)
            if exists(self.file):
                bak = "%s.%s.backup" % (self.file, _TS)
                log.info("reset config (major changes, backup: %s)" % bak)
                shutil.copy(self.file, bak)
            
        # remove unknown options in all sections
        for sec in cp.sections() + [ConfigParser.DEFAULTSECT]:
            for key, value in cp.items(sec):
                if key not in _DEFAULTS and not key.startswith("x-"):
                    cp.remove_option(sec, key)
                    
        # add not yet existing options to default section
        for key, value in _DEFAULTS.items():
            if not cp.has_option(ConfigParser.DEFAULTSECT, key):
                cp.set(ConfigParser.DEFAULTSECT, key, value)
        
        # update version
        cp.set(ConfigParser.DEFAULTSECT, "config-version", _CONFIG_VERSION)
Ejemplo n.º 30
0
    def __init__(self, player_name):
        """Create a new instance for the given player (adapter)."""

        super(Config, self).__init__()
        
        # convert descriptive name to a plain canonical one
        self.player = re.sub(r'[^\w-]', '', player_name).lower()
        
        # paths
        self.dir = join(user_config_dir, "remuco")
        self.cache = join(user_cache_dir, "remuco")
        self.file = join(self.dir, "remuco.cfg")

        # remove old stuff
        self.__cleanup()

        # create directories
        for dname in (self.dir, self.cache):
            try:
                if not isdir(dname):
                    os.makedirs(dname)
            except OSError as e:
                log.error("failed to make dir: %s", e)
        if not "REMUCO_LOG_STDOUT" in os.environ and isdir(self.cache):
            log.set_file(join(self.cache, "%s.log" % self.player))

        # load
        cp = configparser.RawConfigParser(_DEFAULTS, _odict)
        if not cp.has_section(self.player):
            cp.add_section(self.player)
        if exists(self.file):
            try:
                cp.read(self.file)
            except configparser.Error as e:
                log.warning("failed to read config %s (%s)" % (self.file, e))

        # reset on version change
        if cp.get(configparser.DEFAULTSECT, "config-version") != _CONFIG_VERSION:
            sections = cp.sections() # keep already existing player sections
            cp = configparser.RawConfigParser(_DEFAULTS, _odict)
            for sec in sections:
                cp.add_section(sec)
            if exists(self.file):
                bak = "%s.%s.backup" % (self.file, _TS)
                log.info("reset config (major changes, backup: %s)" % bak)
                shutil.copy(self.file, bak)
            
        # remove unknown options in all sections
        for sec in cp.sections() + [configparser.DEFAULTSECT]:
            for key, value in cp.items(sec):
                if key not in _DEFAULTS and not key.startswith("x-"):
                    cp.remove_option(sec, key)
                    
        # add not yet existing options to default section
        for key, value in _DEFAULTS.items():
            if not cp.has_option(configparser.DEFAULTSECT, key):
                cp.set(configparser.DEFAULTSECT, key, value)
        
        # update version
        cp.set(configparser.DEFAULTSECT, "config-version", _CONFIG_VERSION)

        self.__cp = cp
        
        # save to always have a clean file
        self.__save()

        log.set_level(self.log_level)
        
        log.info("remuco version: %s" % defs.REMUCO_VERSION)
Ejemplo n.º 31
0
def __user_notification(summary, text):
    text = text.replace("<b>", "")
    text = text.replace("</b>", "")

    log.info("%s: %s" % (summary, text))
Ejemplo n.º 32
0
def _sighandler(signum, frame):
    
    log.info("received signal %i" % signum)
    if _ml is not None:
        _ml.quit()
Ejemplo n.º 33
0
            if not "--remuco-log-stdout" in sys.argv:
                log.set_file(self.__file_log)
        
        ###### custom volume command ######
        
        cmd = os.path.join(xdg_config, "remuco", "volume")
        if not os.path.isfile(cmd):
            cmd = os.path.join(self.__dir_config, "volume")
        if not os.path.isfile(cmd):
            log.debug("custom volume command does not exist (%s)" % cmd)
            self.__custom_volume_cmd = None
        elif not os.access(cmd, os.X_OK):
            log.warning("custom volume command (%s) is not executable" % cmd)
            self.__custom_volume_cmd = None
        else:
            log.info("using custom volume command (%s)" % cmd)
            self.__custom_volume_cmd = cmd
        
        ###### load configuration ######
        
        self.__cp = ConfigParser.SafeConfigParser(DEFAULTS)

        if os.path.exists(self.__file_config):
            self.__load() 
            self.__check_version()
        else:
            self.__cp.set(SEC, KEY_CONFIG_VERSION, CONFIG_VERSION)
            self.__save()

        log.set_level(self.log_level)
        
Ejemplo n.º 34
0
class Manager(object):
    """Life cycle manager for a stand-alone player adapter.
    
    A manager cares about calling a PlayerAdapter's start and stop methods.
    Additionally, because Remuco needs a GLib main loop to run, it sets up and
    manages such a loop.
    
    It is intended for player adapters running stand-alone, outside the players
    they adapt. A manager is not needed for player adapters realized as a
    plugin for a media player. In that case the player's plugin interface
    should care about the life cycle of a player adapter (see the Rhythmbox
    player adapter as an example).
    
    """
    def __init__(self, pa, dbus_name=None, poll_fn=None):
        """Create a new manager.
        
        @param pa:
            the PlayerAdapter to manage
        @keyword dbus_name:
            if the player adapter uses DBus to communicate with its player set
            this to the player's well known bus name (see run() for more
            information)
        @keyword poll_fn:
            if DBus is not used, this function may be set for periodic checks
            if the player is running, used to automatically start and stop the
            player adapter
        
        When neither `dbus_name` nor `poll_fn` is given, the adapter is started
        immediately, assuming the player is running and the adapter is ready to
        work.
        
        """
        self.__pa = pa
        self.__pa.manager = self
        self.__stopped = False
        self.__observer = None

        global _ml
        if _ml is None:
            _ml = gobject.MainLoop()
            signal.signal(signal.SIGINT, _sighandler)
            signal.signal(signal.SIGTERM, _sighandler)
        self.__ml = _ml

        if dbus_name:
            log.info("start dbus observer")
            self.__observer = _DBusObserver(pa, dbus_name)
        elif poll_fn:
            log.info("start polling observer")
            self.__observer = _PollingObserver(pa, poll_fn)
        else:
            # nothing to do
            pass

    def run(self):
        """Activate the manager.
        
        This method starts the player adapter, runs a main loop (GLib) and
        blocks until SIGINT or SIGTERM arrives or until stop() gets called. If
        this happens the player adapter gets stopped and this method returns.
        
        If `player_dbus_name` or `poll_fn` has been passed to __init__(), then
        the player adapter does not get started until the player is running
        (according to checks based on the DBus name or poll function). Also the
        adapter gets stopped automatically if the player is not running
        anymore. However, the manager keeps running, i.e. the player adapter
        may get started and stopped multiple times while this method is
        running.
        
        """
        if self.__observer is None:  # start pa directly
            ready = _start_pa(self.__pa)
        else:  # observer will start pa
            ready = True

        if ready and not self.__stopped:  # not stopped since creation
            log.info("start main loop")
            try:
                self.__ml.run()
            except Exception, e:
                log.exception("** BUG ** %s", e)
            else:
                log.info("main loop stopped")

        if self.__observer:  # stop observer
            self.__observer.stop()
            log.info("observer stopped")

        # stop pa
        _stop_pa(self.__pa)
Ejemplo n.º 35
0
    def __init__(
        self,
        name,
        playback_known=False,
        volume_known=False,
        repeat_known=False,
        shuffle_known=False,
        progress_known=False,
        max_rating=0,
        poll=2.5,
        file_actions=None,
        mime_types=None,
        search_mask=None,
    ):
        """Create a new player adapter and configure its capabilities.
        
        Just does some early initializations. Real job starts with start().
        
        @param name:
            name of the media player
        @keyword playback_known:
            indicates if the player's playback state can be provided (see
            update_playback())
        @keyword volume_known:
            indicates if the player's volume can be provided (see
            update_volume())
        @keyword repeat_known:
            indicates if the player's repeat mode can be provided (see
            update_repeat())
        @keyword shuffle_known:
            indicates if the player's shuffle mode can be provided (see
            update_shuffle())
        @keyword progress_known:
            indicates if the player's playback progress can be provided (see
            update_progress())
        @keyword max_rating:
            maximum possible rating value for items
        @keyword poll:
            interval in seconds to call poll()
        @keyword file_actions:
            list of ItemAction which can be applied to files from the local
            file system (actions like play a file or append files to the
            playlist) - this keyword is only relevant if the method
            action_files() gets overridden
        @keyword mime_types:
            list of mime types specifying the files to which the actions given
            by the keyword 'file_actions' can be applied, this may be general
            types like 'audio' or 'video' but also specific types like
            'audio/mp3' or 'video/quicktime' (setting this to None means all
            mime types are supported) - this keyword is only relevant if the
            method action_files() gets overridden
        @keyword search_mask:
             list of fields to search the players library for (e.g. artist,
             genre, any, ...) - if set method request_search() should be
             overridden
        
        @attention: When overriding, call super class implementation first!
        
        """

        self.__name = name

        # init config (config inits logging)

        self.config = config.Config(self.__name)

        # init misc fields

        serial.Bin.HOST_ENCODING = self.config.player_encoding

        self.__clients = []

        self.__state = PlayerState()
        self.__progress = Progress()
        self.__item_id = None
        self.__item_info = None
        self.__item_img = None

        flags = self.__util_calc_flags(playback_known, volume_known, repeat_known, shuffle_known, progress_known)

        self.__info = PlayerInfo(name, flags, max_rating, file_actions, search_mask)

        self.__sync_triggers = {}

        self.__poll_ival = max(500, int(poll * 1000))
        self.__poll_sid = 0

        self.stopped = True

        self.__server_bluetooth = None
        self.__server_wifi = None

        if self.config.fb_root_dirs:
            self.__filelib = files.FileSystemLibrary(
                self.config.fb_root_dirs, mime_types, self.config.fb_show_extensions, False
            )
        else:
            log.info("file browser is disabled")

        if "REMUCO_TESTSHELL" in os.environ:
            from remuco import testshell

            testshell.setup(self)

        log.debug("init done")
Ejemplo n.º 36
0
def _sighandler(signum, frame):

    log.info("received signal %i" % signum)
    if _ml is not None:
        _ml.quit()
Ejemplo n.º 37
0
def _sighandler(signum, frame):
    """Used by Manager. """
    
    log.info("received signal %i" % signum)
    if _ml is not None:
        _ml.quit()
Ejemplo n.º 38
0
 def __io_hup(self, fd, cond):
     """ GObject callback function (when other side disconnected). """
     log.info("client %s disconnected" % self)
     self.disconnect()
     return False
Ejemplo n.º 39
0
 def __io_hup(self, fd, cond):
     """ GObject callback function (when other side disconnected). """
     log.info("client %s disconnected" % self)
     self.disconnect()
     return False
Ejemplo n.º 40
0
 def notify(title, text):
     log.info("%s: %s" % (title, text))
Ejemplo n.º 41
0

def _start_pa(pa):
    """Start the given player adapter with error handling."""

    log.info("start player adapter")
    try:
        pa.start()
    except StandardError, e:
        log.error("failed to start player adapter (%s)" % e)
        return False
    except Exception, e:
        log.exception("** BUG ** %s", e)
        return False
    else:
        log.info("player adapter started")
        return True


def _stop_pa(pa):
    """Stop the given player adapter with error handling."""

    log.info("stop player adapter")
    try:
        pa.stop()
    except Exception, e:
        log.exception("** BUG ** %s", e)
    else:
        log.info("player adapter stopped")

Ejemplo n.º 42
0
 def notify(title, text):
     log.info("%s: %s" % (title, text))