2 // This file is part of the aMule Project.
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2003-2008 lfroen ( lfroen@gmail.com / http://www.amule.org )
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 using System
.Collections
.Generic
;
27 using System
.ComponentModel
;
31 using System
.Windows
.Forms
;
32 using System
.Configuration
;
36 public partial class MainWindow
: Form
38 amuleRemote m_amuleRemote
= new amuleRemote();
39 Timer m_updateTimer
= null;
41 DownloadQueueContainer m_dload_info
;
42 SharedFileListContainer m_shared_info
;
44 amuleDownloadStatusList m_download_status_ctrl
;
45 amuleSharedFilesList m_shared_list_ctrl
;
47 amuleSearchControl m_search_ctrl
;
48 amuleSettings m_settings
= new amuleSettings();
52 InitializeComponent();
55 enum UpdateRequestState { Stats, MainInfo }
;
56 UpdateRequestState m_req_state
;
58 ecProto
.ecPacket
GetFullInfoRequest()
60 ecProto
.ecPacket req
= null;
61 Control current_ctrl
= panelMain
.Controls
[0];
62 if (current_ctrl
== m_download_status_ctrl
) {
63 req
= m_dload_info
.ReQuery();
64 } else if (current_ctrl
== m_shared_list_ctrl
) {
65 req
= m_shared_info
.ReQuery();
69 throw new Exception("unhandled GUI state");
74 private static void UpdateTimerProc(Object myObject
,
75 EventArgs myEventArgs
)
77 MainWindow w
= (MainWindow
)((Timer
)myObject
).Tag
;
79 // TODO: for testing 1 request is enough
80 w
.m_updateTimer
.Stop();
82 ecProto
.ecPacket req
= null;
83 switch(w
.m_req_state
) {
84 case UpdateRequestState
.Stats
:
85 req
= new ecProto
.ecPacket(ECOpCodes
.EC_OP_STAT_REQ
);
86 w
.m_req_state
= UpdateRequestState
.MainInfo
;
88 case UpdateRequestState
.MainInfo
:
89 req
= w
.GetFullInfoRequest();
90 w
.m_req_state
= UpdateRequestState
.Stats
;
93 w
.m_amuleRemote
.SendPacket(req
);
96 private void MainWindow_Load(object sender
, EventArgs e
)
99 // First, attempt to connect to remote core
101 ConnectDlg connectDlg
= new ConnectDlg();
102 string errorMsg
= null;
103 bool connect_ok
= false;
104 string amuleHost
= "", amulePort
= "";
105 while ( !connect_ok
) {
106 if (connectDlg
.ShowDialog() == DialogResult
.OK
) {
107 amuleHost
= connectDlg
.Host();
108 amulePort
= connectDlg
.Port();
109 string pass
= connectDlg
.Pass();
110 int amulePort_int
= 0;
112 amulePort_int
= Convert
.ToInt16(amulePort
, 10);
114 MessageBox
.Show("Invalid port number", "Error",
115 MessageBoxButtons
.OK
, MessageBoxIcon
.Error
);
118 connect_ok
= m_amuleRemote
.ConnectToCore(amuleHost
, amulePort_int
, pass
, ref errorMsg
);
120 Console
.WriteLine("Connect failed '{0}'", errorMsg
);
121 MessageBox
.Show(errorMsg
, "Connection to aMule core failed",
122 MessageBoxButtons
.OK
, MessageBoxIcon
.Stop
);
130 textLinktatus
.Text
= "aMule core on [" + amuleHost
+ ":" + amulePort
+ "]";
131 Text
= "aMule remote control [" + amuleHost
+ ":" + amulePort
+ "]";
132 Size
= m_settings
.MainWindowSize
;
134 m_amuleRemote
.SetECHandler(new amuleMainECHanler(this));
137 // Connection OK at this point
139 m_download_status_ctrl
= new amuleDownloadStatusList();
140 m_dload_info
= new DownloadQueueContainer(m_download_status_ctrl
);
141 m_download_status_ctrl
.ItemContainer
= m_dload_info
;
143 m_download_status_ctrl
.OnCancelItem
+=
144 new DownloadStatusListEventHandler(m_download_status_ctrl_OnCancelItem
);
145 m_download_status_ctrl
.OnPauseItem
+=
146 new DownloadStatusListEventHandler(m_download_status_ctrl_OnPauseItem
);
147 m_download_status_ctrl
.OnResumeItem
+=
148 new DownloadStatusListEventHandler(m_download_status_ctrl_OnResumeItem
);
150 m_shared_list_ctrl
= new amuleSharedFilesList();
151 m_shared_info
= new SharedFileListContainer(m_shared_list_ctrl
);
153 m_search_ctrl
= new amuleSearchControl();
155 m_updateTimer
= new Timer();
156 m_updateTimer
.Tag
= this;
157 m_updateTimer
.Tick
+= new EventHandler(UpdateTimerProc
);
158 m_updateTimer
.Interval
= 1000;
159 m_updateTimer
.Start();
161 // default - download list view
162 panelMain
.Controls
.Add(m_download_status_ctrl
);
164 // for testing set needed state!
165 m_req_state
= UpdateRequestState
.MainInfo
;
168 void m_download_status_ctrl_OnResumeItem()
170 ecProto
.ecPacket cmd
= new ecProto
.ecPacket(ECOpCodes
.EC_OP_PARTFILE_RESUME
);
171 m_download_status_ctrl
.SelectedItemsToCommand(cmd
);
172 m_amuleRemote
.SendPacket(cmd
);
175 void m_download_status_ctrl_OnPauseItem()
177 ecProto
.ecPacket cmd
= new ecProto
.ecPacket(ECOpCodes
.EC_OP_PARTFILE_PAUSE
);
178 m_download_status_ctrl
.SelectedItemsToCommand(cmd
);
179 m_amuleRemote
.SendPacket(cmd
);
182 void m_download_status_ctrl_OnCancelItem()
184 string msg
= "Following files will be cancelled:\n";
185 foreach ( ListViewItem i
in m_download_status_ctrl
.SelectedItems
) {
186 msg
+= i
.Text
+ "\n";
188 if ( MessageBox
.Show(msg
, "Cancel files", MessageBoxButtons
.OKCancel
,
189 MessageBoxIcon
.Question
) == DialogResult
.OK
) {
190 ecProto
.ecPacket cmd
= new ecProto
.ecPacket(ECOpCodes
.EC_OP_PARTFILE_DELETE
);
191 m_download_status_ctrl
.SelectedItemsToCommand(cmd
);
192 m_amuleRemote
.SendPacket(cmd
);
197 // Process reply for "stats"
199 delegate void StatsReplyCallback(ecProto
.ecPacket packet
);
200 public void StatsReplyInvoke(ecProto
.ecPacket packet
)
202 if ( InvokeRequired
) {
203 StatsReplyCallback d
= new StatsReplyCallback(StatsReply
);
210 void StatsReply(ecProto
.ecPacket packet
)
212 ecProto
.ecTag t
= null;
213 t
= packet
.SubTag(ECTagNames
.EC_TAG_STATS_DL_SPEED
);
214 int dl_speed
= ((ecProto
.ecTagInt
)t
).ValueInt();
216 t
= packet
.SubTag(ECTagNames
.EC_TAG_STATS_UL_SPEED
);
217 int ul_speed
= ((ecProto
.ecTagInt
)t
).ValueInt();
218 //string server = ((ecProto.ecTagString)t).ToString();
220 ecProto
.ecConnStateTag connState
=
221 new ecProto
.ecConnStateTag((ecProto
.ecTagInt
)packet
.SubTag(ECTagNames
.EC_TAG_CONNSTATE
));
223 textBoxDownSpeed
.Text
= "Down:" + ValueToPrefix(dl_speed
) + "/s";
224 textBoxUpSpeed
.Text
= "Up:" + ValueToPrefix(ul_speed
) + "/s";
225 if ( connState
.IsConnected() ) {
226 if (connState
.IsConnectedED2K()) {
227 textLinktatus
.Text
= "ED2K: connected";
228 //ecProto.ecTagString server_name = (ecProto.ecTagString)server.SubTag(ECTagNames.EC_TAG_SERVER_NAME);
229 //toolStripStatusServer.Text = server_name.StringValue();
231 //toolStripStatusServer.Text = "";
232 if (connState
.IsConnectingED2K() ) {
233 textLinktatus
.Text
= "ED2K: connecting ...";
235 textLinktatus
.Text
= "ED2K: disconnected";
238 if (connState
.IsConnectedKademlia()) {
239 //textLinktatus.Text = "KAD: connected";
245 public void DloadQueueReply(ecProto
.ecPacket packet
)
247 ecProto
.ecPacket reply
= m_dload_info
.HandlePacket(packet
);
248 if ( reply
!= null ) {
249 m_amuleRemote
.SendPacket(reply
);
253 public void SharedFilesReply(ecProto
.ecPacket packet
)
255 ecProto
.ecPacket reply
= m_shared_info
.HandlePacket(packet
);
257 m_amuleRemote
.SendPacket(reply
);
261 private void buttonXfer_Click(object sender
, EventArgs e
)
263 if ( panelMain
.Controls
[0] != m_download_status_ctrl
) {
264 panelMain
.Controls
.Clear();
265 panelMain
.Controls
.Add(m_download_status_ctrl
);
269 private void buttonNetwork_Click(object sender
, EventArgs e
)
271 UpdateTimerProc(m_updateTimer
, null);
274 private void buttonSearch_Click(object sender
, EventArgs e
)
276 if ( panelMain
.Controls
[0] != m_search_ctrl
) {
277 panelMain
.Controls
.Clear();
278 panelMain
.Controls
.Add(m_search_ctrl
);
282 private void buttonShared_Click(object sender
, EventArgs e
)
284 if ( panelMain
.Controls
[0] != m_shared_list_ctrl
) {
285 panelMain
.Controls
.Clear();
286 panelMain
.Controls
.Add(m_shared_list_ctrl
);
291 private void buttonAddLink_Click(object sender
, EventArgs e
)
293 AddLinkDialog dlg
= new AddLinkDialog();
294 if ( dlg
.ShowDialog() == DialogResult
.OK
) {
295 string link
= dlg
.textBoxLink
.Text
;
296 ecProto
.ecPacket cmd
= new ecProto
.ecPacket(ECOpCodes
.EC_OP_ADD_LINK
);
297 ecProto
.ecTagString linktag
= new ecProto
.ecTagString(ECTagNames
.EC_TAG_STRING
, link
);
298 cmd
.AddSubtag(linktag
);
299 m_amuleRemote
.SendPacket(cmd
);
303 private void buttonPrefs_Click(object sender
, EventArgs e
)
308 private void buttonAbout_Click(object sender
, EventArgs e
)
310 AboutBox dlg
= new AboutBox();
314 private void MainWindow_FormClosed(object sender
, FormClosedEventArgs e
)
316 m_settings
.MainWindowSize
= Size
;
321 public string ValueToPrefix(Int64
value)
323 if ( value < 1024 ) {
324 return string.Format("{0} bytes", value);
325 } else if ( value < 1048576 ) {
326 return string.Format("{0:f} Kb", ((float)value) / 1024);
327 } else if ( value < 1073741824 ) {
328 return string.Format("{0:f} Mb", ((float)value) / 1048576);
330 return string.Format("{0:f} Gb", ((float)value) / 1073741824);
336 [SettingsGroupNameAttribute("Application")]
337 public class amuleSettings
: ApplicationSettingsBase
{
339 [UserScopedSettingAttribute()]
342 get { return (string)this["Host"]; }
343 set { this["Host"] = value; }
346 [UserScopedSettingAttribute()]
347 public string Password
349 get { return (string)this["Password"]; }
350 set { this["Password"] = value; }
353 [UserScopedSetting()]
354 [DefaultSettingValueAttribute("500, 400")]
355 public Size MainWindowSize
357 get { return (Size)this["MainWindowSize"]; }
358 set { this["MainWindowSize"] = value; }
363 public class amuleMainECHanler
: amuleECHandler
{
364 MainWindow m_owner
= null;
365 public amuleMainECHanler(MainWindow o
)
370 public override void HandlePacket(ecProto
.ecPacket packet
)
372 ECOpCodes op
= packet
.Opcode();
374 case ECOpCodes
.EC_OP_STATS
:
375 m_owner
.StatsReplyInvoke(packet
);
377 case ECOpCodes
.EC_OP_DLOAD_QUEUE
:
378 m_owner
.DloadQueueReply(packet
);
380 case ECOpCodes
.EC_OP_SHARED_FILES
:
381 m_owner
.SharedFilesReply(packet
);
383 case ECOpCodes
.EC_OP_NOOP
:
386 throw new Exception("Unhandled EC reply");
391 public class amuleListView
: ListView
{
392 protected int[] m_column_index
;
394 public amuleListView()
396 Dock
= DockStyle
.Fill
;
398 DoubleBuffered
= true;
399 FullRowSelect
= true;
403 public void LoadColumns(string [] columns
, int [] width
)
406 foreach (string c
in columns
) {
407 if ( width
[i
] == 0 ) {
410 ColumnHeader h
= new ColumnHeader();
412 h
.Width
= width
[i
++];
417 public void CreateColumtAt(string name
, int width
, int index
)
419 ColumnHeader h
= new ColumnHeader();
423 Columns
.Insert(m_column_index
[index
], h
);
425 public void RemoveColumnAt(int index
)
427 Columns
.RemoveAt(m_column_index
[index
]);
430 public void AppendItemToCtxMenu(ContextMenuStrip menu
, string text
,
431 object tag
, bool check_state
, EventHandler target
)
433 ToolStripMenuItem it
= new ToolStripMenuItem(text
);
435 it
.CheckState
= check_state
? CheckState
.Checked
: CheckState
.Unchecked
;
441 public class amuleSharedFilesList
: amuleListView
, IContainerUI
{
442 public amuleSharedFilesList()
444 string[] columns
= { "File name", "Size" }
;
445 int[] width
= { 300, 100, 100, 100 }
;
446 LoadColumns(columns
, width
);
449 #region IContainerUI Members
451 delegate void UpdateCallback();
452 void IContainerUI
.MyEndUpdate()
454 if (InvokeRequired
) {
455 UpdateCallback d
= new UpdateCallback(EndUpdate
);
462 void IContainerUI
.MyBeginUpdate()
464 if (InvokeRequired
) {
465 UpdateCallback d
= new UpdateCallback(BeginUpdate
);
472 delegate void ItemCallback(SharedFileItem i
);
474 void IContainerUI
.InsertItem(object i
)
476 SharedFileItem it
= i
as SharedFileItem
;
477 if (InvokeRequired
) {
478 ItemCallback d
= new ItemCallback(DoInsertItem
);
485 void IContainerUI
.UpdateItem(object i
)
487 throw new Exception("The method or operation is not implemented.");
490 void DoInsertItem(SharedFileItem i
)
492 ListViewItem it
= new ListViewItem(i
.Name
);
494 it
.SubItems
.Add(new ListViewItem
.ListViewSubItem(it
, i
.Size
));
501 void DoUpdateItem(SharedFileItem i
)
503 ListViewItem it
= i
.UiItem
as ListViewItem
;