Rtorrent color patch.

Как в Debian 9 Stretch сделать rtorrent цветным.
Posted in: debian, rtorrent.

Патч, который будет описан ниже позволяет rtorrent’у отображать раздачи разными цветами, в зависимости от их статуса.

Патч старый как г..но мамонта. Почему разработчики rtorrent’а не сделают это фишкой по умолчанию, остаётся загадкой.

Непосредственно сам патч:

rtorrent-0.9.6_color.patch


diff --git a/src/command_network.cc b/src/command_network.cc
index c445c38..24ad5c0 100644
--- a/src/command_network.cc
+++ b/src/command_network.cc
@@ -241,6 +241,26 @@ initialize_command_network() {
   CMD2_ANY         ("strings.connection_type", tr1::bind(&torrent::option_list_strings, torrent::OPTION_CONNECTION_TYPE));
   CMD2_ANY         ("strings.encryption",      tr1::bind(&torrent::option_list_strings, torrent::OPTION_ENCRYPTION));
 
+  CMD2_ANY         ("colors.color_inactive_fg",       tr1::bind(&ui::Root::get_color_inactive_fg,   control->ui()));
+  CMD2_ANY_VALUE_V ("colors.color_inactive_fg.set",   tr1::bind(&ui::Root::set_color_inactive_fg,   control->ui(), tr1::placeholders::_2));
+  CMD2_ANY         ("colors.color_inactive_bg",       tr1::bind(&ui::Root::get_color_inactive_bg,   control->ui()));
+  CMD2_ANY_VALUE_V ("colors.color_inactive_bg.set",   tr1::bind(&ui::Root::set_color_inactive_bg,   control->ui(), tr1::placeholders::_2));
+  
+  CMD2_ANY         ("colors.color_dead_fg",       tr1::bind(&ui::Root::get_color_dead_fg,   control->ui()));
+  CMD2_ANY_VALUE_V ("colors.color_dead_fg.set",   tr1::bind(&ui::Root::set_color_dead_fg,   control->ui(), tr1::placeholders::_2));
+  CMD2_ANY         ("colors.color_dead_bg",       tr1::bind(&ui::Root::get_color_dead_bg,   control->ui()));
+  CMD2_ANY_VALUE_V ("colors.color_dead_bg.set",   tr1::bind(&ui::Root::set_color_dead_bg,   control->ui(), tr1::placeholders::_2));
+
+  CMD2_ANY         ("colors.color_active_fg",       tr1::bind(&ui::Root::get_color_active_fg,   control->ui()));
+  CMD2_ANY_VALUE_V ("colors.color_active_fg.set",   tr1::bind(&ui::Root::set_color_active_fg,   control->ui(), tr1::placeholders::_2));
+  CMD2_ANY         ("colors.color_active_bg",       tr1::bind(&ui::Root::get_color_active_bg,   control->ui()));
+  CMD2_ANY_VALUE_V ("colors.color_active_bg.set",   tr1::bind(&ui::Root::set_color_active_bg,   control->ui(), tr1::placeholders::_2));
+
+  CMD2_ANY         ("colors.color_finished_fg",       tr1::bind(&ui::Root::get_color_finished_fg,   control->ui()));
+  CMD2_ANY_VALUE_V ("colors.color_finished_fg.set",   tr1::bind(&ui::Root::set_color_finished_fg,   control->ui(), tr1::placeholders::_2));
+  CMD2_ANY         ("colors.color_finished_bg",       tr1::bind(&ui::Root::get_color_finished_bg,   control->ui()));
+  CMD2_ANY_VALUE_V ("colors.color_finished_bg.set",   tr1::bind(&ui::Root::set_color_finished_bg,   control->ui(), tr1::placeholders::_2));
+
   // CMD2_ANY_STRING  ("encoding_list",    tr1::bind(&apply_encoding_list, tr1::placeholders::_2));
   CMD2_ANY_STRING  ("encoding.add", tr1::bind(&apply_encoding_list, tr1::placeholders::_2));
 
diff --git a/src/display/canvas.cc b/src/display/canvas.cc
index 31db4ad..255e7c3 100644
--- a/src/display/canvas.cc
+++ b/src/display/canvas.cc
@@ -99,6 +99,12 @@ Canvas::initialize() {
   m_isInitialized = true;
 
   initscr();
+  start_color();
+  use_default_colors();
+  init_pair(4, -1, -1);
+  init_pair(3, -1, -1);
+  init_pair(2, -1, -1);
+  init_pair(1, -1, -1);
   raw();
   noecho();
   nodelay(stdscr, TRUE);
diff --git a/src/display/window_download_list.cc b/src/display/window_download_list.cc
index ead4ddd..ffd79c9 100644
--- a/src/display/window_download_list.cc
+++ b/src/display/window_download_list.cc
@@ -37,6 +37,7 @@
 #include "config.h"
 
 #include <rak/algorithm.h>
+#include <torrent/rate.h>
 
 #include "core/download.h"
 #include "core/view.h"
@@ -104,9 +105,41 @@ WindowDownloadList::redraw() {
     char buffer[m_canvas->width() + 1];
     char* last = buffer + m_canvas->width() - 2 + 1;
 
+    /*
+    There are four states where colors are applied:
+    1 inactive  # If inactive, e.g. user stopped down/upload
+    2 dead      # If active but no down/upload
+    3 active    # If active and download
+    4 finished  # If finished
+    */
+
     print_download_title(buffer, last, *range.first);
-    m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
-    
+    m_canvas->print(0, pos, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
+    if( (*range.first)->is_done() ) {
+      if( (*range.first)->download()->info()->up_rate()->rate() != 0 ) {
+      m_canvas->set_attr(0, pos, m_canvas->width()-1, A_BOLD, 4);       // Finished and uploading
+      } else {
+      m_canvas->set_attr(0, pos, m_canvas->width()-1, A_NORMAL, 4);     // Finished
+      }
+    } else if( (*range.first)->is_active() ) {
+      if( (*range.first)->download()->info()->down_rate()->rate() != 0 ) {
+        if( (*range.first)->download()->info()->up_rate()->rate() != 0 ) {
+          m_canvas->set_attr(0, pos, m_canvas->width()-1, A_BOLD, 3);     // Active and uploading
+        } else {
+          m_canvas->set_attr(0, pos, m_canvas->width()-1, A_NORMAL, 3);   // Active
+        }
+      } else {
+        if( (*range.first)->download()->info()->up_rate()->rate() != 0 ) {
+          m_canvas->set_attr(0, pos, m_canvas->width()-1, A_BOLD, 2);     // Dead but still uploading
+        } else {
+          m_canvas->set_attr(0, pos, m_canvas->width()-1, A_NORMAL, 2);   // Dead
+        }
+      }
+    } else {
+      m_canvas->set_attr(0, pos, m_canvas->width()-1, A_NORMAL, 1);     // Inactive
+    }
+    pos++;
+
     print_download_info(buffer, last, *range.first);
     m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
 
@@ -114,7 +147,83 @@ WindowDownloadList::redraw() {
     m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
 
     ++range.first;
-  }    
+  }
+}
+
+// Inactive
+void
+WindowDownloadList::set_color_inactive_fg(int64_t color) {
+  short fg, bg;
+  pair_content(1, &fg, &bg);
+  if( color < 0 ) color = -1;
+  color = color % 8;
+  init_pair(1, (short)color, bg);
+}
+
+void
+WindowDownloadList::set_color_inactive_bg(int64_t color) {
+  short fg, bg;
+  pair_content(1, &fg, &bg);
+  if( color < 0 ) color = -1;
+  color = color % 8;
+  init_pair(1, fg, (short)color);
+}
+
+// Dead
+void
+WindowDownloadList::set_color_dead_fg(int64_t color) {
+  short fg, bg;
+  pair_content(2, &fg, &bg);
+  if( color < 0 ) color = -1;
+  color = color % 8;
+  init_pair(2, (short)color, bg);
+}
+
+void
+WindowDownloadList::set_color_dead_bg(int64_t color) {
+  short fg, bg;
+  pair_content(2, &fg, &bg);
+  if( color < 0 ) color = -1;
+  color = color % 8;
+  init_pair(2, fg, (short)color);
+}
+
+// Active
+void
+WindowDownloadList::set_color_active_fg(int64_t color) {
+  short fg, bg;
+  pair_content(3, &fg, &bg);
+  if( color < 0 ) color = -1;
+  color = color % 8;
+  init_pair(3, (short)color, bg);
+}
+
+void
+WindowDownloadList::set_color_active_bg(int64_t color) {
+  short fg, bg;
+  pair_content(3, &fg, &bg);
+  if( color < 0 ) color = -1;
+  color = color % 8;
+  init_pair(3, fg, (short)color);
+}
+
+// Finished
+void
+WindowDownloadList::set_color_finished_fg(int64_t color) {
+  short fg, bg;
+  pair_content(4, &fg, &bg);
+  if( color < 0 ) color = -1;
+  color = color % 8;
+  init_pair(4, (short)color, bg);
+}
+
+void
+WindowDownloadList::set_color_finished_bg(int64_t color) {
+  short fg, bg;
+  pair_content(4, &fg, &bg);
+  if( color < 0 ) color = -1;
+  color = color % 8;
+  init_pair(4, fg, (short)color);
 }
 
 }
diff --git a/src/display/window_download_list.h b/src/display/window_download_list.h
index 8e15cac..4551a47 100644
--- a/src/display/window_download_list.h
+++ b/src/display/window_download_list.h
@@ -55,6 +55,15 @@ public:
 
   void                set_view(core::View* l);
 
+  void                set_color_inactive_fg(int64_t color);
+  void                set_color_inactive_bg(int64_t color);
+  void                set_color_dead_fg(int64_t color);
+  void                set_color_dead_bg(int64_t color);
+  void                set_color_active_fg(int64_t color);
+  void                set_color_active_bg(int64_t color);
+  void                set_color_finished_fg(int64_t color);
+  void                set_color_finished_bg(int64_t color);
+
 private:
   core::View*         m_view;
 
diff --git a/src/main.cc b/src/main.cc
index 5e826bb..44faa21 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -388,6 +388,15 @@ main(int argc, char** argv) {
     CMD2_REDIRECT        ("ip",         "network.local_address.set");
     CMD2_REDIRECT        ("port_range", "network.port_range.set");
 
+    CMD2_REDIRECT       ("color_inactive_fg", "colors.color_inactive_fg.set");
+    CMD2_REDIRECT       ("color_inactive_bg", "colors.color_inactive_bg.set");
+    CMD2_REDIRECT       ("color_dead_fg",     "colors.color_dead_fg.set");
+    CMD2_REDIRECT       ("color_dead_bg",     "colors.color_dead_bg.set");
+    CMD2_REDIRECT       ("color_active_fg",   "colors.color_active_fg.set");
+    CMD2_REDIRECT       ("color_active_bg",   "colors.color_active_bg.set");
+    CMD2_REDIRECT       ("color_finished_fg", "colors.color_finished_fg.set");
+    CMD2_REDIRECT       ("color_finished_bg", "colors.color_finished_bg.set");
+
     CMD2_REDIRECT_GENERIC("dht",      "dht.mode.set");
     CMD2_REDIRECT_GENERIC("dht_port", "dht.port.set");
 
diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc
index e3abc9a..7dc7469 100644
--- a/src/ui/download_list.cc
+++ b/src/ui/download_list.cc
@@ -136,6 +136,11 @@ DownloadList::unfocus_download(core::Download* d) {
   current_view()->next_focus();
 }
 
+display::WindowDownloadList*
+DownloadList::current_window_list() {
+  return dynamic_cast<ElementDownloadList*>(m_uiArray[DISPLAY_DOWNLOAD_LIST])->window();
+}
+
 void
 DownloadList::activate_display(Display displayType) {
   if (!is_active())
diff --git a/src/ui/download_list.h b/src/ui/download_list.h
index 3712e36..7810f65 100644
--- a/src/ui/download_list.h
+++ b/src/ui/download_list.h
@@ -98,6 +98,7 @@ public:
   void                activate_display(Display d);
 
   core::View*         current_view();
+  display::WindowDownloadList* current_window_list();
   void                set_current_view(const std::string& name);
 
   void                slot_open_uri(slot_string s) { m_slot_open_uri = s; }
diff --git a/src/ui/element_download_list.h b/src/ui/element_download_list.h
index 20185b5..00ef880 100644
--- a/src/ui/element_download_list.h
+++ b/src/ui/element_download_list.h
@@ -60,6 +60,7 @@ public:
   void                disable();
 
   core::View*         view() { return m_view; }
+  WDownloadList*      window() { return m_window; }
   void                set_view(core::View* l);
 
   void                receive_command(const char* cmd);
diff --git a/src/ui/root.cc b/src/ui/root.cc
index 981fcc2..2df0f5a 100644
--- a/src/ui/root.cc
+++ b/src/ui/root.cc
@@ -44,6 +44,7 @@
 
 #include "core/manager.h"
 #include "display/frame.h"
+#include "display/window_download_list.h"
 #include "display/window_http_queue.h"
 #include "display/window_title.h"
 #include "display/window_input.h"
@@ -65,7 +66,15 @@ Root::Root() :
   m_windowTitle(NULL),
   m_windowHttpQueue(NULL),
   m_windowInput(NULL),
-  m_windowStatusbar(NULL) {
+  m_windowStatusbar(NULL),
+  color_inactive_fg(-1),
+  color_inactive_bg(-1),
+  color_dead_fg(-1),
+  color_dead_bg(-1),
+  color_active_fg(-1),
+  color_active_bg(-1),
+  color_finished_fg(-1),
+  color_finished_bg(-1) {
 }
 
 void
@@ -97,6 +106,14 @@ Root::init(Control* c) {
   setup_keys();
 
   m_downloadList->activate(rootFrame->frame(1));
+  m_downloadList->current_window_list()->set_color_inactive_fg(color_inactive_fg);
+  m_downloadList->current_window_list()->set_color_inactive_bg(color_inactive_bg);
+  m_downloadList->current_window_list()->set_color_dead_fg(color_dead_fg);
+  m_downloadList->current_window_list()->set_color_dead_bg(color_dead_bg);
+  m_downloadList->current_window_list()->set_color_active_fg(color_active_fg);
+  m_downloadList->current_window_list()->set_color_active_bg(color_active_bg);
+  m_downloadList->current_window_list()->set_color_finished_fg(color_finished_fg);
+  m_downloadList->current_window_list()->set_color_finished_bg(color_finished_bg);
 }
 
 void
@@ -272,4 +289,88 @@ Root::current_input() {
   return m_windowInput->input();
 }
 
+// Inactive
+int
+Root::get_color_inactive_fg() {
+  return color_inactive_fg;
+}
+
+void
+Root::set_color_inactive_fg(int64_t color) {
+  color_inactive_fg = color;
+}
+
+int
+Root::get_color_inactive_bg() {
+  return color_inactive_bg;
+}
+
+void
+Root::set_color_inactive_bg(int64_t color) {
+  color_inactive_bg = color;
+}
+
+// Dead
+int
+Root::get_color_dead_fg() {
+  return color_dead_fg;
+}
+
+void
+Root::set_color_dead_fg(int64_t color) {
+  color_dead_fg = color;
+}
+
+int
+Root::get_color_dead_bg() {
+  return color_dead_bg;
+}
+
+void
+Root::set_color_dead_bg(int64_t color) {
+  color_dead_bg = color;
+}
+
+// Active
+int
+Root::get_color_active_fg() {
+  return color_active_fg;
+}
+
+void
+Root::set_color_active_fg(int64_t color) {
+  color_active_fg = color;
+}
+
+int
+Root::get_color_active_bg() {
+  return color_active_bg;
+}
+
+void
+Root::set_color_active_bg(int64_t color) {
+  color_active_bg = color;
+}
+
+// Finished
+int
+Root::get_color_finished_fg() {
+  return color_finished_fg;
+}
+
+void
+Root::set_color_finished_fg(int64_t color) {
+  color_finished_fg = color;
+}
+
+int
+Root::get_color_finished_bg() {
+  return color_finished_bg;
+}
+
+void
+Root::set_color_finished_bg(int64_t color) {
+  color_finished_bg = color;
+}
+
 }
diff --git a/src/ui/root.h b/src/ui/root.h
index cbc5ff4..a550aeb 100644
--- a/src/ui/root.h
+++ b/src/ui/root.h
@@ -83,6 +83,23 @@ public:
   void                set_down_throttle_i64(int64_t throttle) { set_down_throttle(throttle >> 10); }
   void                set_up_throttle_i64(int64_t throttle)   { set_up_throttle(throttle >> 10); }
 
+  int                 get_color_inactive_fg();
+  void                set_color_inactive_fg(int64_t color);
+  int                 get_color_inactive_bg();
+  void                set_color_inactive_bg(int64_t color);
+  int                 get_color_dead_fg();
+  void                set_color_dead_fg(int64_t color);
+  int                 get_color_dead_bg();
+  void                set_color_dead_bg(int64_t color);
+  int                 get_color_active_fg();
+  void                set_color_active_fg(int64_t color);
+  int                 get_color_active_bg();
+  void                set_color_active_bg(int64_t color);
+  int                 get_color_finished_fg();
+  void                set_color_finished_fg(int64_t color);
+  int                 get_color_finished_bg();
+  void                set_color_finished_bg(int64_t color);
+
   void                adjust_down_throttle(int throttle);
   void                adjust_up_throttle(int throttle);
 
@@ -105,6 +122,15 @@ private:
   WStatusbar*         m_windowStatusbar;
 
   input::Bindings     m_bindings;
+
+  int64_t             color_inactive_fg;
+  int64_t             color_inactive_bg;
+  int64_t             color_dead_fg;
+  int64_t             color_dead_bg;
+  int64_t             color_active_fg;
+  int64_t             color_active_bg;
+  int64_t             color_finished_fg;
+  int64_t             color_finished_bg;
 };
 
 }

Скачиваем и распаковываем исходники с официального сайта rtorrent. Нам нужна версия 0.9.6, так как в репозитории Debian 9 именно такая версия:

$ wget -qO - http://rtorrent.net/downloads/rtorrent-0.9.6.tar.gz | tar zxvf -

Патч rtorrent-0.9.6_color.patch необходимо положить в папку с нашими исходниками rtorrent-0.9.6:

$ mv rtorrent-0.9.6_color.patch /home/user_name/rtorrent-0.9.6/

Теперь переходим в папку с исходниками, накладываем наш патч и собираем rtorrent:


$ cd rtorrent-0.9.6
$ patch -uNp1 -i rtorrent-0.9.6_color.patch
$ sed '/AM_PATH_CPPUNIT/d' -i configure.ac
$ ./autogen.sh
$ ./configure --prefix=/usr/local --with-xmlrpc-c

Если сборка заканчивается неудачей - это свидетельствует об отсутствии в вашей системе необходимых библиотек. Их нужно будет доустановить, после чего запустить сборку повторно.

Теперь остаётся задать необходимые цвета в конфигурационном файле rtorrent’a .rtorrent.rc:


# Colors
# Colors: 0 = black  1 = red  
#         2 = green  3 = yellow 
#         4 = blue   5 = magenta 
#         6 = cyan   7 = white

color_active_fg   = 3
color_inactive_fg = 2
color_dead_fg     = 1
color_finished_fg = 6
color_active_bg   = 4
color_inactive_bg = 0
color_dead_bg     = 0
color_finished_bg = 0

Запускаем rtorrent и смотрим результат:

Комментарий на GitHub
ce0f13b2-4a83-4c1c-b2b9-b6d18f4ee6d2