# # Copyright (C) 2009 Andrew Resch # # Basic plugin template created by: # Copyright (C) 2008 Martijn Voncken # Copyright (C) 2007-2009 Andrew Resch # # This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with # the additional special exception to link portions of this program with the OpenSSL library. # See LICENSE for more details. # import logging import time from twisted.internet import reactor import deluge.component as component import deluge.configmanager from deluge.core.rpcserver import export from deluge.event import DelugeEvent from deluge.plugins.pluginbase import CorePluginBase log = logging.getLogger(__name__) DEFAULT_PREFS = { 'low_down': -1.0, 'low_up': -1.0, 'low_active': -1, 'low_active_down': -1, 'low_active_up': -1, 'button_state': [[0] * 7 for dummy in range(24)], } STATES = {0: 'Green', 1: 'Yellow', 2: 'Red'} CONTROLLED_SETTINGS = [ 'max_download_speed', 'max_upload_speed', 'max_active_limit', 'max_active_downloading', 'max_active_seeding', ] class SchedulerEvent(DelugeEvent): """ Emitted when a schedule state changes. """ def __init__(self, colour): """ :param colour: str, the current scheduler state """ self._args = [colour] class Core(CorePluginBase): def enable(self): # Create the defaults with the core config core_config = component.get('Core').config DEFAULT_PREFS['low_down'] = core_config['max_download_speed'] DEFAULT_PREFS['low_up'] = core_config['max_upload_speed'] DEFAULT_PREFS['low_active'] = core_config['max_active_limit'] DEFAULT_PREFS['low_active_down'] = core_config['max_active_downloading'] DEFAULT_PREFS['low_active_up'] = core_config['max_active_seeding'] self.config = deluge.configmanager.ConfigManager( 'scheduler.conf', DEFAULT_PREFS ) self.state = self.get_state() # Apply the scheduling rules self.do_schedule(False) # Schedule the next do_schedule() call for on the next hour now = time.localtime(time.time()) secs_to_next_hour = ((60 - now[4]) * 60) + (60 - now[5]) self.timer = reactor.callLater(secs_to_next_hour, self.do_schedule) # Register for config changes so state isn't overridden component.get('EventManager').register_event_handler( 'ConfigValueChangedEvent', self.on_config_value_changed ) def disable(self): if self.timer.active(): self.timer.cancel() component.get('EventManager').deregister_event_handler( 'ConfigValueChangedEvent', self.on_config_value_changed ) self.__apply_set_functions() def update(self): pass def on_config_value_changed(self, key, value): if key in CONTROLLED_SETTINGS: self.do_schedule(False) def __apply_set_functions(self): """ Have the core apply it's bandwidth settings as specified in core.conf. """ core_config = deluge.configmanager.ConfigManager('core.conf') for setting in CONTROLLED_SETTINGS: component.get('PreferencesManager').do_config_set_func( setting, core_config[setting] ) # Resume the session if necessary component.get('Core').resume_session() def do_schedule(self, timer=True): """ This is where we apply schedule rules. """ state = self.get_state() if state == 'Green': # This is Green (Normal) so we just make sure we've applied the # global defaults self.__apply_set_functions() elif state == 'Yellow': # This is Yellow (Slow), so use the settings provided from the user settings = { 'active_limit': self.config['low_active'], 'active_downloads': self.config['low_active_down'], 'active_seeds': self.config['low_active_up'], 'download_rate_limit': int(self.config['low_down'] * 1024), 'upload_rate_limit': int(self.config['low_up'] * 1024), } component.get('Core').apply_session_settings(settings) # Resume the session if necessary component.get('Core').resume_session() elif state == 'Red': # This is Red (Stop), so pause the libtorrent session component.get('Core').pause_session() if state != self.state: # The state has changed since last update so we need to emit an event self.state = state component.get('EventManager').emit(SchedulerEvent(self.state)) if timer: # Call this again in 1 hour self.timer = reactor.callLater(3600, self.do_schedule) @export() def set_config(self, config): """Sets the config dictionary.""" for key in config: self.config[key] = config[key] self.config.save() self.do_schedule(False) @export() def get_config(self): """Returns the config dictionary.""" return self.config.config @export() def get_state(self): now = time.localtime(time.time()) level = self.config['button_state'][now[3]][now[6]] return STATES[level]