|
|
@ -69,7 +69,26 @@ static QString boostTimeToQString(const boost::posix_time::ptime &boostDate) { |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
QTorrentHandle::QTorrentHandle(torrent_handle h): torrent_handle(h) {} |
|
|
|
static QPair<int, int> get_file_extremity_pieces(const torrent_info& t, int file_index) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const int num_pieces = t.num_pieces(); |
|
|
|
|
|
|
|
const int piece_size = t.piece_length(); |
|
|
|
|
|
|
|
const file_entry& file = t.file_at(file_index); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Determine the first and last piece of the file
|
|
|
|
|
|
|
|
int first_piece = floor((file.offset + 1) / (float) piece_size); |
|
|
|
|
|
|
|
Q_ASSERT(first_piece >= 0 && first_piece < num_pieces); |
|
|
|
|
|
|
|
qDebug("First piece of the file is %d/%d", first_piece, num_pieces - 1); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int num_pieces_in_file = ceil(file.size / (float) piece_size); |
|
|
|
|
|
|
|
int last_piece = first_piece + num_pieces_in_file - 1; |
|
|
|
|
|
|
|
Q_ASSERT(last_piece >= 0 && last_piece < num_pieces); |
|
|
|
|
|
|
|
qDebug("last piece of the file is %d/%d", last_piece, num_pieces - 1); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return qMakePair(first_piece, last_piece); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QTorrentHandle::QTorrentHandle(const torrent_handle& h): torrent_handle(h) {} |
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Getters
|
|
|
|
// Getters
|
|
|
@ -118,7 +137,7 @@ qlonglong QTorrentHandle::next_announce_s() const { |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
qreal QTorrentHandle::progress() const { |
|
|
|
float QTorrentHandle::progress() const { |
|
|
|
#if LIBTORRENT_VERSION_MINOR > 15 |
|
|
|
#if LIBTORRENT_VERSION_MINOR > 15 |
|
|
|
torrent_status st = torrent_handle::status(query_accurate_download_counters); |
|
|
|
torrent_status st = torrent_handle::status(query_accurate_download_counters); |
|
|
|
#else |
|
|
|
#else |
|
|
@ -128,7 +147,7 @@ qreal QTorrentHandle::progress() const { |
|
|
|
return 0.; |
|
|
|
return 0.; |
|
|
|
if (st.total_wanted_done == st.total_wanted) |
|
|
|
if (st.total_wanted_done == st.total_wanted) |
|
|
|
return 1.; |
|
|
|
return 1.; |
|
|
|
qreal progress = (float)st.total_wanted_done/(float)st.total_wanted; |
|
|
|
float progress = (float) st.total_wanted_done / (float) st.total_wanted; |
|
|
|
Q_ASSERT(progress >= 0. && progress <= 1.); |
|
|
|
Q_ASSERT(progress >= 0. && progress <= 1.); |
|
|
|
return progress; |
|
|
|
return progress; |
|
|
|
} |
|
|
|
} |
|
|
@ -180,32 +199,29 @@ int QTorrentHandle::num_pieces() const { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool QTorrentHandle::first_last_piece_first() const { |
|
|
|
bool QTorrentHandle::first_last_piece_first() const { |
|
|
|
// Detect first media file
|
|
|
|
const torrent_info& t = get_torrent_info(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Get int first media file
|
|
|
|
int index = 0; |
|
|
|
int index = 0; |
|
|
|
for (index = 0; index < num_files(); ++index) { |
|
|
|
for (index = 0; index < t.num_files(); ++index) { |
|
|
|
#if LIBTORRENT_VERSION_MINOR > 15 |
|
|
|
#if LIBTORRENT_VERSION_MINOR > 15 |
|
|
|
QString path = misc::toQStringU(get_torrent_info().file_at(index).path); |
|
|
|
QString path = misc::toQStringU(t.file_at(index).path); |
|
|
|
#else |
|
|
|
#else |
|
|
|
QString path = misc::toQStringU(get_torrent_info().file_at(index).path.string()); |
|
|
|
QString path = misc::toQStringU(t.file_at(index).path.string()); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
const QString ext = misc::file_extension(path); |
|
|
|
const QString ext = misc::file_extension(path); |
|
|
|
if (misc::isPreviewable(ext) && torrent_handle::file_priority(index) > 0) { |
|
|
|
if (misc::isPreviewable(ext) && torrent_handle::file_priority(index) > 0) |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
++index; |
|
|
|
|
|
|
|
} |
|
|
|
if (index >= t.num_files()) // No media file
|
|
|
|
if (index >= torrent_handle::get_torrent_info().num_files()) return false; |
|
|
|
return false; |
|
|
|
file_entry media_file = torrent_handle::get_torrent_info().file_at(index); |
|
|
|
|
|
|
|
int piece_size = torrent_handle::get_torrent_info().piece_length(); |
|
|
|
|
|
|
|
Q_ASSERT(piece_size>0); |
|
|
|
QPair<int, int> extremities = get_file_extremity_pieces (t, index); |
|
|
|
int first_piece = floor((media_file.offset+1)/(double)piece_size); |
|
|
|
|
|
|
|
Q_ASSERT(first_piece >= 0 && first_piece < torrent_handle::get_torrent_info().num_pieces()); |
|
|
|
return (torrent_handle::piece_priority(extremities.first) == 7) |
|
|
|
qDebug("First piece of the file is %d/%d", first_piece, torrent_handle::get_torrent_info().num_pieces()-1); |
|
|
|
&& (torrent_handle::piece_priority(extremities.second) == 7); |
|
|
|
int num_pieces_in_file = ceil(media_file.size/(double)piece_size); |
|
|
|
|
|
|
|
int last_piece = first_piece+num_pieces_in_file-1; |
|
|
|
|
|
|
|
Q_ASSERT(last_piece >= 0 && last_piece < torrent_handle::get_torrent_info().num_pieces()); |
|
|
|
|
|
|
|
qDebug("last piece of the file is %d/%d", last_piece, torrent_handle::get_torrent_info().num_pieces()-1); |
|
|
|
|
|
|
|
return (torrent_handle::piece_priority(first_piece) == 7) && (torrent_handle::piece_priority(last_piece) == 7); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
size_type QTorrentHandle::total_wanted_done() const { |
|
|
|
size_type QTorrentHandle::total_wanted_done() const { |
|
|
@ -305,9 +321,10 @@ size_type QTorrentHandle::actual_size() const { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool QTorrentHandle::has_filtered_pieces() const { |
|
|
|
bool QTorrentHandle::has_filtered_pieces() const { |
|
|
|
std::vector<int> piece_priorities = torrent_handle::piece_priorities(); |
|
|
|
const std::vector<int> piece_priorities = torrent_handle::piece_priorities(); |
|
|
|
for (unsigned int i = 0; i<piece_priorities.size(); ++i) { |
|
|
|
foreach (const int priority, piece_priorities) { |
|
|
|
if (!piece_priorities[i]) return true; |
|
|
|
if (priority == 0) |
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
@ -480,7 +497,8 @@ bool QTorrentHandle::is_seed() const { |
|
|
|
// May suffer from approximation problems
|
|
|
|
// May suffer from approximation problems
|
|
|
|
//return (progress() == 1.);
|
|
|
|
//return (progress() == 1.);
|
|
|
|
// This looks safe
|
|
|
|
// This looks safe
|
|
|
|
return (state() == torrent_status::finished || state() == torrent_status::seeding); |
|
|
|
torrent_status::state_t st = state(); |
|
|
|
|
|
|
|
return (st == torrent_status::finished || st == torrent_status::seeding); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool QTorrentHandle::is_auto_managed() const { |
|
|
|
bool QTorrentHandle::is_auto_managed() const { |
|
|
@ -572,7 +590,7 @@ QString QTorrentHandle::error() const { |
|
|
|
void QTorrentHandle::downloading_pieces(bitfield &bf) const { |
|
|
|
void QTorrentHandle::downloading_pieces(bitfield &bf) const { |
|
|
|
std::vector<partial_piece_info> queue; |
|
|
|
std::vector<partial_piece_info> queue; |
|
|
|
torrent_handle::get_download_queue(queue); |
|
|
|
torrent_handle::get_download_queue(queue); |
|
|
|
for (std::vector<partial_piece_info>::iterator it=queue.begin(); it!= queue.end(); it++) { |
|
|
|
for (std::vector<partial_piece_info>::const_iterator it=queue.begin(); it!= queue.end(); it++) { |
|
|
|
bf.set_bit(it->piece_index); |
|
|
|
bf.set_bit(it->piece_index); |
|
|
|
} |
|
|
|
} |
|
|
|
return; |
|
|
|
return; |
|
|
@ -609,7 +627,9 @@ void QTorrentHandle::pause() const { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void QTorrentHandle::resume() const { |
|
|
|
void QTorrentHandle::resume() const { |
|
|
|
if (has_error()) torrent_handle::clear_error(); |
|
|
|
if (has_error()) |
|
|
|
|
|
|
|
torrent_handle::clear_error(); |
|
|
|
|
|
|
|
|
|
|
|
const QString torrent_hash = hash(); |
|
|
|
const QString torrent_hash = hash(); |
|
|
|
bool has_persistant_error = TorrentPersistentData::hasError(torrent_hash); |
|
|
|
bool has_persistant_error = TorrentPersistentData::hasError(torrent_hash); |
|
|
|
TorrentPersistentData::setErrorState(torrent_hash, false); |
|
|
|
TorrentPersistentData::setErrorState(torrent_hash, false); |
|
|
@ -630,22 +650,24 @@ void QTorrentHandle::resume() const { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void QTorrentHandle::remove_url_seed(QString seed) const { |
|
|
|
void QTorrentHandle::remove_url_seed(const QString& seed) const { |
|
|
|
torrent_handle::remove_url_seed(seed.toStdString()); |
|
|
|
torrent_handle::remove_url_seed(seed.toStdString()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void QTorrentHandle::add_url_seed(QString seed) const { |
|
|
|
void QTorrentHandle::add_url_seed(const QString& seed) const { |
|
|
|
const std::string str_seed = seed.toStdString(); |
|
|
|
const std::string str_seed = seed.toStdString(); |
|
|
|
qDebug("calling torrent_handle::add_url_seed(%s)", str_seed.c_str()); |
|
|
|
qDebug("calling torrent_handle::add_url_seed(%s)", str_seed.c_str()); |
|
|
|
torrent_handle::add_url_seed(str_seed); |
|
|
|
torrent_handle::add_url_seed(str_seed); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void QTorrentHandle::set_tracker_login(QString username, QString password) const { |
|
|
|
void QTorrentHandle::set_tracker_login(const QString& username, const QString& password) const { |
|
|
|
torrent_handle::set_tracker_login(std::string(username.toLocal8Bit().constData()), std::string(password.toLocal8Bit().constData())); |
|
|
|
torrent_handle::set_tracker_login(std::string(username.toLocal8Bit().constData()), std::string(password.toLocal8Bit().constData())); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void QTorrentHandle::move_storage(QString new_path) const { |
|
|
|
void QTorrentHandle::move_storage(const QString& new_path) const { |
|
|
|
if (QDir(save_path()) == QDir(new_path)) return; |
|
|
|
if (QDir(save_path()) == QDir(new_path)) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
TorrentPersistentData::setPreviousSavePath(hash(), save_path()); |
|
|
|
TorrentPersistentData::setPreviousSavePath(hash(), save_path()); |
|
|
|
// Create destination directory if necessary
|
|
|
|
// Create destination directory if necessary
|
|
|
|
// or move_storage() will fail...
|
|
|
|
// or move_storage() will fail...
|
|
|
@ -654,10 +676,13 @@ void QTorrentHandle::move_storage(QString new_path) const { |
|
|
|
torrent_handle::move_storage(new_path.toUtf8().constData()); |
|
|
|
torrent_handle::move_storage(new_path.toUtf8().constData()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool QTorrentHandle::save_torrent_file(QString path) const { |
|
|
|
bool QTorrentHandle::save_torrent_file(const QString& path) const { |
|
|
|
if (!has_metadata()) return false; |
|
|
|
if (!has_metadata()) return false; |
|
|
|
|
|
|
|
|
|
|
|
entry meta = bdecode(torrent_handle::get_torrent_info().metadata().get(), torrent_handle::get_torrent_info().metadata().get()+torrent_handle::get_torrent_info().metadata_size()); |
|
|
|
const torrent_info& t = torrent_handle::get_torrent_info(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
entry meta = bdecode(t.metadata().get(), |
|
|
|
|
|
|
|
t.metadata().get() + t.metadata_size()); |
|
|
|
entry torrent_entry(entry::dictionary_t); |
|
|
|
entry torrent_entry(entry::dictionary_t); |
|
|
|
torrent_entry["info"] = meta; |
|
|
|
torrent_entry["info"] = meta; |
|
|
|
if (!torrent_handle::trackers().empty()) |
|
|
|
if (!torrent_handle::trackers().empty()) |
|
|
@ -692,7 +717,7 @@ void QTorrentHandle::prioritize_files(const vector<int> &files) const { |
|
|
|
qDebug() << Q_FUNC_INFO << "Changing files priorities..."; |
|
|
|
qDebug() << Q_FUNC_INFO << "Changing files priorities..."; |
|
|
|
torrent_handle::prioritize_files(files); |
|
|
|
torrent_handle::prioritize_files(files); |
|
|
|
qDebug() << Q_FUNC_INFO << "Moving unwanted files to .unwanted folder..."; |
|
|
|
qDebug() << Q_FUNC_INFO << "Moving unwanted files to .unwanted folder..."; |
|
|
|
for (uint i=0; i<files.size(); ++i) { |
|
|
|
for (uint i = 0; i < files.size(); ++i) { |
|
|
|
// Move unwanted files to a .unwanted subfolder
|
|
|
|
// Move unwanted files to a .unwanted subfolder
|
|
|
|
if (files[i] == 0 && progress[i] < filesize_at(i)) { |
|
|
|
if (files[i] == 0 && progress[i] < filesize_at(i)) { |
|
|
|
QString old_path = filepath_at(i); |
|
|
|
QString old_path = filepath_at(i); |
|
|
@ -761,34 +786,20 @@ void QTorrentHandle::prioritize_files(const vector<int> &files) const { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void QTorrentHandle::add_tracker(const announce_entry& url) const { |
|
|
|
|
|
|
|
torrent_handle::add_tracker(url); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void QTorrentHandle::prioritize_first_last_piece(int file_index, bool b) const { |
|
|
|
void QTorrentHandle::prioritize_first_last_piece(int file_index, bool b) const { |
|
|
|
// Determine the priority to set
|
|
|
|
// Determine the priority to set
|
|
|
|
int prio = 7; // MAX
|
|
|
|
int prio = b ? 7 : torrent_handle::file_priority(file_index); |
|
|
|
if (!b) prio = torrent_handle::file_priority(file_index); |
|
|
|
|
|
|
|
file_entry file = get_torrent_info().file_at(file_index); |
|
|
|
QPair<int, int> extremities = get_file_extremity_pieces (get_torrent_info(), file_index); |
|
|
|
// Determine the first and last piece of the file
|
|
|
|
piece_priority(extremities.first, prio); |
|
|
|
int piece_size = torrent_handle::get_torrent_info().piece_length(); |
|
|
|
piece_priority(extremities.second, prio); |
|
|
|
Q_ASSERT(piece_size>0); |
|
|
|
|
|
|
|
int first_piece = floor((file.offset+1)/(double)piece_size); |
|
|
|
|
|
|
|
Q_ASSERT(first_piece >= 0 && first_piece < torrent_handle::get_torrent_info().num_pieces()); |
|
|
|
|
|
|
|
qDebug("First piece of the file is %d/%d", first_piece, torrent_handle::get_torrent_info().num_pieces()-1); |
|
|
|
|
|
|
|
int num_pieces_in_file = ceil(file.size/(double)piece_size); |
|
|
|
|
|
|
|
int last_piece = first_piece+num_pieces_in_file-1; |
|
|
|
|
|
|
|
Q_ASSERT(last_piece >= 0 && last_piece < torrent_handle::get_torrent_info().num_pieces()); |
|
|
|
|
|
|
|
qDebug("last piece of the file is %d/%d", last_piece, torrent_handle::get_torrent_info().num_pieces()-1); |
|
|
|
|
|
|
|
torrent_handle::piece_priority(first_piece, prio); |
|
|
|
|
|
|
|
torrent_handle::piece_priority(last_piece, prio); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void QTorrentHandle::prioritize_first_last_piece(bool b) const { |
|
|
|
void QTorrentHandle::prioritize_first_last_piece(bool b) const { |
|
|
|
if (!has_metadata()) return; |
|
|
|
if (!has_metadata()) return; |
|
|
|
// Download first and last pieces first for all media files in the torrent
|
|
|
|
// Download first and last pieces first for all media files in the torrent
|
|
|
|
int index = 0; |
|
|
|
const uint nbfiles = num_files(); |
|
|
|
for (index = 0; index < num_files(); ++index) { |
|
|
|
for (uint index = 0; index < nbfiles; ++index) { |
|
|
|
const QString path = filepath_at(index); |
|
|
|
const QString path = filepath_at(index); |
|
|
|
const QString ext = misc::file_extension(path); |
|
|
|
const QString ext = misc::file_extension(path); |
|
|
|
if (misc::isPreviewable(ext) && torrent_handle::file_priority(index) > 0) { |
|
|
|
if (misc::isPreviewable(ext) && torrent_handle::file_priority(index) > 0) { |
|
|
@ -798,7 +809,7 @@ void QTorrentHandle::prioritize_first_last_piece(bool b) const { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void QTorrentHandle::rename_file(int index, QString name) const { |
|
|
|
void QTorrentHandle::rename_file(int index, const QString& name) const { |
|
|
|
qDebug() << Q_FUNC_INFO << index << name; |
|
|
|
qDebug() << Q_FUNC_INFO << index << name; |
|
|
|
torrent_handle::rename_file(index, std::string(name.toUtf8().constData())); |
|
|
|
torrent_handle::rename_file(index, std::string(name.toUtf8().constData())); |
|
|
|
} |
|
|
|
} |
|
|
@ -808,6 +819,5 @@ void QTorrentHandle::rename_file(int index, QString name) const { |
|
|
|
//
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
bool QTorrentHandle::operator ==(const QTorrentHandle& new_h) const { |
|
|
|
bool QTorrentHandle::operator ==(const QTorrentHandle& new_h) const { |
|
|
|
const QString hash = misc::toQString(torrent_handle::info_hash()); |
|
|
|
return info_hash() == new_h.info_hash(); |
|
|
|
return (hash == new_h.hash()); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|