mirror of
https://git.deluge-torrent.org/deluge
synced 2025-08-03 15:08:40 +00:00
torrent piece plugin - micah
This commit is contained in:
parent
d1342efc67
commit
b6ee1d0e37
11 changed files with 561 additions and 30 deletions
|
@ -183,6 +183,63 @@ namespace libtorrent
|
||||||
{ return std::auto_ptr<alert>(new torrent_finished_alert(*this)); }
|
{ return std::auto_ptr<alert>(new torrent_finished_alert(*this)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TORRENT_EXPORT piece_finished_alert: torrent_alert
|
||||||
|
{
|
||||||
|
piece_finished_alert(
|
||||||
|
const torrent_handle& h
|
||||||
|
, int piece_num
|
||||||
|
, const std::string& msg)
|
||||||
|
: torrent_alert(h, alert::warning, msg)
|
||||||
|
, piece_index(piece_num)
|
||||||
|
{ assert(piece_index >= 0);}
|
||||||
|
|
||||||
|
int piece_index;
|
||||||
|
|
||||||
|
virtual std::auto_ptr<alert> clone() const
|
||||||
|
{ return std::auto_ptr<alert>(new piece_finished_alert(*this)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TORRENT_EXPORT block_finished_alert: torrent_alert
|
||||||
|
{
|
||||||
|
block_finished_alert(
|
||||||
|
const torrent_handle& h
|
||||||
|
, int block_num
|
||||||
|
, int piece_num
|
||||||
|
, const std::string& msg)
|
||||||
|
: torrent_alert(h, alert::warning, msg)
|
||||||
|
, block_index(block_num)
|
||||||
|
, piece_index(piece_num)
|
||||||
|
{ assert(block_index >= 0 && piece_index >= 0);}
|
||||||
|
|
||||||
|
int block_index;
|
||||||
|
int piece_index;
|
||||||
|
|
||||||
|
virtual std::auto_ptr<alert> clone() const
|
||||||
|
{ return std::auto_ptr<alert>(new block_finished_alert(*this)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TORRENT_EXPORT block_downloading_alert: torrent_alert
|
||||||
|
{
|
||||||
|
block_downloading_alert(
|
||||||
|
const torrent_handle& h
|
||||||
|
, std::string& speedmsg
|
||||||
|
, int block_num
|
||||||
|
, int piece_num
|
||||||
|
, const std::string& msg)
|
||||||
|
: torrent_alert(h, alert::warning, msg)
|
||||||
|
, peer_speedmsg(speedmsg)
|
||||||
|
, block_index(block_num)
|
||||||
|
, piece_index(piece_num)
|
||||||
|
{ assert(block_index >= 0 && piece_index >= 0);}
|
||||||
|
|
||||||
|
std::string peer_speedmsg;
|
||||||
|
int block_index;
|
||||||
|
int piece_index;
|
||||||
|
|
||||||
|
virtual std::auto_ptr<alert> clone() const
|
||||||
|
{ return std::auto_ptr<alert>(new block_downloading_alert(*this)); }
|
||||||
|
};
|
||||||
|
|
||||||
struct TORRENT_EXPORT storage_moved_alert: torrent_alert
|
struct TORRENT_EXPORT storage_moved_alert: torrent_alert
|
||||||
{
|
{
|
||||||
storage_moved_alert(torrent_handle const& h, std::string const& path)
|
storage_moved_alert(torrent_handle const& h, std::string const& path)
|
||||||
|
|
|
@ -241,6 +241,12 @@ namespace libtorrent
|
||||||
enum { max_blocks_per_piece = 256 };
|
enum { max_blocks_per_piece = 256 };
|
||||||
int piece_index;
|
int piece_index;
|
||||||
int blocks_in_piece;
|
int blocks_in_piece;
|
||||||
|
// the number of blocks in the finished state
|
||||||
|
int finished;
|
||||||
|
// the number of blocks in the writing state
|
||||||
|
int writing;
|
||||||
|
// the number of blocks in the requested state
|
||||||
|
int requested;
|
||||||
block_info blocks[max_blocks_per_piece];
|
block_info blocks[max_blocks_per_piece];
|
||||||
enum state_t { none, slow, medium, fast };
|
enum state_t { none, slow, medium, fast };
|
||||||
state_t piece_state;
|
state_t piece_state;
|
||||||
|
|
|
@ -1183,6 +1183,11 @@ namespace libtorrent
|
||||||
assert(p.start == j.offset);
|
assert(p.start == j.offset);
|
||||||
piece_block block_finished(p.piece, p.start / t->block_size());
|
piece_block block_finished(p.piece, p.start / t->block_size());
|
||||||
picker.mark_as_finished(block_finished, peer_info_struct());
|
picker.mark_as_finished(block_finished, peer_info_struct());
|
||||||
|
if (t->alerts().should_post(alert::info))
|
||||||
|
{
|
||||||
|
t->alerts().post_alert(block_finished_alert(t->get_handle(),
|
||||||
|
block_finished.block_index, block_finished.piece_index, "block finished"));
|
||||||
|
}
|
||||||
|
|
||||||
if (!has_peer_choked() && !t->is_seed() && !m_torrent.expired())
|
if (!has_peer_choked() && !t->is_seed() && !m_torrent.expired())
|
||||||
{
|
{
|
||||||
|
@ -1290,11 +1295,29 @@ namespace libtorrent
|
||||||
|
|
||||||
piece_picker::piece_state_t state;
|
piece_picker::piece_state_t state;
|
||||||
peer_speed_t speed = peer_speed();
|
peer_speed_t speed = peer_speed();
|
||||||
if (speed == fast) state = piece_picker::fast;
|
std::string speedmsg;
|
||||||
else if (speed == medium) state = piece_picker::medium;
|
if (speed == fast)
|
||||||
else state = piece_picker::slow;
|
{
|
||||||
|
speedmsg = "fast";
|
||||||
|
state = piece_picker::fast;
|
||||||
|
}
|
||||||
|
else if (speed == medium)
|
||||||
|
{
|
||||||
|
speedmsg = "medium";
|
||||||
|
state = piece_picker::medium;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
speedmsg = "slow";
|
||||||
|
state = piece_picker::slow;
|
||||||
|
}
|
||||||
|
|
||||||
t->picker().mark_as_downloading(block, peer_info_struct(), state);
|
t->picker().mark_as_downloading(block, peer_info_struct(), state);
|
||||||
|
if (t->alerts().should_post(alert::info))
|
||||||
|
{
|
||||||
|
t->alerts().post_alert(block_downloading_alert(t->get_handle(),
|
||||||
|
speedmsg, block.block_index, block.piece_index, "block downloading"));
|
||||||
|
}
|
||||||
|
|
||||||
m_request_queue.push_back(block);
|
m_request_queue.push_back(block);
|
||||||
}
|
}
|
||||||
|
|
|
@ -831,6 +831,11 @@ namespace libtorrent
|
||||||
|
|
||||||
if (passed_hash_check)
|
if (passed_hash_check)
|
||||||
{
|
{
|
||||||
|
if (m_ses.m_alerts.should_post(alert::info))
|
||||||
|
{
|
||||||
|
m_ses.m_alerts.post_alert(piece_finished_alert(get_handle()
|
||||||
|
, index, "piece finished"));
|
||||||
|
}
|
||||||
// the following call may cause picker to become invalid
|
// the following call may cause picker to become invalid
|
||||||
// in case we just became a seed
|
// in case we just became a seed
|
||||||
announce_piece(index);
|
announce_piece(index);
|
||||||
|
|
|
@ -773,6 +773,9 @@ namespace libtorrent
|
||||||
partial_piece_info pi;
|
partial_piece_info pi;
|
||||||
pi.piece_state = (partial_piece_info::state_t)i->state;
|
pi.piece_state = (partial_piece_info::state_t)i->state;
|
||||||
pi.blocks_in_piece = p.blocks_in_piece(i->index);
|
pi.blocks_in_piece = p.blocks_in_piece(i->index);
|
||||||
|
pi.finished = (int)i->finished;
|
||||||
|
pi.writing = (int)i->writing;
|
||||||
|
pi.requested = (int)i->requested;
|
||||||
int piece_size = t->torrent_file().piece_size(i->index);
|
int piece_size = t->torrent_file().piece_size(i->index);
|
||||||
for (int j = 0; j < pi.blocks_in_piece; ++j)
|
for (int j = 0; j < pi.blocks_in_piece; ++j)
|
||||||
{
|
{
|
||||||
|
|
98
plugins/TorrentPieces/__init__.py
Normal file
98
plugins/TorrentPieces/__init__.py
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
# Copyright (C) 2007 - Micah Bucy <eternalsword@gmail.com>
|
||||||
|
#
|
||||||
|
# This program is free software; you can 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, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# This program 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 this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
### Initialization ###
|
||||||
|
|
||||||
|
plugin_name = _("Torrent Pieces")
|
||||||
|
plugin_author = "Micah Bucy"
|
||||||
|
plugin_version = "0.1"
|
||||||
|
plugin_description = _("""
|
||||||
|
Adds a pieces tab which gives piece by piece progress for a torrent.
|
||||||
|
Each piece is represented by a small progress bar.
|
||||||
|
|
||||||
|
Pieces currently downloading show up as partially filled progress bars,
|
||||||
|
but this does not represent percentage done.
|
||||||
|
|
||||||
|
More information is provided as a tooltip for each piece.
|
||||||
|
For currently downloading pieces, the tooltip contains the number
|
||||||
|
of blocks finished as well as the peer speed for that piece.
|
||||||
|
|
||||||
|
When the plugin initializes, such as when enabling the plugin or
|
||||||
|
when a different torrent is selected, the cpu will spike. This is normal,
|
||||||
|
as initialization must get information on every piece from libtorrent,
|
||||||
|
and the cpu will normalize once all of the information is retrieved.""")
|
||||||
|
|
||||||
|
def deluge_init(deluge_path):
|
||||||
|
global path
|
||||||
|
path = deluge_path
|
||||||
|
|
||||||
|
def enable(core, interface):
|
||||||
|
global path
|
||||||
|
return TorrentPieces(path, core, interface)
|
||||||
|
|
||||||
|
### The Plugin ###
|
||||||
|
import deluge
|
||||||
|
import gtk
|
||||||
|
from TorrentPieces.tab_pieces import PiecesManager
|
||||||
|
|
||||||
|
class TorrentPieces:
|
||||||
|
|
||||||
|
def __init__(self, path, core, interface):
|
||||||
|
print "Loading TorrentPieces plugin..."
|
||||||
|
self.manager = core
|
||||||
|
self.parent = interface
|
||||||
|
self.table = gtk.Table()
|
||||||
|
self.viewport = gtk.Viewport()
|
||||||
|
self.viewport.add(self.table)
|
||||||
|
self.scrolledWindow = gtk.ScrolledWindow()
|
||||||
|
self.scrolledWindow.add(self.viewport)
|
||||||
|
self.scrolledWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||||
|
|
||||||
|
self.topWidget = self.scrolledWindow
|
||||||
|
|
||||||
|
self.parentNotebook = self.parent.notebook
|
||||||
|
|
||||||
|
self.parentNotebook.append_page(self.topWidget, gtk.Label(_("Pieces")))
|
||||||
|
self.viewport.show()
|
||||||
|
self.scrolledWindow.show()
|
||||||
|
self.table.show()
|
||||||
|
self.tab_pieces = PiecesManager(self.table, self.manager)
|
||||||
|
|
||||||
|
def unload(self):
|
||||||
|
self.manager.disconnect_event(self.manager.constants['EVENT_PIECE_FINISHED'], self.tab_pieces.handle_event)
|
||||||
|
self.manager.disconnect_event(self.manager.constants['EVENT_BLOCK_FINISHED'], self.tab_pieces.handle_event)
|
||||||
|
self.manager.disconnect_event(self.manager.constants['EVENT_BLOCK_DOWNLOADING'], self.tab_pieces.handle_event)
|
||||||
|
numPages = self.parentNotebook.get_n_pages()
|
||||||
|
for page in xrange(numPages):
|
||||||
|
if self.parentNotebook.get_nth_page(page) == self.topWidget:
|
||||||
|
self.parentNotebook.remove_page(page)
|
||||||
|
break
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
unique_id = self.parent.get_selected_torrent()
|
||||||
|
# If no torrents added or more than one torrent selected
|
||||||
|
if unique_id is None:
|
||||||
|
return
|
||||||
|
if unique_id != self.tab_pieces.unique_id:
|
||||||
|
self.manager.disconnect_event(self.manager.constants['EVENT_PIECE_FINISHED'], self.tab_pieces.handle_event)
|
||||||
|
self.manager.disconnect_event(self.manager.constants['EVENT_BLOCK_FINISHED'], self.tab_pieces.handle_event)
|
||||||
|
self.manager.disconnect_event(self.manager.constants['EVENT_BLOCK_DOWNLOADING'], self.tab_pieces.handle_event)
|
||||||
|
self.tab_pieces.clear_pieces_store()
|
||||||
|
self.tab_pieces.set_unique_id(unique_id)
|
||||||
|
self.tab_pieces.prepare_pieces_store()
|
||||||
|
self.manager.connect_event(self.manager.constants['EVENT_PIECE_FINISHED'], self.tab_pieces.handle_event)
|
||||||
|
self.manager.connect_event(self.manager.constants['EVENT_BLOCK_FINISHED'], self.tab_pieces.handle_event)
|
||||||
|
self.manager.connect_event(self.manager.constants['EVENT_BLOCK_DOWNLOADING'], self.tab_pieces.handle_event)
|
115
plugins/TorrentPieces/tab_pieces.py
Normal file
115
plugins/TorrentPieces/tab_pieces.py
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
import gtk
|
||||||
|
|
||||||
|
import math
|
||||||
|
|
||||||
|
class PiecesManager(object):
|
||||||
|
def __init__(self, table, manager):
|
||||||
|
self.table = table
|
||||||
|
self.manager = manager
|
||||||
|
self.progress = []
|
||||||
|
self.tooltips = []
|
||||||
|
self.eventboxes = []
|
||||||
|
self.rows = 0
|
||||||
|
self.columns = 33
|
||||||
|
self.piece_width = 30
|
||||||
|
self.piece_height = 20
|
||||||
|
self.unique_id = -1
|
||||||
|
self.peer_speed = []
|
||||||
|
self.piece_info = []
|
||||||
|
|
||||||
|
def set_unique_id(self, unique_id):
|
||||||
|
self.unique_id = unique_id
|
||||||
|
|
||||||
|
def clear_pieces_store(self):
|
||||||
|
self.unique_id = -1
|
||||||
|
self.rows = 0
|
||||||
|
for widget in self.eventboxes:
|
||||||
|
widget.destroy()
|
||||||
|
for widget in self.progress:
|
||||||
|
widget.hide()
|
||||||
|
widget.destroy()
|
||||||
|
self.peer_speed = []
|
||||||
|
self.eventboxes = []
|
||||||
|
self.progress = []
|
||||||
|
self.piece_info = []
|
||||||
|
self.tooltips = []
|
||||||
|
|
||||||
|
def prepare_pieces_store(self):
|
||||||
|
state = self.manager.get_torrent_state(self.unique_id)
|
||||||
|
num_pieces = state["num_pieces"]
|
||||||
|
self.rows = int(math.ceil(num_pieces/self.columns))
|
||||||
|
self.table.resize(self.rows, self.columns)
|
||||||
|
self.table.set_size_request((self.columns+1)*self.piece_width, (self.rows+1)*self.piece_height)
|
||||||
|
for index in xrange(num_pieces):
|
||||||
|
self.piece_info.append({'blocks_total':0, 'blocks_finished':0, 'blocks_requested':0})
|
||||||
|
self.progress.append(gtk.ProgressBar())
|
||||||
|
self.tooltips.append(gtk.Tooltips())
|
||||||
|
self.eventboxes.append(gtk.EventBox())
|
||||||
|
self.peer_speed.append("unknown")
|
||||||
|
self.progress[index].set_size_request(self.piece_width, self.piece_height)
|
||||||
|
row = index/self.columns
|
||||||
|
column = index%self.columns
|
||||||
|
self.table.attach(self.eventboxes[index], column, column+1, row, row+1,
|
||||||
|
xoptions=0, yoptions=0, xpadding=0, ypadding=0)
|
||||||
|
self.eventboxes[index].add(self.progress[index])
|
||||||
|
if self.manager.has_piece(self.unique_id, index):
|
||||||
|
self.progress[index].set_fraction(1)
|
||||||
|
self.tooltips[index].set_tip(self.eventboxes[index], _("Piece finished"))
|
||||||
|
else:
|
||||||
|
self.tooltips[index].set_tip(self.eventboxes[index], _("Piece not started"))
|
||||||
|
self.eventboxes[index].show_all()
|
||||||
|
all_piece_info = self.manager.get_all_piece_info(self.unique_id)
|
||||||
|
for piece_index in all_piece_info:
|
||||||
|
temp_piece_info = {'blocks_total':piece_index['blocks_total'], \
|
||||||
|
'blocks_finished':piece_index['blocks_finished']}
|
||||||
|
self.piece_info[piece_index['piece_index']] = temp_piece_info
|
||||||
|
blocks_total = str(temp_piece_info['blocks_total'])
|
||||||
|
info_string = str(temp_piece_info['blocks_finished']) + "/" + blocks_total + " " + _("blocks finished") + "\n" \
|
||||||
|
+ _("peer speed: unknown")
|
||||||
|
if self.progress[index].get_fraction() == 0:
|
||||||
|
self.progress[index].set_fraction(0.5)
|
||||||
|
self.tooltips[index].set_tip(self.eventboxes[index], info_string)
|
||||||
|
|
||||||
|
def handle_event(self, event):
|
||||||
|
if event['event_type'] is self.manager.constants['EVENT_PIECE_FINISHED']:
|
||||||
|
if event['unique_ID'] == self.unique_id:
|
||||||
|
self.update_pieces_store(event['piece_index'], piece_finished=True)
|
||||||
|
elif event['event_type'] is self.manager.constants['EVENT_BLOCK_DOWNLOADING']:
|
||||||
|
if event['unique_ID'] == self.unique_id:
|
||||||
|
index = event['piece_index']
|
||||||
|
if self.piece_info[index]['blocks_total'] == 0:
|
||||||
|
self.piece_info[index] = self.manager.get_piece_info(self.unique_id, index)
|
||||||
|
temp_peer_speed = event['peer_speed']
|
||||||
|
if temp_peer_speed == "fast":
|
||||||
|
peer_speed_msg = _("fast")
|
||||||
|
elif temp_peer_speed == "slow":
|
||||||
|
peer_speed_msg = _("slow")
|
||||||
|
elif temp_peer_speed == "medium":
|
||||||
|
peer_speed_msg = _("medium")
|
||||||
|
else:
|
||||||
|
peer_speed_msg = _("unknown")
|
||||||
|
self.peer_speed[index] = peer_speed_msg
|
||||||
|
self.update_pieces_store(index)
|
||||||
|
else:
|
||||||
|
if event['unique_ID'] == self.unique_id:
|
||||||
|
index = event['piece_index']
|
||||||
|
if self.piece_info[index]['blocks_total'] == 0:
|
||||||
|
self.piece_info[index] = self.manager.get_piece_info(self.unique_id, index)
|
||||||
|
else:
|
||||||
|
self.piece_info[index]['blocks_finished'] += 1
|
||||||
|
self.update_pieces_store(event['piece_index'])
|
||||||
|
|
||||||
|
def update_pieces_store(self, index, piece_finished=False):
|
||||||
|
if piece_finished:
|
||||||
|
self.progress[index].set_fraction(1)
|
||||||
|
self.tooltips[index].set_tip(self.eventboxes[index], _("Piece finished"))
|
||||||
|
else:
|
||||||
|
temp_fraction = self.progress[index].get_fraction()
|
||||||
|
if temp_fraction == 0:
|
||||||
|
self.progress[index].set_fraction(0.5)
|
||||||
|
if temp_fraction != 1:
|
||||||
|
temp_piece_info = self.piece_info[index]
|
||||||
|
blocks_total = str(temp_piece_info['blocks_total'])
|
||||||
|
info_string = str(temp_piece_info['blocks_finished']) + "/" + blocks_total + " " + _("blocks finished") + "\n" \
|
||||||
|
+ _("peer speed: ") + self.peer_speed[index]
|
||||||
|
self.tooltips[index].set_tip(self.eventboxes[index], info_string)
|
|
@ -30,3 +30,5 @@ plugins/BlocklistImport/ui.py
|
||||||
plugins/BlocklistImport/text.py
|
plugins/BlocklistImport/text.py
|
||||||
plugins/BlocklistImport/test.py
|
plugins/BlocklistImport/test.py
|
||||||
plugins/BlocklistImport/peerguardian.py
|
plugins/BlocklistImport/peerguardian.py
|
||||||
|
plugins/TorrentPieces/__init__.py
|
||||||
|
plugins/TorrentPieces/tab_pieces.py
|
||||||
|
|
|
@ -1377,3 +1377,68 @@ msgstr ""
|
||||||
#: plugins/BlocklistImport/peerguardian.py:37
|
#: plugins/BlocklistImport/peerguardian.py:37
|
||||||
msgid "Invalid version"
|
msgid "Invalid version"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/TorrentPieces/__init__.py:22
|
||||||
|
msgid "Torrent Pieces"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/TorrentPieces/__init__.py:22
|
||||||
|
msgid ""
|
||||||
|
"\n"
|
||||||
|
"Adds a pieces tab which gives piece by piece progress for a torrent.\n"
|
||||||
|
"Each piece is represented by a small progress bar.\n"
|
||||||
|
"\n"
|
||||||
|
"Pieces currently downloading show up as partially filled progress bars,\n"
|
||||||
|
"but this does not represent percentage done.\n"
|
||||||
|
"\n"
|
||||||
|
"More information is provided as a tooltip for each piece.\n"
|
||||||
|
"For currently downloading pieces, the tooltip contains the number\n"
|
||||||
|
"of blocks finished as well as the peer speed for that piece.\n"
|
||||||
|
"\n"
|
||||||
|
"When the plugin initializes, such as when enabling the plugin or\n"
|
||||||
|
"when a different torrent is selected, the cpu will spike. This is normal,\n"
|
||||||
|
"as initialization must get information on every piece from libtorrent,\n"
|
||||||
|
"and the cpu will normalize once all of the information is retrieved.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/TorrentPieces/__init__.py:68
|
||||||
|
msgid "Pieces"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/TorrentPieces/tab_pieces.py:57
|
||||||
|
#: plugins/TorrentPieces/tab_pieces.py:105
|
||||||
|
msgid "Piece finished"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/TorrentPieces/tab_pieces.py:59
|
||||||
|
msgid "Piece not started"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/TorrentPieces/tab_pieces.py:67
|
||||||
|
#: plugins/TorrentPieces/tab_pieces.py:113
|
||||||
|
msgid "blocks finished"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/TorrentPieces/tab_pieces.py:68
|
||||||
|
msgid "peer speed: unknown"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/TorrentPieces/tab_pieces.py:84
|
||||||
|
msgid "fast"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/TorrentPieces/tab_pieces.py:86
|
||||||
|
msgid "slow"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/TorrentPieces/tab_pieces.py:88
|
||||||
|
msgid "medium"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/TorrentPieces/tab_pieces.py:90
|
||||||
|
msgid "unknown"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: plugins/TorrentPieces/tab_pieces.py:114
|
||||||
|
msgid "peer speed: "
|
||||||
|
msgstr ""
|
||||||
|
|
11
src/core.py
11
src/core.py
|
@ -318,6 +318,10 @@ class Manager:
|
||||||
# Get the value from the preferences object
|
# Get the value from the preferences object
|
||||||
return self.config.get(key)
|
return self.config.get(key)
|
||||||
|
|
||||||
|
# Check if piece is finished
|
||||||
|
def has_piece(self, unique_id, piece_index):
|
||||||
|
return deluge_core.has_piece(unique_id, piece_index)
|
||||||
|
|
||||||
# Dump torrent info without adding
|
# Dump torrent info without adding
|
||||||
def dump_torrent_file_info(self, torrent):
|
def dump_torrent_file_info(self, torrent):
|
||||||
return deluge_core.dump_file_info(torrent)
|
return deluge_core.dump_file_info(torrent)
|
||||||
|
@ -437,6 +441,12 @@ class Manager:
|
||||||
def get_torrent_file_info(self, unique_ID):
|
def get_torrent_file_info(self, unique_ID):
|
||||||
return self.get_core_torrent_file_info(unique_ID)
|
return self.get_core_torrent_file_info(unique_ID)
|
||||||
|
|
||||||
|
def get_piece_info(self, unique_ID, piece_index):
|
||||||
|
return deluge_core.get_piece_info(unique_ID, piece_index)
|
||||||
|
|
||||||
|
def get_all_piece_info(self, unique_ID):
|
||||||
|
return deluge_core.get_all_piece_info(unique_ID)
|
||||||
|
|
||||||
# Queueing functions
|
# Queueing functions
|
||||||
|
|
||||||
def queue_top(self, unique_ID, enforce_queue=True):
|
def queue_top(self, unique_ID, enforce_queue=True):
|
||||||
|
@ -572,7 +582,6 @@ class Manager:
|
||||||
event['unique_ID'] not in self.unique_IDs:
|
event['unique_ID'] not in self.unique_IDs:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Call plugins events callbacks
|
|
||||||
if event['event_type'] in self.event_callbacks:
|
if event['event_type'] in self.event_callbacks:
|
||||||
for callback in self.event_callbacks[event['event_type']]:
|
for callback in self.event_callbacks[event['event_type']]:
|
||||||
callback(event)
|
callback(event)
|
||||||
|
|
|
@ -83,7 +83,9 @@ using namespace libtorrent;
|
||||||
#define EVENT_TRACKER_WARNING 12
|
#define EVENT_TRACKER_WARNING 12
|
||||||
#define EVENT_OTHER 13
|
#define EVENT_OTHER 13
|
||||||
#define EVENT_STORAGE_MOVED 14
|
#define EVENT_STORAGE_MOVED 14
|
||||||
|
#define EVENT_PIECE_FINISHED 15
|
||||||
|
#define EVENT_BLOCK_DOWNLOADING 16
|
||||||
|
#define EVENT_BLOCK_FINISHED 17
|
||||||
|
|
||||||
#define STATE_QUEUED 0
|
#define STATE_QUEUED 0
|
||||||
#define STATE_CHECKING 1
|
#define STATE_CHECKING 1
|
||||||
|
@ -181,6 +183,17 @@ long get_index_from_unique_ID(long unique_ID)
|
||||||
RAISE_INT(DelugeError, "No such unique_ID.");
|
RAISE_INT(DelugeError, "No such unique_ID.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
partial_piece_info internal_get_piece_info(torrent_handle h, long piece_index)
|
||||||
|
{
|
||||||
|
std::vector<partial_piece_info> queue;
|
||||||
|
std::vector<partial_piece_info>& q = queue;
|
||||||
|
h.get_download_queue(q);
|
||||||
|
for (unsigned long i = 0; i < q.size(); i++)
|
||||||
|
{
|
||||||
|
if ((long)q[i].piece_index == piece_index) return queue[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
torrent_info internal_get_torrent_info(std::string const& torrent_name)
|
torrent_info internal_get_torrent_info(std::string const& torrent_name)
|
||||||
{
|
{
|
||||||
std::ifstream in(torrent_name.c_str(), std::ios_base::binary);
|
std::ifstream in(torrent_name.c_str(), std::ios_base::binary);
|
||||||
|
@ -264,6 +277,10 @@ long get_peer_index(tcp::endpoint addr, std::vector<peer_info> const& peers)
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool internal_has_piece(std::vector<bool> const& pieces, long index)
|
||||||
|
{
|
||||||
|
return pieces[index];
|
||||||
|
}
|
||||||
|
|
||||||
// The following function contains code by Christophe Dumez and Arvid Norberg
|
// The following function contains code by Christophe Dumez and Arvid Norberg
|
||||||
void internal_add_files(torrent_info& t,
|
void internal_add_files(torrent_info& t,
|
||||||
|
@ -359,29 +376,32 @@ static PyObject *torrent_init(PyObject *self, PyObject *args)
|
||||||
|
|
||||||
M_ses->add_extension(&libtorrent::create_metadata_plugin);
|
M_ses->add_extension(&libtorrent::create_metadata_plugin);
|
||||||
|
|
||||||
M_constants = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i}",
|
M_constants = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i}",
|
||||||
"EVENT_NULL", EVENT_NULL,
|
"EVENT_NULL", EVENT_NULL,
|
||||||
"EVENT_FINISHED", EVENT_FINISHED,
|
"EVENT_FINISHED", EVENT_FINISHED,
|
||||||
"EVENT_PEER_ERROR", EVENT_PEER_ERROR,
|
"EVENT_PEER_ERROR", EVENT_PEER_ERROR,
|
||||||
"EVENT_INVALID_REQUEST", EVENT_INVALID_REQUEST,
|
"EVENT_INVALID_REQUEST", EVENT_INVALID_REQUEST,
|
||||||
"EVENT_FILE_ERROR", EVENT_FILE_ERROR,
|
"EVENT_FILE_ERROR", EVENT_FILE_ERROR,
|
||||||
"EVENT_HASH_FAILED_ERROR", EVENT_HASH_FAILED_ERROR,
|
"EVENT_HASH_FAILED_ERROR", EVENT_HASH_FAILED_ERROR,
|
||||||
"EVENT_PEER_BAN_ERROR", EVENT_PEER_BAN_ERROR,
|
"EVENT_PEER_BAN_ERROR", EVENT_PEER_BAN_ERROR,
|
||||||
"EVENT_FASTRESUME_REJECTED_ERROR", EVENT_FASTRESUME_REJECTED_ERROR,
|
"EVENT_FASTRESUME_REJECTED_ERROR", EVENT_FASTRESUME_REJECTED_ERROR,
|
||||||
"EVENT_TRACKER_ANNOUNCE", EVENT_TRACKER_ANNOUNCE,
|
"EVENT_TRACKER_ANNOUNCE", EVENT_TRACKER_ANNOUNCE,
|
||||||
"EVENT_TRACKER_REPLY", EVENT_TRACKER_REPLY,
|
"EVENT_TRACKER_REPLY", EVENT_TRACKER_REPLY,
|
||||||
"EVENT_TRACKER_ALERT", EVENT_TRACKER_ALERT,
|
"EVENT_TRACKER_ALERT", EVENT_TRACKER_ALERT,
|
||||||
"EVENT_TRACKER_WARNING", EVENT_TRACKER_WARNING,
|
"EVENT_TRACKER_WARNING", EVENT_TRACKER_WARNING,
|
||||||
"EVENT_OTHER", EVENT_OTHER,
|
"EVENT_OTHER", EVENT_OTHER,
|
||||||
"EVENT_STORAGE_MOVED", EVENT_STORAGE_MOVED,
|
"EVENT_STORAGE_MOVED", EVENT_STORAGE_MOVED,
|
||||||
"STATE_QUEUED", STATE_QUEUED,
|
"EVENT_PIECE_FINISHED", EVENT_PIECE_FINISHED,
|
||||||
"STATE_CHECKING", STATE_CHECKING,
|
"EVENT_BLOCK_DOWNLOADING", EVENT_BLOCK_DOWNLOADING,
|
||||||
"STATE_CONNECTING", STATE_CONNECTING,
|
"EVENT_BLOCK_FINISHED", EVENT_BLOCK_FINISHED,
|
||||||
"STATE_DOWNLOADING_META", STATE_DOWNLOADING_META,
|
"STATE_QUEUED", STATE_QUEUED,
|
||||||
"STATE_DOWNLOADING", STATE_DOWNLOADING,
|
"STATE_CHECKING", STATE_CHECKING,
|
||||||
"STATE_FINISHED", STATE_FINISHED,
|
"STATE_CONNECTING", STATE_CONNECTING,
|
||||||
"STATE_SEEDING", STATE_SEEDING,
|
"STATE_DOWNLOADING_META", STATE_DOWNLOADING_META,
|
||||||
"STATE_ALLOCATING", STATE_ALLOCATING);
|
"STATE_DOWNLOADING", STATE_DOWNLOADING,
|
||||||
|
"STATE_FINISHED", STATE_FINISHED,
|
||||||
|
"STATE_SEEDING", STATE_SEEDING,
|
||||||
|
"STATE_ALLOCATING", STATE_ALLOCATING);
|
||||||
|
|
||||||
Py_INCREF(Py_None); return Py_None;
|
Py_INCREF(Py_None); return Py_None;
|
||||||
};
|
};
|
||||||
|
@ -733,6 +753,77 @@ static PyObject *torrent_resume(PyObject *self, PyObject *args)
|
||||||
Py_INCREF(Py_None); return Py_None;
|
Py_INCREF(Py_None); return Py_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *torrent_has_piece(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
python_long unique_ID;
|
||||||
|
long piece_index;
|
||||||
|
bool has_piece;
|
||||||
|
if (!PyArg_ParseTuple(args, "ii", &unique_ID, &piece_index))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
long index = get_index_from_unique_ID(unique_ID);
|
||||||
|
if (PyErr_Occurred())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
torrent_status s = M_torrents->at(index).handle.status();
|
||||||
|
has_piece = internal_has_piece(*s.pieces, piece_index);
|
||||||
|
return Py_BuildValue("b", has_piece);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *torrent_get_all_piece_info(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
python_long unique_ID;
|
||||||
|
if (!PyArg_ParseTuple(args, "i", &unique_ID))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
long index = get_index_from_unique_ID(unique_ID);
|
||||||
|
if (PyErr_Occurred())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
torrent_handle h = M_torrents->at(index).handle;
|
||||||
|
std::vector<partial_piece_info> queue;
|
||||||
|
std::vector<partial_piece_info>& q = queue;
|
||||||
|
h.get_download_queue(q);
|
||||||
|
PyObject *piece_info;
|
||||||
|
long piece_index = 0;
|
||||||
|
PyObject *ret = PyTuple_New(q.size());
|
||||||
|
|
||||||
|
for(unsigned long i=0; i<q.size(); i++)
|
||||||
|
{
|
||||||
|
piece_info = Py_BuildValue("{s:i,s:i,s:i}",
|
||||||
|
"piece_index", q[i].piece_index,
|
||||||
|
"blocks_total", q[i].blocks_in_piece,
|
||||||
|
"blocks_finished", q[i].finished);
|
||||||
|
|
||||||
|
PyTuple_SetItem(ret, piece_index, piece_info);
|
||||||
|
piece_index++;
|
||||||
|
};
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *torrent_get_piece_info(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
python_long unique_ID;
|
||||||
|
long piece_index;
|
||||||
|
if (!PyArg_ParseTuple(args, "ii", &unique_ID, &piece_index))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
long index = get_index_from_unique_ID(unique_ID);
|
||||||
|
if (PyErr_Occurred())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
torrent_handle h = M_torrents->at(index).handle;
|
||||||
|
partial_piece_info piece_info = internal_get_piece_info(h, piece_index);
|
||||||
|
int blocks_total=0, blocks_finished=0;
|
||||||
|
if(piece_info.piece_index == piece_index)
|
||||||
|
{
|
||||||
|
blocks_total = piece_info.blocks_in_piece;
|
||||||
|
blocks_finished = piece_info.finished;
|
||||||
|
}
|
||||||
|
return Py_BuildValue("{s:i,s:i}",
|
||||||
|
"blocks_total", blocks_total,
|
||||||
|
"blocks_finished", blocks_finished);
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *torrent_get_torrent_state(PyObject *self, PyObject *args)
|
static PyObject *torrent_get_torrent_state(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
@ -810,6 +901,60 @@ static PyObject *torrent_pop_event(PyObject *self, PyObject *args)
|
||||||
if (!popped_alert)
|
if (!popped_alert)
|
||||||
{
|
{
|
||||||
Py_INCREF(Py_None); return Py_None;
|
Py_INCREF(Py_None); return Py_None;
|
||||||
|
} else if (dynamic_cast<block_downloading_alert*>(popped_alert))
|
||||||
|
{
|
||||||
|
torrent_handle handle = (dynamic_cast<block_downloading_alert*>(popped_alert))->handle;
|
||||||
|
int piece_index = (dynamic_cast<block_downloading_alert*>(popped_alert))->piece_index;
|
||||||
|
int block_index = (dynamic_cast<block_downloading_alert*>(popped_alert))->block_index;
|
||||||
|
std::string speedmsg = (dynamic_cast<block_downloading_alert*>(popped_alert))->peer_speedmsg;
|
||||||
|
long index = get_torrent_index(handle);
|
||||||
|
if (PyErr_Occurred())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (handle_exists(handle))
|
||||||
|
return Py_BuildValue("{s:i,s:i,s:i,s:i,s:s,s:s}",
|
||||||
|
"event_type", EVENT_BLOCK_DOWNLOADING,
|
||||||
|
"unique_ID", M_torrents->at(index).unique_ID,
|
||||||
|
"block_index", block_index,
|
||||||
|
"piece_index", piece_index,
|
||||||
|
"peer_speed", speedmsg.c_str(),
|
||||||
|
"message", a->msg().c_str());
|
||||||
|
else
|
||||||
|
{ Py_INCREF(Py_None); return Py_None; }
|
||||||
|
} else if (dynamic_cast<block_finished_alert*>(popped_alert))
|
||||||
|
{
|
||||||
|
torrent_handle handle = (dynamic_cast<block_finished_alert*>(popped_alert))->handle;
|
||||||
|
int piece_index = (dynamic_cast<block_finished_alert*>(popped_alert))->piece_index;
|
||||||
|
int block_index = (dynamic_cast<block_finished_alert*>(popped_alert))->block_index;
|
||||||
|
long index = get_torrent_index(handle);
|
||||||
|
if (PyErr_Occurred())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (handle_exists(handle))
|
||||||
|
return Py_BuildValue("{s:i,s:i,s:i,s:i,s:s}",
|
||||||
|
"event_type", EVENT_BLOCK_FINISHED,
|
||||||
|
"unique_ID", M_torrents->at(index).unique_ID,
|
||||||
|
"block_index", block_index,
|
||||||
|
"piece_index", piece_index,
|
||||||
|
"message", a->msg().c_str());
|
||||||
|
else
|
||||||
|
{ Py_INCREF(Py_None); return Py_None; }
|
||||||
|
} else if (dynamic_cast<piece_finished_alert*>(popped_alert))
|
||||||
|
{
|
||||||
|
torrent_handle handle = (dynamic_cast<piece_finished_alert*>(popped_alert))->handle;
|
||||||
|
int piece_index = (dynamic_cast<piece_finished_alert*>(popped_alert))->piece_index;
|
||||||
|
long index = get_torrent_index(handle);
|
||||||
|
if (PyErr_Occurred())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (handle_exists(handle))
|
||||||
|
return Py_BuildValue("{s:i,s:i,s:i,s:s}",
|
||||||
|
"event_type", EVENT_PIECE_FINISHED,
|
||||||
|
"unique_ID", M_torrents->at(index).unique_ID,
|
||||||
|
"piece_index", piece_index,
|
||||||
|
"message", a->msg().c_str());
|
||||||
|
else
|
||||||
|
{ Py_INCREF(Py_None); return Py_None; }
|
||||||
} else if (dynamic_cast<torrent_finished_alert*>(popped_alert))
|
} else if (dynamic_cast<torrent_finished_alert*>(popped_alert))
|
||||||
{
|
{
|
||||||
torrent_handle handle = (dynamic_cast<torrent_finished_alert*>(popped_alert))->handle;
|
torrent_handle handle = (dynamic_cast<torrent_finished_alert*>(popped_alert))->handle;
|
||||||
|
@ -1719,6 +1864,9 @@ static PyMethodDef deluge_core_methods[] =
|
||||||
{"prioritize_first_last_pieces", torrent_prioritize_first_last_pieces, METH_VARARGS, "."},
|
{"prioritize_first_last_pieces", torrent_prioritize_first_last_pieces, METH_VARARGS, "."},
|
||||||
{"set_priv", torrent_set_priv, METH_VARARGS, "."},
|
{"set_priv", torrent_set_priv, METH_VARARGS, "."},
|
||||||
{"test_duplicate", torrent_test_duplicate, METH_VARARGS, "."},
|
{"test_duplicate", torrent_test_duplicate, METH_VARARGS, "."},
|
||||||
|
{"has_piece", torrent_has_piece, METH_VARARGS, "."},
|
||||||
|
{"get_piece_info", torrent_get_piece_info, METH_VARARGS, "."},
|
||||||
|
{"get_all_piece_info", torrent_get_all_piece_info, METH_VARARGS, "."},
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue