1 | /* |
---|
2 | * Xmission - a cross-platform bittorrent client |
---|
3 | * Copyright (C) 2007 Charles Kerr <charles@transmissionbt.com> |
---|
4 | * |
---|
5 | * This program is free software; you can redistribute it and/or modify |
---|
6 | * it under the terms of the GNU General Public License as published by |
---|
7 | * the Free Software Foundation; version 2 of the License. |
---|
8 | * |
---|
9 | * This program is distributed in the hope that it will be useful, |
---|
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
12 | * GNU General Public License for more details. |
---|
13 | * |
---|
14 | * You should have received a copy of the GNU General Public License |
---|
15 | * along with this program; if not, write to the Free Software |
---|
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
17 | * |
---|
18 | * $Id: speed-stats.cc 7468 2008-12-22 19:14:43Z charles $ |
---|
19 | */ |
---|
20 | |
---|
21 | #include <wx/dcclient.h> |
---|
22 | #include <wx/dcmemory.h> |
---|
23 | #include <wx/event.h> |
---|
24 | #include <wx/gbsizer.h> |
---|
25 | #include <wx/stattext.h> |
---|
26 | #include <wx/intl.h> |
---|
27 | #include <libtransmission/transmission.h> |
---|
28 | #include "foreach.h" |
---|
29 | #include "speed-stats.h" |
---|
30 | |
---|
31 | #define SNAPSHOT_PIXEL_WIDTH 2 |
---|
32 | |
---|
33 | BEGIN_EVENT_TABLE( SpeedStats, wxPanel ) |
---|
34 | EVT_SIZE( SpeedStats::OnSize ) |
---|
35 | EVT_PAINT( SpeedStats::OnPaint ) |
---|
36 | END_EVENT_TABLE() |
---|
37 | |
---|
38 | SpeedStats :: SpeedStats( wxWindow * parent, |
---|
39 | wxWindowID id, |
---|
40 | const wxPoint & pos, |
---|
41 | const wxSize & size, |
---|
42 | long style, |
---|
43 | const wxString & name ): |
---|
44 | wxPanel( parent, id, pos, size, style|wxFULL_REPAINT_ON_RESIZE, name ), |
---|
45 | myBitmap( 0 ), |
---|
46 | myTorrent( 0 ), |
---|
47 | myMaxSpeed( -1 ), |
---|
48 | myHistory( 0 ) |
---|
49 | { |
---|
50 | myColors[BACKGROUND] = wxColour( 0, 0, 0 ); // black |
---|
51 | myColors[FRAME] = wxColour( 34, 139, 34 ); // forest green |
---|
52 | myColors[ALL_UP] = wxColour( 255, 0, 0 ); |
---|
53 | myColors[TORRENT_UP] = wxColour( 255, 255, 0 ); |
---|
54 | |
---|
55 | myColors[ALL_DOWN] = wxColour( 255, 0, 255 ); |
---|
56 | myColors[TORRENT_DOWN] = wxColour( 0, 255, 128 ); |
---|
57 | } |
---|
58 | |
---|
59 | SpeedStats :: ~SpeedStats() |
---|
60 | { |
---|
61 | delete myBitmap; |
---|
62 | } |
---|
63 | |
---|
64 | /** |
---|
65 | *** |
---|
66 | **/ |
---|
67 | |
---|
68 | void |
---|
69 | SpeedStats :: SetColor( int i, const wxColour& c ) |
---|
70 | { |
---|
71 | assert( 0<=i && i<N_COLORS ); |
---|
72 | |
---|
73 | myColors[i] = c; |
---|
74 | } |
---|
75 | |
---|
76 | wxString |
---|
77 | SpeedStats :: GetColorName( int i ) |
---|
78 | { |
---|
79 | static const wxString xstr[N_COLORS] = { |
---|
80 | _T("background"), _T("frame"), |
---|
81 | _T("torrent-up"), _T("torrent-down"), |
---|
82 | _T("all-up"), _T("all-down") |
---|
83 | }; |
---|
84 | |
---|
85 | wxString ret = _T("speed-color-"); |
---|
86 | ret += xstr[i]; |
---|
87 | return ret; |
---|
88 | } |
---|
89 | |
---|
90 | /** |
---|
91 | *** |
---|
92 | **/ |
---|
93 | |
---|
94 | void |
---|
95 | SpeedStats :: OnSize( wxSizeEvent& event ) |
---|
96 | { |
---|
97 | delete myBitmap; |
---|
98 | |
---|
99 | const wxSize size = event.GetSize(); |
---|
100 | myBitmap = new wxBitmap( size.GetWidth(), size.GetHeight() ); |
---|
101 | myHistory = size.GetWidth() / SNAPSHOT_PIXEL_WIDTH; |
---|
102 | } |
---|
103 | |
---|
104 | void |
---|
105 | SpeedStats :: OnPaint( wxPaintEvent& WXUNUSED(event) ) |
---|
106 | { |
---|
107 | const int draw_width = myBitmap->GetWidth(); |
---|
108 | const int draw_height = myBitmap->GetHeight(); |
---|
109 | |
---|
110 | const int top = (((int)myMaxSpeed + 11) / 10) * 10; |
---|
111 | const double y_scale = (double)draw_height / top; |
---|
112 | const int num_bars = 4; |
---|
113 | const int per_bar = top / num_bars; |
---|
114 | |
---|
115 | // clear |
---|
116 | wxMemoryDC memDC; |
---|
117 | memDC.SelectObject( *myBitmap ); |
---|
118 | memDC.SetBackground( myColors[BACKGROUND] ); |
---|
119 | memDC.Clear( ); |
---|
120 | |
---|
121 | // draw the frame |
---|
122 | |
---|
123 | memDC.SetPen( wxPen ( myColors[FRAME] ) ); |
---|
124 | memDC.SetTextForeground( myColors[FRAME] ); |
---|
125 | |
---|
126 | const int fontsize = 10; |
---|
127 | const int dely = int( draw_height / num_bars ); |
---|
128 | |
---|
129 | wxString xstr; |
---|
130 | |
---|
131 | memDC.SetFont( wxFont ( fontsize, wxFONTFAMILY_SWISS, |
---|
132 | wxFONTSTYLE_NORMAL, |
---|
133 | wxFONTWEIGHT_NORMAL ) ); |
---|
134 | |
---|
135 | for( int i=0; i<=num_bars; ++i ) |
---|
136 | { |
---|
137 | const int y = (int)(draw_height - (i*dely+0.5)); |
---|
138 | |
---|
139 | // line |
---|
140 | memDC.DrawLine( wxCoord(0), wxCoord(draw_height - (i*dely+0.5)), |
---|
141 | wxCoord(draw_width), wxCoord(draw_height - (i*dely+0.5)) ); |
---|
142 | |
---|
143 | xstr.Printf( _("%d KiB/s"), (per_bar*i) ); |
---|
144 | memDC.DrawText( xstr, wxCoord(0), wxCoord(y+2) ); |
---|
145 | } |
---|
146 | |
---|
147 | const int n = myStats.size( ); |
---|
148 | if( n ) |
---|
149 | { |
---|
150 | wxPoint * points = new wxPoint[ n ]; |
---|
151 | |
---|
152 | int x = draw_width - (n * SNAPSHOT_PIXEL_WIDTH); |
---|
153 | for( int i=0; i<n; ++i ) { |
---|
154 | points[i].x = x; |
---|
155 | x += SNAPSHOT_PIXEL_WIDTH; |
---|
156 | } |
---|
157 | |
---|
158 | // torrent upload |
---|
159 | for( int i=0; i<n; ++i ) |
---|
160 | points[i].y = draw_height - 10 - int(myStats[i].torrentUp * y_scale); |
---|
161 | wxPen pen( myColors[TORRENT_UP] ); |
---|
162 | memDC.SetPen( pen ); |
---|
163 | memDC.DrawLines( n, points, 0, 0 ); |
---|
164 | |
---|
165 | // torrent download |
---|
166 | for( int i=0; i<n; ++i ) |
---|
167 | points[i].y = draw_height - int(myStats[i].torrentDown * y_scale); |
---|
168 | pen.SetColour( myColors[TORRENT_DOWN] ); |
---|
169 | memDC.SetPen( pen ); |
---|
170 | memDC.DrawLines( n, points, 0, 0 ); |
---|
171 | |
---|
172 | // all upload |
---|
173 | for( int i=0; i<n; ++i ) |
---|
174 | points[i].y = draw_height - int(myStats[i].allUp * y_scale); |
---|
175 | pen.SetColour( myColors[ALL_UP] ); |
---|
176 | memDC.SetPen( pen ); |
---|
177 | memDC.DrawLines( n, points, 0, 0 ); |
---|
178 | |
---|
179 | // all download |
---|
180 | for( int i=0; i<n; ++i ) |
---|
181 | points[i].y = draw_height - int(myStats[i].allDown * y_scale); |
---|
182 | pen.SetColour( myColors[ALL_DOWN] ); |
---|
183 | memDC.SetPen( pen ); |
---|
184 | memDC.DrawLines( n, points, 0, 0 ); |
---|
185 | |
---|
186 | delete [] points; |
---|
187 | } |
---|
188 | |
---|
189 | wxPaintDC dc( this ); |
---|
190 | dc.Blit( 0, 0, draw_width, draw_height, &memDC, 0, 0 ); |
---|
191 | memDC.SelectObject( wxNullBitmap ); |
---|
192 | } |
---|
193 | |
---|
194 | void |
---|
195 | SpeedStats :: SetTorrent( tr_torrent * tor ) |
---|
196 | { |
---|
197 | if( tor != myTorrent ) |
---|
198 | { |
---|
199 | myTorrent = tor; |
---|
200 | |
---|
201 | myMaxSpeed = 0; |
---|
202 | foreach( stats_t, myStats, it ) |
---|
203 | { |
---|
204 | it->torrentUp = 0; |
---|
205 | it->torrentDown = 0; |
---|
206 | myMaxSpeed = std::max( myMaxSpeed, it->allUp ); |
---|
207 | myMaxSpeed = std::max( myMaxSpeed, it->allDown ); |
---|
208 | } |
---|
209 | } |
---|
210 | } |
---|
211 | |
---|
212 | void |
---|
213 | SpeedStats :: Pulse( tr_session * handle ) |
---|
214 | { |
---|
215 | // add a new record |
---|
216 | const double allUp = tr_sessionGetPieceSpeed( handle, TR_UP ); |
---|
217 | const double allDown = tr_sessionGetPieceSpeed( handle, TR_DOWN ); |
---|
218 | Speed s; |
---|
219 | s.time = time( NULL ); |
---|
220 | s.allUp = allUp; |
---|
221 | s.allDown = allDown; |
---|
222 | if( myTorrent ) { |
---|
223 | const tr_stat * stat = tr_torrentStat( myTorrent ); |
---|
224 | s.torrentUp = stat->pieceUploadSpeed; |
---|
225 | s.torrentDown = stat->pieceDownloadSpeed; |
---|
226 | } |
---|
227 | myStats.push_back( s ); |
---|
228 | |
---|
229 | // age off old data |
---|
230 | const int eraseCount = myStats.size() - myHistory; |
---|
231 | if( eraseCount > 0 ) |
---|
232 | myStats.erase( myStats.begin(), |
---|
233 | myStats.begin() + eraseCount ); |
---|
234 | |
---|
235 | // update max |
---|
236 | myMaxSpeed = std::max( myMaxSpeed, s.allUp ); |
---|
237 | myMaxSpeed = std::max( myMaxSpeed, s.allDown ); |
---|
238 | myMaxSpeed = std::max( myMaxSpeed, s.torrentUp ); |
---|
239 | myMaxSpeed = std::max( myMaxSpeed, s.torrentDown ); |
---|
240 | |
---|
241 | Refresh( false ); |
---|
242 | } |
---|