torrent piece plugin - micah

This commit is contained in:
Marcos Pinto 2007-07-31 06:04:40 +00:00
parent d1342efc67
commit b6ee1d0e37
11 changed files with 561 additions and 30 deletions

View File

@ -183,6 +183,63 @@ namespace libtorrent
{ 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
{
storage_moved_alert(torrent_handle const& h, std::string const& path)

View File

@ -241,6 +241,12 @@ namespace libtorrent
enum { max_blocks_per_piece = 256 };
int piece_index;
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];
enum state_t { none, slow, medium, fast };
state_t piece_state;

View File

@ -1183,6 +1183,11 @@ namespace libtorrent
assert(p.start == j.offset);
piece_block block_finished(p.piece, p.start / t->block_size());
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())
{
@ -1290,11 +1295,29 @@ namespace libtorrent
piece_picker::piece_state_t state;
peer_speed_t speed = peer_speed();
if (speed == fast) state = piece_picker::fast;
else if (speed == medium) state = piece_picker::medium;
else state = piece_picker::slow;
std::string speedmsg;
if (speed == fast)
{
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);
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);
}

View File

@ -831,6 +831,11 @@ namespace libtorrent
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
// in case we just became a seed
announce_piece(index);

View File

@ -773,6 +773,9 @@ namespace libtorrent
partial_piece_info pi;
pi.piece_state = (partial_piece_info::state_t)i->state;
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);
for (int j = 0; j < pi.blocks_in_piece; ++j)
{

View 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)

View 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)

View File

@ -30,3 +30,5 @@ plugins/BlocklistImport/ui.py
plugins/BlocklistImport/text.py
plugins/BlocklistImport/test.py
plugins/BlocklistImport/peerguardian.py
plugins/TorrentPieces/__init__.py
plugins/TorrentPieces/tab_pieces.py

View File

@ -1377,3 +1377,68 @@ msgstr ""
#: plugins/BlocklistImport/peerguardian.py:37
msgid "Invalid version"
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 ""

View File

@ -317,7 +317,11 @@ class Manager:
def get_pref(self, key):
# Get the value from the preferences object
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
def dump_torrent_file_info(self, torrent):
return deluge_core.dump_file_info(torrent)
@ -437,6 +441,12 @@ class Manager:
def get_torrent_file_info(self, 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
def queue_top(self, unique_ID, enforce_queue=True):
@ -571,8 +581,7 @@ class Manager:
if 'unique_ID' in event and \
event['unique_ID'] not in self.unique_IDs:
continue
# Call plugins events callbacks
if event['event_type'] in self.event_callbacks:
for callback in self.event_callbacks[event['event_type']]:
callback(event)

View File

@ -83,7 +83,9 @@ using namespace libtorrent;
#define EVENT_TRACKER_WARNING 12
#define EVENT_OTHER 13
#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_CHECKING 1
@ -181,6 +183,17 @@ long get_index_from_unique_ID(long 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)
{
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;
}
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
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_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}",
"EVENT_NULL", EVENT_NULL,
"EVENT_FINISHED", EVENT_FINISHED,
"EVENT_PEER_ERROR", EVENT_PEER_ERROR,
"EVENT_INVALID_REQUEST", EVENT_INVALID_REQUEST,
"EVENT_FILE_ERROR", EVENT_FILE_ERROR,
"EVENT_HASH_FAILED_ERROR", EVENT_HASH_FAILED_ERROR,
"EVENT_PEER_BAN_ERROR", EVENT_PEER_BAN_ERROR,
"EVENT_FASTRESUME_REJECTED_ERROR", EVENT_FASTRESUME_REJECTED_ERROR,
"EVENT_TRACKER_ANNOUNCE", EVENT_TRACKER_ANNOUNCE,
"EVENT_TRACKER_REPLY", EVENT_TRACKER_REPLY,
"EVENT_TRACKER_ALERT", EVENT_TRACKER_ALERT,
"EVENT_TRACKER_WARNING", EVENT_TRACKER_WARNING,
"EVENT_OTHER", EVENT_OTHER,
"EVENT_STORAGE_MOVED", EVENT_STORAGE_MOVED,
"STATE_QUEUED", STATE_QUEUED,
"STATE_CHECKING", STATE_CHECKING,
"STATE_CONNECTING", STATE_CONNECTING,
"STATE_DOWNLOADING_META", STATE_DOWNLOADING_META,
"STATE_DOWNLOADING", STATE_DOWNLOADING,
"STATE_FINISHED", STATE_FINISHED,
"STATE_SEEDING", STATE_SEEDING,
"STATE_ALLOCATING", STATE_ALLOCATING);
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_FINISHED", EVENT_FINISHED,
"EVENT_PEER_ERROR", EVENT_PEER_ERROR,
"EVENT_INVALID_REQUEST", EVENT_INVALID_REQUEST,
"EVENT_FILE_ERROR", EVENT_FILE_ERROR,
"EVENT_HASH_FAILED_ERROR", EVENT_HASH_FAILED_ERROR,
"EVENT_PEER_BAN_ERROR", EVENT_PEER_BAN_ERROR,
"EVENT_FASTRESUME_REJECTED_ERROR", EVENT_FASTRESUME_REJECTED_ERROR,
"EVENT_TRACKER_ANNOUNCE", EVENT_TRACKER_ANNOUNCE,
"EVENT_TRACKER_REPLY", EVENT_TRACKER_REPLY,
"EVENT_TRACKER_ALERT", EVENT_TRACKER_ALERT,
"EVENT_TRACKER_WARNING", EVENT_TRACKER_WARNING,
"EVENT_OTHER", EVENT_OTHER,
"EVENT_STORAGE_MOVED", EVENT_STORAGE_MOVED,
"EVENT_PIECE_FINISHED", EVENT_PIECE_FINISHED,
"EVENT_BLOCK_DOWNLOADING", EVENT_BLOCK_DOWNLOADING,
"EVENT_BLOCK_FINISHED", EVENT_BLOCK_FINISHED,
"STATE_QUEUED", STATE_QUEUED,
"STATE_CHECKING", STATE_CHECKING,
"STATE_CONNECTING", STATE_CONNECTING,
"STATE_DOWNLOADING_META", STATE_DOWNLOADING_META,
"STATE_DOWNLOADING", STATE_DOWNLOADING,
"STATE_FINISHED", STATE_FINISHED,
"STATE_SEEDING", STATE_SEEDING,
"STATE_ALLOCATING", STATE_ALLOCATING);
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;
}
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)
{
@ -810,6 +901,60 @@ static PyObject *torrent_pop_event(PyObject *self, PyObject *args)
if (!popped_alert)
{
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))
{
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, "."},
{"set_priv", torrent_set_priv, 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}
};