1//
2// This file is part of the aMule Project.
3//
4// Copyright (c) 2004-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5//
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
8// respective authors.
9//
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.
14//
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.
19//
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
23//
24
25#include "amule.h"				// Interface declarations.
26
27#include <common/EventIDs.h>
28#include <common/ClientVersion.h>
29
30#include <wx/clipbrd.h>			// Needed for wxClipBoard
31#include <wx/tokenzr.h>			// Needed for wxStringTokenizer
32
33#include "SharedFilesWnd.h"		// Needed for CSharedFilesWnd
34#include "Timer.h"				// Needed for CTimer
35#include "PartFile.h"			// Needed for CPartFile
36
37#include "muuli_wdr.h"			// Needed for IDs
38#include "amuleDlg.h"			// Needed for CamuleDlg
39#include "PartFileConvert.h"
40#include "ThreadTasks.h"
41#include "Logger.h"				// Needed for EVT_MULE_LOGGING
42#include "GuiEvents.h"			// Needed for EVT_MULE_NOTIFY
43
44#ifdef __WXMAC__
45	#include <CoreFoundation/CFBundle.h>  // Do_not_auto_remove
46	#include <ApplicationServices/ApplicationServices.h>	// For LSRegisterURL // Do_not_auto_remove
47#endif
48
49#ifndef CLIENT_GUI
50#include "InternalEvents.h"		// Needed for wxEVT_*
51
52BEGIN_EVENT_TABLE(CamuleGuiApp, wxApp)
53
54	// Socket handlers
55	// Listen Socket
56	EVT_SOCKET(ID_LISTENSOCKET_EVENT, CamuleGuiApp::ListenSocketHandler)
57
58	// UDP Socket (servers)
59	EVT_SOCKET(ID_SERVERUDPSOCKET_EVENT, CamuleGuiApp::UDPSocketHandler)
60	// UDP Socket (clients)
61	EVT_SOCKET(ID_CLIENTUDPSOCKET_EVENT, CamuleGuiApp::UDPSocketHandler)
62
63	// Socket timers (TCP + UDP)
64	EVT_MULE_TIMER(ID_SERVER_RETRY_TIMER_EVENT, CamuleGuiApp::OnTCPTimer)
65
66	// Core timer
67	EVT_MULE_TIMER(ID_CORE_TIMER_EVENT, CamuleGuiApp::OnCoreTimer)
68
69	EVT_MULE_NOTIFY(CamuleGuiApp::OnNotifyEvent)
70
71	// Async dns handling
72	EVT_MULE_INTERNAL(wxEVT_CORE_UDP_DNS_DONE, -1, CamuleGuiApp::OnUDPDnsDone)
73
74	EVT_MULE_INTERNAL(wxEVT_CORE_SOURCE_DNS_DONE, -1, CamuleGuiApp::OnSourceDnsDone)
75
76	EVT_MULE_INTERNAL(wxEVT_CORE_SERVER_DNS_DONE, -1, CamuleGuiApp::OnServerDnsDone)
77
78	// Hash ended notifier
79	EVT_MULE_HASHING(CamuleGuiApp::OnFinishedHashing)
80	EVT_MULE_AICH_HASHING(CamuleGuiApp::OnFinishedAICHHashing)
81
82	// File completion ended notifier
83	EVT_MULE_FILE_COMPLETED(CamuleGuiApp::OnFinishedCompletion)
84
85	// HTTPDownload finished
86	EVT_MULE_INTERNAL(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD, -1, CamuleGuiApp::OnFinishedHTTPDownload)
87
88	// Disk space preallocation finished
89	EVT_MULE_ALLOC_FINISHED(CamuleGuiApp::OnFinishedAllocation)
90END_EVENT_TABLE()
91
92
93IMPLEMENT_APP(CamuleGuiApp)
94
95#endif // CLIENT_GUI
96
97CamuleGuiBase::CamuleGuiBase()
98{
99	amuledlg = NULL;
100	m_FileDetailDialogActive = 0;
101}
102
103
104CamuleGuiBase::~CamuleGuiBase()
105{
106	#ifndef CLIENT_GUI
107	CPartFileConvert::StopThread();
108	#endif
109}
110
111
112int CamuleGuiBase::ShowAlert(wxString msg, wxString title, int flags)
113{
114	return wxMessageBox(msg, title, flags);
115}
116
117
118int CamuleGuiBase::InitGui(bool geometry_enabled, wxString &geom_string)
119{
120	// Standard size is 800x600 at position (0,0)
121	int geometry_x = 0;
122	int geometry_y = 0;
123	unsigned int geometry_width = 800;
124	unsigned int geometry_height = 600;
125
126	if ( geometry_enabled ) {
127		// I plan on moving this to a separate function, as it just clutters up OnInit()
128		/*
129		This implementation might work with mac, provided that the
130		SetSize() function works as expected.
131		*/
132
133		// Remove possible prefix
134		if ( geom_string.GetChar(0) == '=' ) {
135			geom_string.Remove( 0, 1 );
136		}
137
138		// Stupid ToLong functions forces me to use longs =(
139		long width = geometry_width;
140		long height = geometry_height;
141
142		// Get the avilable display area
143		wxRect display = wxGetClientDisplayRect();
144
145		// We want to place aMule inside the client area by default
146		long x = display.x;
147		long y = display.y;
148
149		// Tokenize the string
150		wxStringTokenizer tokens(geom_string, wxT("xX+-"));
151
152		// First part: Program width
153		if ( tokens.GetNextToken().ToLong( &width ) ) {
154			wxString prefix = geom_string[ tokens.GetPosition() - 1 ];
155			if ( prefix == wxT("x") || prefix == wxT("X") ) {
156				// Second part: Program height
157				if ( tokens.GetNextToken().ToLong( &height ) ) {
158					prefix = geom_string[ tokens.GetPosition() - 1 ];
159					if ( prefix == wxT("+") || prefix == wxT("-") ) {
160						// Third part: X-Offset
161						if ( tokens.GetNextToken().ToLong( &x ) ) {
162							if ( prefix == wxT("-") )
163								x = display.GetRight() - ( width + x );
164							prefix = geom_string[ tokens.GetPosition() - 1 ];
165							if ( prefix == wxT("+") || prefix == wxT("-") ) {
166								// Fourth part: Y-Offset
167								if ( tokens.GetNextToken().ToLong( &y ) ) {
168									if ( prefix == wxT("-") )
169										y = display.GetBottom() - ( height + y );
170								}
171							}
172						}
173					}
174					// We need at least height and width to override default geometry
175					geometry_enabled = true;
176					geometry_x = x;
177					geometry_y = y;
178					geometry_width = width;
179					geometry_height = height;
180				}
181			}
182		}
183	}
184
185	ResetTitle();
186
187	// Should default/last-used position be overridden?
188	if ( geometry_enabled ) {
189		amuledlg = new CamuleDlg(NULL, m_FrameTitle,
190		                         wxPoint(geometry_x,geometry_y),
191		                         wxSize( geometry_width, geometry_height - 58 ));
192	} else {
193		amuledlg = new CamuleDlg(NULL, m_FrameTitle);
194	}
195
196	return 0;
197}
198
199// Sets m_FrameTitle
200void CamuleGuiBase::ResetTitle()
201{
202#ifdef SVNDATE
203	#ifdef CLIENT_GUI
204		m_FrameTitle = CFormat(wxT("aMule remote control %s %s")) % wxT( VERSION ) % wxT( SVNDATE );
205	#else
206		m_FrameTitle = CFormat(wxT("aMule %s %s")) % wxT( VERSION ) % wxT( SVNDATE );
207	#endif
208#else
209	#ifdef CLIENT_GUI
210		m_FrameTitle = _("aMule remote control");
211	#else
212		m_FrameTitle = _("aMule");
213	#endif
214
215	if (thePrefs::ShowVersionOnTitle()) {
216		m_FrameTitle += wxT(' ');
217		m_FrameTitle += wxT( VERSION );
218	}
219#endif
220}
221
222
223// Sets the contents of the clipboard. Prior content  erased.
224bool CamuleGuiBase::CopyTextToClipboard(wxString strText)
225{
226	bool ClipBoardOpen = wxTheClipboard->Open();
227	if (ClipBoardOpen) {
228		wxTheClipboard->UsePrimarySelection(false);
229		wxTheClipboard->SetData(new wxTextDataObject(strText));
230		wxTheClipboard->Close();
231	}
232
233	return ClipBoardOpen;
234}
235
236
237void CamuleGuiBase::AddGuiLogLine(const wxString& line)
238{
239	if (amuledlg) {
240		while ( !m_logLines.empty() ) {
241			amuledlg->AddLogLine(m_logLines.front());
242			m_logLines.pop_front();
243		}
244		amuledlg->AddLogLine(line);
245	} else {
246		m_logLines.push_back(line);
247	}
248}
249
250
251#ifndef CLIENT_GUI
252
253int CamuleGuiApp::InitGui(bool geometry_enable, wxString &geometry_string)
254{
255	CamuleGuiBase::InitGui(geometry_enable, geometry_string);
256	SetTopWindow(amuledlg);
257	return 0;
258}
259
260
261int CamuleGuiApp::ShowAlert(wxString msg, wxString title, int flags)
262{
263	return CamuleGuiBase::ShowAlert(msg, title, flags);
264}
265
266
267int CamuleGuiApp::OnExit()
268{
269	delete core_timer;
270
271	return CamuleApp::OnExit();
272}
273
274
275void CamuleGuiApp::ShutDown(wxCloseEvent &WXUNUSED(evt))
276{
277	amuledlg->DlgShutDown();
278	amuledlg->Destroy();
279	CamuleApp::ShutDown();
280}
281
282
283bool CamuleGuiApp::OnInit()
284{
285	amuledlg = NULL;
286
287	if ( !CamuleApp::OnInit() ) {
288		return false;
289	}
290
291	// Create the Core timer
292	core_timer = new CTimer(this,ID_CORE_TIMER_EVENT);
293	if (!core_timer) {
294		AddLogLineCS(_("Fatal Error: Failed to create Core Timer"));
295		OnExit();
296	}
297
298	// Start the Core and Gui timers
299
300	// Note: wxTimer can be off by more than 10% !!!
301	// In addition to the systematic error introduced by wxTimer, we are losing
302	// timer cycles due to high CPU load.  I've observed about 0.5% random loss of cycles under
303	// low load, and more than 6% lost cycles with heavy download traffic and/or other tasks
304	// in the system, such as a video player or a VMware virtual machine.
305	// The upload queue process loop has now been rewritten to compensate for timer errors.
306	// When adding functionality, assume that the timer is only approximately correct;
307	// for measurements, always use the system clock [::GetTickCount()].
308	core_timer->Start(CORE_TIMER_PERIOD);
309	amuledlg->StartGuiTimer();
310
311#ifdef __WXMAC__
312	// This tells the OS to notice the ed2kHelperScript.app inside aMule.app.
313	// ed2kHelperScript.app describes itself (Info.plist) as handling ed2k URLs.
314	// So, from then on the OS will know to pass ed2k URLs to the helper app.
315	CFURLRef ed2kHelperUrl = CFBundleCopyAuxiliaryExecutableURL(
316		CFBundleGetMainBundle(), CFSTR("ed2kHelperScript.app"));
317	if (ed2kHelperUrl) {
318		LSRegisterURL(ed2kHelperUrl, true);
319		CFRelease(ed2kHelperUrl);
320	}
321#endif
322
323	return true;
324}
325
326
327wxString CamuleGuiApp::GetLog(bool reset)
328{
329	if ( reset ) {
330		amuledlg->ResetLog(ID_LOGVIEW);
331	}
332	return CamuleApp::GetLog(reset);
333}
334
335
336wxString CamuleGuiApp::GetServerLog(bool reset)
337{
338	if ( reset ) {
339		amuledlg->ResetLog(ID_SERVERINFO);
340	}
341	return CamuleApp::GetServerLog(reset);
342}
343
344
345void CamuleGuiApp::AddServerMessageLine(wxString &msg)
346{
347	amuledlg->AddServerMessageLine(msg);
348	CamuleApp::AddServerMessageLine(msg);
349}
350
351#endif /* CLIENT_GUI */
352// File_checked_for_headers
353