2 // This file is part of the aMule Project.
4 // Copyright (c) 2004-2008 aMule Team ( admin@amule.org / http://www.amule.org )
6 // Any parts of this program derived from the xMule, lMule or eMule project,
7 // or contributed by third-party developers are copyrighted by their
10 // This program is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "amule.h" // Interface declarations.
27 #include <common/EventIDs.h>
28 #include <common/ClientVersion.h>
30 #include <wx/clipbrd.h> // Needed for wxClipBoard
31 #include <wx/tokenzr.h> // Needed for wxStringTokenizer
33 #include "SharedFilesWnd.h" // Needed for CSharedFilesWnd
34 #include "Timer.h" // Needed for CTimer
35 #include "PartFile.h" // Needed for CPartFile
36 #include "updownclient.h" // Needed for CUpDownClient
38 #include "muuli_wdr.h" // Needed for IDs
39 #include "amuleDlg.h" // Needed for CamuleDlg
40 #include "PartFileConvert.h"
41 #include "ThreadTasks.h"
42 #include "Logger.h" // Needed for EVT_MULE_LOGGING
43 #include "GuiEvents.h" // Needed for EVT_MULE_NOTIFY
46 #include <CoreFoundation/CFBundle.h> // Do_not_auto_remove
47 #include <ApplicationServices/ApplicationServices.h> // For LSRegisterURL // Do_not_auto_remove
51 #include "InternalEvents.h" // Needed for wxEVT_*
53 BEGIN_EVENT_TABLE(CamuleGuiApp
, wxApp
)
57 EVT_SOCKET(ID_LISTENSOCKET_EVENT
, CamuleGuiApp::ListenSocketHandler
)
59 // UDP Socket (servers)
60 EVT_SOCKET(ID_SERVERUDPSOCKET_EVENT
, CamuleGuiApp::UDPSocketHandler
)
61 // UDP Socket (clients)
62 EVT_SOCKET(ID_CLIENTUDPSOCKET_EVENT
, CamuleGuiApp::UDPSocketHandler
)
64 // Socket timers (TCP + UDP)
65 EVT_MULE_TIMER(ID_SERVER_RETRY_TIMER_EVENT
, CamuleGuiApp::OnTCPTimer
)
68 EVT_MULE_TIMER(ID_CORE_TIMER_EVENT
, CamuleGuiApp::OnCoreTimer
)
70 EVT_MULE_NOTIFY(CamuleGuiApp::OnNotifyEvent
)
71 EVT_MULE_LOGGING(CamuleGuiApp::OnLoggingEvent
)
74 EVT_MULE_INTERNAL(wxEVT_CORE_UDP_DNS_DONE
, -1, CamuleGuiApp::OnUDPDnsDone
)
76 EVT_MULE_INTERNAL(wxEVT_CORE_SOURCE_DNS_DONE
, -1, CamuleGuiApp::OnSourceDnsDone
)
78 EVT_MULE_INTERNAL(wxEVT_CORE_SERVER_DNS_DONE
, -1, CamuleGuiApp::OnServerDnsDone
)
80 // Hash ended notifier
81 EVT_MULE_HASHING(CamuleGuiApp::OnFinishedHashing
)
82 EVT_MULE_AICH_HASHING(CamuleGuiApp::OnFinishedAICHHashing
)
84 // File completion ended notifier
85 EVT_MULE_FILE_COMPLETED(CamuleGuiApp::OnFinishedCompletion
)
87 // HTTPDownload finished
88 EVT_MULE_INTERNAL(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD
, -1, CamuleGuiApp::OnFinishedHTTPDownload
)
90 // Disk space preallocation finished
91 EVT_MULE_ALLOC_FINISHED(CamuleGuiApp::OnFinishedAllocation
)
95 IMPLEMENT_APP(CamuleGuiApp
)
99 CamuleGuiBase::CamuleGuiBase()
102 m_FileDetailDialogActive
= 0;
106 CamuleGuiBase::~CamuleGuiBase()
109 CPartFileConvert::StopThread();
114 void CamuleGuiBase::ShowAlert(wxString msg
, wxString title
, int flags
)
116 wxMessageBox(msg
, title
, flags
);
120 int CamuleGuiBase::InitGui(bool geometry_enabled
, wxString
&geom_string
)
122 // Standard size is 800x600 at position (0,0)
125 unsigned int geometry_width
= 800;
126 unsigned int geometry_height
= 600;
128 if ( geometry_enabled
) {
129 // I plan on moving this to a separate function, as it just clutters up OnInit()
131 This implementation might work with mac, provided that the
132 SetSize() function works as expected.
135 // Remove possible prefix
136 if ( geom_string
.GetChar(0) == '=' ) {
137 geom_string
.Remove( 0, 1 );
140 // Stupid ToLong functions forces me to use longs =(
141 long width
= geometry_width
;
142 long height
= geometry_height
;
144 // Get the avilable display area
145 wxRect display
= wxGetClientDisplayRect();
147 // We want to place aMule inside the client area by default
151 // Tokenize the string
152 wxStringTokenizer
tokens(geom_string
, wxT("xX+-"));
154 // First part: Program width
155 if ( tokens
.GetNextToken().ToLong( &width
) ) {
156 wxString prefix
= geom_string
[ tokens
.GetPosition() - 1 ];
157 if ( prefix
== wxT("x") || prefix
== wxT("X") ) {
158 // Second part: Program height
159 if ( tokens
.GetNextToken().ToLong( &height
) ) {
160 prefix
= geom_string
[ tokens
.GetPosition() - 1 ];
161 if ( prefix
== wxT("+") || prefix
== wxT("-") ) {
162 // Third part: X-Offset
163 if ( tokens
.GetNextToken().ToLong( &x
) ) {
164 if ( prefix
== wxT("-") )
165 x
= display
.GetRight() - ( width
+ x
);
166 prefix
= geom_string
[ tokens
.GetPosition() - 1 ];
167 if ( prefix
== wxT("+") || prefix
== wxT("-") ) {
168 // Fourth part: Y-Offset
169 if ( tokens
.GetNextToken().ToLong( &y
) ) {
170 if ( prefix
== wxT("-") )
171 y
= display
.GetBottom() - ( height
+ y
);
176 // We need at least height and width to override default geometry
177 geometry_enabled
= true;
180 geometry_width
= width
;
181 geometry_height
= height
;
187 // Should default/last-used position be overridden?
190 m_FrameTitle
= wxString::Format(wxT("aMule remote control %s %s"), wxT( VERSION
), wxT( SVNDATE
));
192 m_FrameTitle
= wxString::Format(wxT("aMule %s %s"), wxT( VERSION
), wxT( SVNDATE
));
196 m_FrameTitle
= wxString::Format(_("aMule remote control"));
198 m_FrameTitle
= wxString::Format(_("aMule"));
201 if ( geometry_enabled
) {
202 amuledlg
= new CamuleDlg(NULL
, m_FrameTitle
,
203 wxPoint(geometry_x
,geometry_y
),
204 wxSize( geometry_width
, geometry_height
- 58 ));
206 amuledlg
= new CamuleDlg(NULL
, m_FrameTitle
);
213 // Sets the contents of the clipboard. Prior content erased.
214 bool CamuleGuiBase::CopyTextToClipboard(wxString strText
)
216 bool ClipBoardOpen
= wxTheClipboard
->Open();
218 wxTheClipboard
->UsePrimarySelection(false);
219 wxTheClipboard
->SetData(new wxTextDataObject(strText
));
220 wxTheClipboard
->Close();
223 return ClipBoardOpen
;
229 int CamuleGuiApp::InitGui(bool geometry_enable
, wxString
&geometry_string
)
231 CamuleGuiBase::InitGui(geometry_enable
, geometry_string
);
232 SetTopWindow(amuledlg
);
237 void CamuleGuiApp::ShowAlert(wxString msg
, wxString title
, int flags
)
239 CamuleGuiBase::ShowAlert(msg
, title
, flags
);
243 int CamuleGuiApp::OnExit()
247 return CamuleApp::OnExit();
251 void CamuleGuiApp::ShutDown(wxCloseEvent
&WXUNUSED(evt
))
253 amuledlg
->DlgShutDown();
255 CamuleApp::ShutDown();
259 bool CamuleGuiApp::OnInit()
263 if ( !CamuleApp::OnInit() ) {
267 // Create the Core timer
268 core_timer
= new CTimer(this,ID_CORE_TIMER_EVENT
);
270 printf("Fatal Error: Failed to create Core Timer");
274 // Start the Core and Gui timers
276 // Note: wxTimer can be off by more than 10% !!!
277 // In addition to the systematic error introduced by wxTimer, we are losing
278 // timer cycles due to high CPU load. I've observed about 0.5% random loss of cycles under
279 // low load, and more than 6% lost cycles with heavy download traffic and/or other tasks
280 // in the system, such as a video player or a VMware virtual machine.
281 // The upload queue process loop has now been rewritten to compensate for timer errors.
282 // When adding functionality, assume that the timer is only approximately correct;
283 // for measurements, always use the system clock [::GetTickCount()].
284 core_timer
->Start(100);
285 amuledlg
->StartGuiTimer();
288 // This tells the OS to notice the ed2kHelperScript.app inside aMule.app.
289 // ed2kHelperScript.app describes itself (Info.plist) as handling ed2k URLs.
290 // So, from then on the OS will know to pass ed2k URLs to the helper app.
291 CFURLRef ed2kHelperUrl
= CFBundleCopyAuxiliaryExecutableURL(
292 CFBundleGetMainBundle(), CFSTR("ed2kHelperScript.app"));
294 LSRegisterURL(ed2kHelperUrl
, true);
295 CFRelease(ed2kHelperUrl
);
303 wxString
CamuleGuiApp::GetLog(bool reset
)
306 amuledlg
->ResetLog(ID_LOGVIEW
);
308 return CamuleApp::GetLog(reset
);
312 wxString
CamuleGuiApp::GetServerLog(bool reset
)
315 amuledlg
->ResetLog(ID_SERVERINFO
);
317 return CamuleApp::GetServerLog(reset
);
321 void CamuleGuiApp::AddServerMessageLine(wxString
&msg
)
323 amuledlg
->AddServerMessageLine(msg
);
324 CamuleApp::AddServerMessageLine(msg
);
328 void CamuleGuiApp::OnLoggingEvent(CLoggingEvent
& evt
)
331 while ( !m_logLines
.empty() ) {
332 QueuedLogLine entry
= m_logLines
.front();
333 amuledlg
->AddLogLine( entry
.show
, entry
.line
);
334 m_logLines
.pop_front();
337 amuledlg
->AddLogLine(evt
.IsCritical(), evt
.Message());
339 QueuedLogLine entry
= { evt
.Message(), evt
.IsCritical() };
340 m_logLines
.push_back( entry
);
343 CamuleApp::AddLogLine( evt
.Message() );
346 #endif /* CLIENT_GUI */
347 // File_checked_for_headers