Browse Source

Issue 373

Add Speed and Time Remaining
Cancel Button disables itself when transfer completes.

Send/Wait for the correct acks (Acks are total bytes recieved so far, not bytes recieved this time)
Fix fast-dcc support (Treated as turbo, but with acks at the end.)

git-svn-id: http://svn.dmdirc.com/trunk@4045 00569f92-eb28-0410-84fd-f71c24880f
tags/0.6
Shane Mc Cormack 16 years ago
parent
commit
d6d1a19063

+ 26
- 6
src/com/dmdirc/addons/dcc/DCCSend.java View File

271
 			transferFile = new File(filename);
271
 			transferFile = new File(filename);
272
 			if (transferType == TransferType.RECEIVE) {
272
 			if (transferType == TransferType.RECEIVE) {
273
 				fileOut = new DataOutputStream(new FileOutputStream(transferFile.getAbsolutePath(), (startpos > 0)));
273
 				fileOut = new DataOutputStream(new FileOutputStream(transferFile.getAbsolutePath(), (startpos > 0)));
274
-				//System.out.println("Appending: "+(startpos > 0));
275
 			}
274
 			}
276
 			out = new DataOutputStream(socket.getOutputStream());
275
 			out = new DataOutputStream(socket.getOutputStream());
277
 			in = new DataInputStream(socket.getInputStream());
276
 			in = new DataInputStream(socket.getInputStream());
327
 			readSize = readSize + bytesRead;
326
 			readSize = readSize + bytesRead;
328
 			
327
 			
329
 			if (bytesRead > 0) {
328
 			if (bytesRead > 0) {
329
+				if (handler != null) { handler.dataTransfered(this, bytesRead); }
330
 				fileOut.write(data, 0, bytesRead);
330
 				fileOut.write(data, 0, bytesRead);
331
-				out.writeInt(bytesRead);
331
+				// Send ack
332
+				out.writeInt(readSize);
332
 				out.flush();
333
 				out.flush();
333
 				if (readSize == size) {
334
 				if (readSize == size) {
334
 					fileOut.close();
335
 					fileOut.close();
353
 	 *         called again.
354
 	 *         called again.
354
 	 */
355
 	 */
355
 	protected boolean handleSend() {
356
 	protected boolean handleSend() {
356
-		if (fileIn == null) { return true; }
357
 		try {
357
 		try {
358
 			final byte[] data = new byte[blockSize];
358
 			final byte[] data = new byte[blockSize];
359
 			int bytesRead = fileIn.read(data);
359
 			int bytesRead = fileIn.read(data);
364
 				out.write(data, 0, bytesRead);
364
 				out.write(data, 0, bytesRead);
365
 				out.flush();
365
 				out.flush();
366
 				
366
 				
367
+				// Wait for acknowlegement packet.
367
 				if (!turbo) {
368
 				if (!turbo) {
368
-					while (bytesRead > 0) {
369
-						bytesRead = bytesRead - in.readInt();
370
-					}
369
+					int bytesRecieved;
370
+					do {
371
+						bytesRecieved = in.readInt();
372
+					} while ((readSize - bytesRecieved) > 0);
371
 				}
373
 				}
372
 				
374
 				
373
 				if (readSize == size) {
375
 				if (readSize == size) {
374
 					fileIn.close();
376
 					fileIn.close();
375
 					fileIn = null;
377
 					fileIn = null;
378
+					
379
+					// Process all the ack packets that may have been sent.
380
+					// In true turbo dcc mode, none will have been sent and the socket
381
+					// will just close, in fast-dcc mode all the acks will be here,
382
+					// So keep reading acks untill the socket closes (IOException) or we
383
+					// have recieved all the acks.
384
+					if (turbo) {
385
+						int ack = 0;
386
+						do {
387
+							try {
388
+								ack = in.readInt();
389
+							} catch (IOException e) {
390
+								break;
391
+							}
392
+						} while (ack > 0 && (readSize - ack) > 0);
393
+					}
394
+					
395
+					return false;
376
 				}
396
 				}
377
 				
397
 				
378
 				return true;
398
 				return true;

+ 65
- 6
src/com/dmdirc/addons/dcc/DCCSendWindow.java View File

54
 	/** Total data transfered */
54
 	/** Total data transfered */
55
 	private long transferCount = 0;
55
 	private long transferCount = 0;
56
 	
56
 	
57
+	/** Time Started */
58
+	private long timeStarted = 0;
59
+	
57
 	/** Progress Bar */
60
 	/** Progress Bar */
58
 	private final JProgressBar progress = new JProgressBar();
61
 	private final JProgressBar progress = new JProgressBar();
59
 	
62
 	
60
 	/** Status Label */
63
 	/** Status Label */
61
 	private final JLabel status = new JLabel("Status: Waiting");
64
 	private final JLabel status = new JLabel("Status: Waiting");
62
 	
65
 	
66
+	/** Speed Label */
67
+	private final JLabel speed = new JLabel("Speed: Unknown");
68
+	
69
+	/** Time Label */
70
+	private final JLabel remaining = new JLabel("Time Remaining: Unknown");
71
+	
72
+	/** Time Taken */
73
+	private final JLabel taken = new JLabel("Time Taken: 00:00");
74
+	
75
+	/** Button */
76
+	private final JButton button = new JButton("Cancel");
77
+	
63
 	/**
78
 	/**
64
 	 * Creates a new instance of DCCSendWindow with a given DCCSend object.
79
 	 * Creates a new instance of DCCSendWindow with a given DCCSend object.
65
 	 *
80
 	 *
78
 		
93
 		
79
 		getContentPane().setLayout(new MigLayout());
94
 		getContentPane().setLayout(new MigLayout());
80
 		
95
 		
81
-		transferCount = dcc.getFileStart();
82
-		
83
 		progress.setMinimum(0);
96
 		progress.setMinimum(0);
84
 		progress.setMaximum(100);
97
 		progress.setMaximum(100);
85
 		progress.setStringPainted(true);
98
 		progress.setStringPainted(true);
93
 			getContentPane().add(new JLabel("From: "+targetNick), "wrap");
106
 			getContentPane().add(new JLabel("From: "+targetNick), "wrap");
94
 		}
107
 		}
95
 		getContentPane().add(status, "wrap");
108
 		getContentPane().add(status, "wrap");
109
+		getContentPane().add(speed, "wrap");
110
+		getContentPane().add(remaining, "wrap");
111
+		getContentPane().add(taken, "wrap");
96
 		getContentPane().add(progress, "growx, wrap");
112
 		getContentPane().add(progress, "growx, wrap");
97
 		
113
 		
98
-		final JButton button = new JButton("Cancel");
99
 		button.addActionListener(this);
114
 		button.addActionListener(this);
100
-		
101
 		getContentPane().add(button, "wrap, align right");
115
 		getContentPane().add(button, "wrap, align right");
102
 		
116
 		
103
 		plugin.addWindow(this);
117
 		plugin.addWindow(this);
106
 	/** {@inheritDoc} */
120
 	/** {@inheritDoc} */
107
 	public void actionPerformed(final ActionEvent e) {
121
 	public void actionPerformed(final ActionEvent e) {
108
 		if (e.getActionCommand().equals("Cancel")) {
122
 		if (e.getActionCommand().equals("Cancel")) {
109
-			((JButton)e.getSource()).setEnabled(false);
123
+			button.setEnabled(false);
110
 			dcc.close();
124
 			dcc.close();
111
 		}
125
 		}
112
 	}
126
 	}
119
 	 */
133
 	 */
120
 	public void dataTransfered(final DCCSend dcc, final int bytes) {
134
 	public void dataTransfered(final DCCSend dcc, final int bytes) {
121
 		transferCount += bytes;
135
 		transferCount += bytes;
122
-		final double percent = (100.00 / dcc.getFileSize()) * transferCount;
136
+		final double percent = (100.00 / dcc.getFileSize()) * (transferCount + dcc.getFileStart());
123
 		
137
 		
124
 		if (dcc.getType() == DCCSend.TransferType.SEND) {
138
 		if (dcc.getType() == DCCSend.TransferType.SEND) {
125
 			status.setText("Status: Sending");
139
 			status.setText("Status: Sending");
127
 			status.setText("Status: Recieving");
141
 			status.setText("Status: Recieving");
128
 		}
142
 		}
129
 		
143
 		
144
+		updateSpeedAndTime();
145
+		
130
 		progress.setValue((int)Math.floor(percent));
146
 		progress.setValue((int)Math.floor(percent));
131
 	}
147
 	}
132
 	
148
 	
149
+	/**
150
+	 * Update the transfer speed, time remaining and time taken labels.
151
+	 */
152
+	public void updateSpeedAndTime() {
153
+		final long time = (System.currentTimeMillis() - timeStarted) / 1000;
154
+		final double bytesPerSecond = (time > 0) ? (transferCount / time) : 0;
155
+		
156
+		if (bytesPerSecond > 1048576) {
157
+			speed.setText(String.format("Speed: %.2f MB/s", (bytesPerSecond/1048576)));
158
+		} else if (bytesPerSecond > 1024) {
159
+			speed.setText(String.format("Speed: %.2f KB/s", (bytesPerSecond/1024)));
160
+		} else {
161
+			speed.setText(String.format("Speed: %f B/s", bytesPerSecond));
162
+		}
163
+		
164
+		final long remaningBytes = dcc.getFileSize() - dcc.getFileStart() - transferCount;
165
+		final double remainingSeconds = (bytesPerSecond > 0) ? (remaningBytes / bytesPerSecond) : 1;
166
+		
167
+		remaining.setText(String.format("Time Remaining: %s", duration((int)Math.floor(remainingSeconds))));
168
+		taken.setText(String.format("Time Taken: %s", duration(time)));
169
+	}
170
+	
171
+	/**
172
+	 * Get the duration in seconds as a string.
173
+	 *
174
+	 * @param secondsInput to get duration for
175
+	 * @return Duration as a string
176
+	 */
177
+	private String duration(final long secondsInput) {
178
+		final StringBuilder result = new StringBuilder();
179
+		final long hours = (secondsInput / 3600);
180
+		final long minutes = (secondsInput / 60 % 60);
181
+		final long seconds = (secondsInput % 60);
182
+		
183
+		if (hours > 0) { result.append(hours+":"); }
184
+		result.append(String.format("%0,2d:%0,2d",minutes,seconds));
185
+		
186
+		return result.toString();
187
+	}
188
+	
133
 	/**
189
 	/**
134
 	 * Called when the socket is closed
190
 	 * Called when the socket is closed
135
 	 *
191
 	 *
137
 	 */
193
 	 */
138
 	@Override
194
 	@Override
139
 	public void socketClosed(final DCCSend dcc) {
195
 	public void socketClosed(final DCCSend dcc) {
196
+		button.setEnabled(false);
140
 		if (transferCount == dcc.getFileSize()) {
197
 		if (transferCount == dcc.getFileSize()) {
141
 			status.setText("Status: Transfer Compelete.");
198
 			status.setText("Status: Transfer Compelete.");
142
 		} else {
199
 		} else {
143
 			status.setText("Status: Transfer Failed.");
200
 			status.setText("Status: Transfer Failed.");
144
 		}
201
 		}
202
+		updateSpeedAndTime();
145
 	}
203
 	}
146
 	
204
 	
147
 	/**
205
 	/**
152
 	@Override
210
 	@Override
153
 	public void socketOpened(final DCCSend dcc) {
211
 	public void socketOpened(final DCCSend dcc) {
154
 		status.setText("Status: Socket Opened");
212
 		status.setText("Status: Socket Opened");
213
+		timeStarted = System.currentTimeMillis();
155
 	}
214
 	}
156
 	
215
 	
157
 	/**
216
 	/**

Loading…
Cancel
Save