More work on the queue torrent plugin and plugins in general.

This commit is contained in:
Andrew Resch 2007-08-10 08:15:02 +00:00
commit 13fc181fa2
10 changed files with 896 additions and 1005 deletions

View file

@ -112,6 +112,10 @@ class Core(dbus.service.Object):
""" """
log.info("Adding torrent: %s", filename) log.info("Adding torrent: %s", filename)
torrent_id = self.torrents.add(filename, filedump) torrent_id = self.torrents.add(filename, filedump)
# Run the plugin hooks for 'post_torrent_add'
self.plugins.run_post_torrent_add(torrent_id)
if torrent_id is not None: if torrent_id is not None:
# Emit the torrent_added signal # Emit the torrent_added signal
self.torrent_added(torrent_id) self.torrent_added(torrent_id)
@ -123,6 +127,8 @@ class Core(dbus.service.Object):
def remove_torrent(self, torrent_id): def remove_torrent(self, torrent_id):
log.debug("Removing torrent %s from the core.", torrent_id) log.debug("Removing torrent %s from the core.", torrent_id)
if self.torrents.remove(torrent_id): if self.torrents.remove(torrent_id):
# Run the plugin hooks for 'post_torrent_remove'
self.plugins.run_post_torrent_remove(torrent_id)
# Emit the torrent_removed signal # Emit the torrent_removed signal
self.torrent_removed(torrent_id) self.torrent_removed(torrent_id)
@ -153,35 +159,6 @@ class Core(dbus.service.Object):
status = pickle.dumps(status) status = pickle.dumps(status)
return status return status
## Queueing functions ######
@dbus.service.method(dbus_interface="org.deluge_torrent.Deluge",
in_signature="s", out_signature="")
def queue_top(self, torrent_id):
# If the queue method returns True, then we should emit a signal
if self.torrents.queue.top(torrent_id):
self.torrent_queue_changed()
@dbus.service.method(dbus_interface="org.deluge_torrent.Deluge",
in_signature="s", out_signature="")
def queue_up(self, torrent_id):
# If the queue method returns True, then we should emit a signal
if self.torrents.queue.up(torrent_id):
self.torrent_queue_changed()
@dbus.service.method(dbus_interface="org.deluge_torrent.Deluge",
in_signature="s", out_signature="")
def queue_down(self, torrent_id):
# If the queue method returns True, then we should emit a signal
if self.torrents.queue.down(torrent_id):
self.torrent_queue_changed()
@dbus.service.method(dbus_interface="org.deluge_torrent.Deluge",
in_signature="s", out_signature="")
def queue_bottom(self, torrent_id):
# If the queue method returns True, then we should emit a signal
if self.torrents.queue.bottom(torrent_id):
self.torrent_queue_changed()
# Signals # Signals
@dbus.service.signal(dbus_interface="org.deluge_torrent.Deluge", @dbus.service.signal(dbus_interface="org.deluge_torrent.Deluge",
signature="s") signature="s")
@ -201,12 +178,6 @@ class Core(dbus.service.Object):
"""Emitted when a torrent has been removed from the core""" """Emitted when a torrent has been removed from the core"""
log.debug("torrent_remove signal emitted") log.debug("torrent_remove signal emitted")
@dbus.service.signal(dbus_interface="org.deluge_torrent.Deluge",
signature="")
def torrent_queue_changed(self):
"""Emitted when a torrent queue position is changed"""
log.debug("torrent_queue_changed signal emitted")
@dbus.service.signal(dbus_interface="org.deluge_torrent.Deluge", @dbus.service.signal(dbus_interface="org.deluge_torrent.Deluge",
signature="s") signature="s")
def torrent_paused(self, torrent_id): def torrent_paused(self, torrent_id):

View file

@ -41,6 +41,9 @@ log = logging.getLogger("deluge")
class PluginManager: class PluginManager:
def __init__(self): def __init__(self):
# Set up the hooks dictionary
self.hooks = {"post_torrent_add": []}
# This will load any .eggs in the plugins folder inside the main # This will load any .eggs in the plugins folder inside the main
# deluge egg.. Need to scan the local plugin folder too. # deluge egg.. Need to scan the local plugin folder too.
@ -54,10 +57,35 @@ class PluginManager:
egg = pkg_env[name][0] egg = pkg_env[name][0]
egg.activate() egg.activate()
modules = [] modules = []
for name in egg.get_entry_map("deluge.plugin"): for name in egg.get_entry_map("deluge.plugin.core"):
entry_point = egg.get_entry_info("deluge.plugin", name) entry_point = egg.get_entry_info("deluge.plugin.core", name)
cls = entry_point.load() cls = entry_point.load()
instance = cls() instance = cls(self)
self.plugins[name] = instance self.plugins[name] = instance
log.info("Load plugin %s", name)
def __getitem__(self, key):
return self.plugins[key]
log.info("Plugins loaded: %s", self.plugins) def register_hook(self, hook, function):
"""Register a hook function with the plugin manager"""
try:
self.hooks[hook].append(function)
except KeyError:
log.warning("Plugin attempting to register invalid hook.")
def run_post_torrent_add(self, torrent_id):
log.debug("run_post_torrent_add")
try:
for function in self.hooks["post_torrent_add"]:
function(torrent_id)
except:
pass
def run_post_torrent_remove(self, torrent_id):
log.debug("run_post_torrent_remove")
try:
for function in self.hooks["post_torrent_remove"]:
function(torrent_id)
except:
pass

View file

@ -39,19 +39,14 @@ import deluge.libtorrent as lt
log = logging.getLogger("deluge") log = logging.getLogger("deluge")
class Torrent: class Torrent:
def __init__(self, filename, handle, queue): def __init__(self, filename, handle):
# Set the filename # Set the filename
self.filename = filename self.filename = filename
# Set the libtorrent handle # Set the libtorrent handle
self.handle = handle self.handle = handle
# Set the queue this torrent belongs too
self.queue = queue
# Set the torrent_id for this torrent # Set the torrent_id for this torrent
self.torrent_id = str(handle.info_hash()) self.torrent_id = str(handle.info_hash())
def __del__(self):
self.queue.remove(self.torrent_id)
def get_state(self): def get_state(self):
"""Returns the state of this torrent for saving to the session state""" """Returns the state of this torrent for saving to the session state"""
return (self.torrent_id, self.filename) return (self.torrent_id, self.filename)
@ -91,8 +86,7 @@ class Torrent:
"num_peers": status.num_peers, "num_peers": status.num_peers,
"num_seeds": status.num_seeds, "num_seeds": status.num_seeds,
"total_wanted": status.total_wanted, "total_wanted": status.total_wanted,
"eta": self.get_eta(), "eta": self.get_eta()
"queue": self.queue[self.torrent_id]
} }
# Create the desired status dictionary and return it # Create the desired status dictionary and return it

View file

@ -40,7 +40,6 @@ import deluge.libtorrent as lt
import deluge.common import deluge.common
from deluge.config import Config from deluge.config import Config
from deluge.core.torrent import Torrent from deluge.core.torrent import Torrent
from deluge.core.torrentqueue import TorrentQueue
from deluge.core.torrentmanagerstate import TorrentManagerState, TorrentState from deluge.core.torrentmanagerstate import TorrentManagerState, TorrentState
# Get the logger # Get the logger
@ -53,7 +52,6 @@ class TorrentManager:
self.session = session self.session = session
# Create the torrents dict { torrent_id: Torrent } # Create the torrents dict { torrent_id: Torrent }
self.torrents = {} self.torrents = {}
self.queue = TorrentQueue()
def __getitem__(self, torrent_id): def __getitem__(self, torrent_id):
"""Return the Torrent with torrent_id""" """Return the Torrent with torrent_id"""
@ -103,11 +101,9 @@ class TorrentManager:
log.warning("Unable to save torrent file: %s", filename) log.warning("Unable to save torrent file: %s", filename)
# Create a Torrent object # Create a Torrent object
torrent = Torrent(filename, handle, self.queue) torrent = Torrent(filename, handle)
# Add the torrent object to the dictionary # Add the torrent object to the dictionary
self.torrents[torrent.torrent_id] = torrent self.torrents[torrent.torrent_id] = torrent
# Add the torrent to the queue
self.queue.append(torrent.torrent_id)
return torrent.torrent_id return torrent.torrent_id
def remove(self, torrent_id): def remove(self, torrent_id):
@ -146,8 +142,6 @@ class TorrentManager:
def save_state(self): def save_state(self):
"""Save the state of the TorrentManager to the torrents.state file""" """Save the state of the TorrentManager to the torrents.state file"""
state = TorrentManagerState() state = TorrentManagerState()
# Grab the queue from TorrentQueue
state.queue = self.queue.queue
# Create the state for each Torrent and append to the list # Create the state for each Torrent and append to the list
for (key, torrent) in self.torrents: for (key, torrent) in self.torrents:
t = TorrentState(torrent.get_state()) t = TorrentState(torrent.get_state())

View file

@ -1,136 +0,0 @@
#
# torrentqueue.py
#
# Copyright (C) 2007 Andrew Resch ('andar') <andrewresch@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the OpenSSL
# library.
# You must obey the GNU General Public License in all respects for all of
# the code used other than OpenSSL. If you modify file(s) with this
# exception, you may extend this exception to your version of the file(s),
# but you are not obligated to do so. If you do not wish to do so, delete
# this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here.
import logging
# Get the logger
log = logging.getLogger("deluge")
class TorrentQueue:
def __init__(self):
log.debug("TorrentQueue init..")
self.queue = []
def __getitem__(self, torrent_id):
"""Return the queue position of the torrent_id"""
return self.queue.index(torrent_id)
def append(self, torrent_id):
"""Append torrent_id to the bottom of the queue"""
log.debug("Append torrent %s to queue..", torrent_id)
self.queue.append(torrent_id)
def prepend(self, torrent_id):
"""Prepend torrent_id to the top of the queue"""
log.debug("Prepend torrent %s to queue..", torrent_id)
self.queue.insert(0, torrent_id)
def remove(self, torrent_id):
"""Removes torrent_id from the list"""
self.queue.remove(torrent_id)
def up(self, torrent_id):
"""Move torrent_id up one in the queue"""
if torrent_id not in self.queue:
# Raise KeyError if the torrent_id is not in the queue
raise KeyError
log.debug("Move torrent %s up..", torrent_id)
# Get the index of the torrent_id
index = self.queue.index(torrent_id)
# Can't queue up if torrent is already at top
if index is 0:
return False
# Pop and insert the torrent_id at index - 1
self.queue.insert(index - 1, self.queue.pop(index))
return True
def top(self, torrent_id):
"""Move torrent_id to top of the queue"""
if torrent_id not in self.queue:
# Raise KeyError if the torrent_id is not in the queue
raise KeyError
log.debug("Move torrent %s to top..", torrent_id)
# Get the index of the torrent_id
index = self.queue.index(torrent_id)
# Can't queue up if torrent is already at top
if index is 0:
return False
# Pop and prepend the torrent_id
self.prepend(self.queue.pop(index))
return True
def down(self, torrent_id):
"""Move torrent_id down one in the queue"""
if torrent_id not in self.queue:
# Raise KeyError if torrent_id is not in the queue
raise KeyError
log.debug("Move torrent %s down..", torrent_id)
# Get the index of the torrent_id
index = self.queue.index(torrent_id)
# Can't queue down of torrent_id is at bottom
if index is len(self.queue) - 1:
return False
# Pop and insert the torrent_id at index + 1
self.queue.insert(index + 1, self.queue.pop(index))
return True
def bottom(self, torrent_id):
"""Move torrent_id to bottom of the queue"""
if torrent_id not in self.queue:
# Raise KeyError if torrent_id is not in the queue
raise KeyError
log.debug("Move torrent %s to bottom..", torrent_id)
# Get the index of the torrent_id
index = self.queue.index(torrent_id)
# Can't queue down of torrent_id is at bottom
if index is len(self.queue) - 1:
return False
# Pop and append the torrent_id
self.append(self.queue.pop(index))
return True

View file

@ -31,9 +31,116 @@
# this exception statement from your version. If you delete this exception # this exception statement from your version. If you delete this exception
# statement from all source files in the program, then also delete it here. # statement from all source files in the program, then also delete it here.
class QueuePlugin: import logging
def __init__(self):
print "queue plugin init!" try:
import dbus, dbus.service
dbus_version = getattr(dbus, "version", (0,0,0))
if dbus_version >= (0,41,0) and dbus_version < (0,80,0):
import dbus.glib
elif dbus_version >= (0,80,0):
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
else:
pass
except: dbus_imported = False
else: dbus_imported = True
from torrentqueue import TorrentQueue
# Get the logger
log = logging.getLogger("deluge")
class QueueCorePlugin(dbus.service.Object):
def __init__(self, plugin, path="/org/deluge_torrent/Plugin/Queue"):
# Get the pluginmanager reference
self.plugin = plugin
# Setup DBUS
bus_name = dbus.service.BusName("org.deluge_torrent.Deluge",
bus=dbus.SessionBus())
dbus.service.Object.__init__(self, bus_name, path)
# Instantiate the TorrentQueue object
self.queue = TorrentQueue()
# Register core hooks
self.plugin.register_hook("post_torrent_add", self.post_torrent_add)
self.plugin.register_hook("post_torrent_remove",
self.post_torrent_remove)
log.info("Queue plugin initialized..")
def test(self): ## Hooks for core ##
print "queue plugin test!" def post_torrent_add(self, torrent_id):
if torrent_id is not None:
self.queue.append(torrent_id)
def post_torrent_remove(self, torrent_id):
if torrent_id is not None:
self.queue.remove(torrent_id)
## Queueing functions ##
@dbus.service.method(dbus_interface="org.deluge_torrent.Deluge.Queue",
in_signature="s", out_signature="")
def queue_top(self, torrent_id):
log.debug("Attempting to queue %s to top", torrent_id)
try:
# If the queue method returns True, then we should emit a signal
if self.queue.top(torrent_id):
self.torrent_queue_changed()
except KeyError:
log.warning("torrent_id: %s does not exist in the queue",
torrent_id)
@dbus.service.method(dbus_interface="org.deluge_torrent.Deluge.Queue",
in_signature="s", out_signature="")
def queue_up(self, torrent_id):
log.debug("Attempting to queue %s to up", torrent_id)
try:
# If the queue method returns True, then we should emit a signal
if self.queue.up(torrent_id):
self.torrent_queue_changed()
except KeyError:
log.warning("torrent_id: %s does not exist in the queue",
torrent_id)
@dbus.service.method(dbus_interface="org.deluge_torrent.Deluge.Queue",
in_signature="s", out_signature="")
def queue_down(self, torrent_id):
log.debug("Attempting to queue %s to down", torrent_id)
try:
# If the queue method returns True, then we should emit a signal
if self.queue.down(torrent_id):
self.torrent_queue_changed()
except KeyError:
log.warning("torrent_id: %s does not exist in the queue",
torrent_id)
@dbus.service.method(dbus_interface="org.deluge_torrent.Deluge.Queue",
in_signature="s", out_signature="")
def queue_bottom(self, torrent_id):
log.debug("Attempting to queue %s to bottom", torrent_id)
try:
# If the queue method returns True, then we should emit a signal
if self.queue.bottom(torrent_id):
self.torrent_queue_changed()
except KeyError:
log.warning("torrent_id: %s does not exist in the queue",
torrent_id)
@dbus.service.method(dbus_interface="org.deluge_torrent.Deluge.Queue",
in_signature="", out_signature="as")
def get_queue(self):
"""Returns the queue list.
"""
log.debug("Getting queue list")
return self.queue.queue
## Signals ##
@dbus.service.signal(dbus_interface="org.deluge_torrent.Deluge.Queue",
signature="")
def torrent_queue_changed(self):
"""Emitted when a torrent queue position is changed"""
log.debug("torrent_queue_changed signal emitted")

View file

@ -43,7 +43,7 @@ setup(
author=__author__, author=__author__,
packages=["queue"], packages=["queue"],
entry_points=""" entry_points="""
[deluge.plugin] [deluge.plugin.core]
Queue = queue:QueuePlugin Queue = queue:QueueCorePlugin
""" """
) )

View file

@ -66,6 +66,15 @@ def get_core():
log.debug("Got core proxy object..") log.debug("Got core proxy object..")
return core return core
def get_core_plugin(plugin):
"""Get the core plugin object and return it"""
log.debug("Getting core plugin %s from DBUS..", plugin)
bus = dbus.SessionBus()
proxy = bus.get_object("org.deluge_torrent.Deluge",
"/org/deluge_torrent/Plugin/" + plugin)
core = dbus.Interface(proxy, "org.deluge_torrent.Deluge." + plugin)
return core
def add_torrent_file(torrent_files): def add_torrent_file(torrent_files):
"""Adds torrent files to the core """Adds torrent files to the core
Expects a list of torrent files Expects a list of torrent files
@ -106,7 +115,7 @@ def resume_torrent(torrent_ids):
def queue_top(torrent_ids): def queue_top(torrent_ids):
"""Attempts to queue all torrent_ids to the top""" """Attempts to queue all torrent_ids to the top"""
log.debug("Attempting to queue to top these torrents: %s", torrent_ids) log.debug("Attempting to queue to top these torrents: %s", torrent_ids)
core = get_core() core = get_core_plugin("Queue")
for torrent_id in torrent_ids: for torrent_id in torrent_ids:
core.queue_top(torrent_id) core.queue_top(torrent_id)

File diff suppressed because it is too large Load diff

View file

@ -47,7 +47,7 @@ log = logging.getLogger("deluge")
# Initializes the columns for the torrent_view # Initializes the columns for the torrent_view
(TORRENT_VIEW_COL_UID, (TORRENT_VIEW_COL_UID,
TORRENT_VIEW_COL_QUEUE, #TORRENT_VIEW_COL_QUEUE,
TORRENT_VIEW_COL_STATUSICON, TORRENT_VIEW_COL_STATUSICON,
TORRENT_VIEW_COL_NAME, TORRENT_VIEW_COL_NAME,
TORRENT_VIEW_COL_SIZE, TORRENT_VIEW_COL_SIZE,
@ -60,7 +60,7 @@ TORRENT_VIEW_COL_PEERS,
TORRENT_VIEW_COL_DOWNLOAD, TORRENT_VIEW_COL_DOWNLOAD,
TORRENT_VIEW_COL_UPLOAD, TORRENT_VIEW_COL_UPLOAD,
TORRENT_VIEW_COL_ETA, TORRENT_VIEW_COL_ETA,
TORRENT_VIEW_COL_RATIO) = range(15) TORRENT_VIEW_COL_RATIO) = range(14)
class TorrentView: class TorrentView:
def __init__(self, window): def __init__(self, window):
@ -71,9 +71,9 @@ class TorrentView:
self.torrent_view = self.window.main_glade.get_widget("torrent_view") self.torrent_view = self.window.main_glade.get_widget("torrent_view")
## TreeModel setup ## ## TreeModel setup ##
# UID, Q#, Status Icon, Name, Size, Progress, Message, Seeders, Peers, # UID, Status Icon, Name, Size, Progress, Message, Seeders, Peers,
# DL, UL, ETA, Share # DL, UL, ETA, Share
self.torrent_model = gtk.ListStore(str, int, gtk.gdk.Pixbuf, str, self.torrent_model = gtk.ListStore(str, gtk.gdk.Pixbuf, str,
long, float, str, int, int, int, int, int, int, int, float) long, float, str, int, int, int, int, int, int, int, float)
## TreeView setup ## ## TreeView setup ##
@ -82,9 +82,9 @@ class TorrentView:
self.torrent_view.set_reorderable(True) self.torrent_view.set_reorderable(True)
self.torrent_view.get_selection().set_mode(gtk.SELECTION_MULTIPLE) self.torrent_view.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
self.queue_column = columns.add_text_column( # self.queue_column = columns.add_text_column(
self.torrent_view, "#", # self.torrent_view, "#",
TORRENT_VIEW_COL_QUEUE) # TORRENT_VIEW_COL_QUEUE)
self.name_column = columns.add_texticon_column( self.name_column = columns.add_texticon_column(
self.torrent_view, self.torrent_view,
_("Name"), _("Name"),
@ -138,8 +138,8 @@ class TorrentView:
self.peer_column.set_sort_column_id(TORRENT_VIEW_COL_CONNECTED_PEERS) self.peer_column.set_sort_column_id(TORRENT_VIEW_COL_CONNECTED_PEERS)
# Set the default sort column to the queue column # Set the default sort column to the queue column
self.torrent_model.set_sort_column_id(TORRENT_VIEW_COL_QUEUE, # self.torrent_model.set_sort_column_id(TORRENT_VIEW_COL_QUEUE,
gtk.SORT_ASCENDING) # gtk.SORT_ASCENDING)
### Connect Signals ### ### Connect Signals ###
# Connect to the 'button-press-event' to know when to bring up the # Connect to the 'button-press-event' to know when to bring up the
@ -156,15 +156,15 @@ class TorrentView:
# This function is used for the foreach method of the treemodel # This function is used for the foreach method of the treemodel
def update_row(model, path, row, user_data): def update_row(model, path, row, user_data):
torrent_id = self.torrent_model.get_value(row, 0) torrent_id = self.torrent_model.get_value(row, 0)
status_keys = ["queue", "progress", "state", "num_seeds", status_keys = ["progress", "state", "num_seeds",
"num_peers", "download_payload_rate", "upload_payload_rate", "num_peers", "download_payload_rate", "upload_payload_rate",
"eta"] "eta"]
status = functions.get_torrent_status(self.core, torrent_id, status = functions.get_torrent_status(self.core, torrent_id,
status_keys) status_keys)
# Set values for each column in the row # Set values for each column in the row
self.torrent_model.set_value(row, TORRENT_VIEW_COL_QUEUE, # self.torrent_model.set_value(row, TORRENT_VIEW_COL_QUEUE,
status["queue"]+1) # status["queue"]+1)
self.torrent_model.set_value(row, TORRENT_VIEW_COL_PROGRESS, self.torrent_model.set_value(row, TORRENT_VIEW_COL_PROGRESS,
status["progress"]*100) status["progress"]*100)
self.torrent_model.set_value(row, TORRENT_VIEW_COL_STATUS, self.torrent_model.set_value(row, TORRENT_VIEW_COL_STATUS,
@ -190,15 +190,16 @@ class TorrentView:
def add_row(self, torrent_id): def add_row(self, torrent_id):
"""Adds a new torrent row to the treeview""" """Adds a new torrent row to the treeview"""
# Get the status and info dictionaries # Get the status and info dictionaries
status_keys = ["queue", "name", "total_size", "progress", "state", status_keys = ["name", "total_size", "progress", "state",
"num_seeds", "num_peers", "download_payload_rate", "num_seeds", "num_peers", "download_payload_rate",
"upload_payload_rate", "eta"] "upload_payload_rate", "eta"]
status = functions.get_torrent_status(self.core, torrent_id, status = functions.get_torrent_status(self.core, torrent_id,
status_keys) status_keys)
# Insert the row with info provided from core # Insert the row with info provided from core
self.torrent_model.insert(status["queue"], [ #self.torrent_model.insert(status["queue"], [
self.torrent_model.append([
torrent_id, torrent_id,
status["queue"]+1, # status["queue"]+1,
None, None,
status["name"], status["name"],
status["total_size"], status["total_size"],