]> icculus.org git repositories - taylor/freespace2.git/blob - src/launcher/launcher.cpp
fix some memory issues that were causing problems
[taylor/freespace2.git] / src / launcher / launcher.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 #include "launcher.h"
10 #include "launchersetup.h"
11
12 #include "wx/filename.h"
13 #include "wx/stdpaths.h"
14
15 #include "pstypes.h"
16 #include "osregistry.h"
17 #include "cfile.h"
18
19 #ifndef MAKE_FS1
20 #include "res/fs2_background.xpm"
21 #include "res/fs2_btn_help.xpm"
22 #include "res/fs2_btn_help-hover.xpm"
23 #include "res/fs2_btn_help-click.xpm"
24 #include "res/fs2_btn_play.xpm"
25 #include "res/fs2_btn_play-hover.xpm"
26 #include "res/fs2_btn_play-click.xpm"
27 #include "res/fs2_btn_pxo.xpm"
28 #include "res/fs2_btn_pxo-hover.xpm"
29 #include "res/fs2_btn_pxo-click.xpm"
30 #include "res/fs2_btn_quit.xpm"
31 #include "res/fs2_btn_quit-hover.xpm"
32 #include "res/fs2_btn_quit-click.xpm"
33 #include "res/fs2_btn_readme.xpm"
34 #include "res/fs2_btn_readme-hover.xpm"
35 #include "res/fs2_btn_readme-click.xpm"
36 #include "res/fs2_btn_setup.xpm"
37 #include "res/fs2_btn_setup-hover.xpm"
38 #include "res/fs2_btn_setup-click.xpm"
39 #include "res/fs2_btn_uninstall.xpm"
40 #include "res/fs2_btn_uninstall-hover.xpm"
41 #include "res/fs2_btn_uninstall-click.xpm"
42 #include "res/fs2_btn_update.xpm"
43 #include "res/fs2_btn_update-hover.xpm"
44 #include "res/fs2_btn_update-click.xpm"
45 #include "res/fs2_btn_volition.xpm"
46 #include "res/fs2_btn_volition-hover.xpm"
47 #include "res/fs2_btn_volition-click.xpm"
48 #ifdef FS2_DEMO
49 #include "res/fs2demo_help_txt.h"
50 #else
51 #include "res/fs2_help_txt.h"
52 #endif
53 #include "res/fs2_snd_hover_wav.h"
54 #include "res/fs2_snd_click_wav.h"
55 #else
56 #include "res/freespace_img.xpm"
57 #include "res/volition_img.xpm"
58 #endif
59
60
61
62 class LauncherApp: public wxApp
63 {
64         public:
65                 virtual bool OnInit();
66 };
67
68
69 IMPLEMENT_APP(LauncherApp)
70
71 bool LauncherApp::OnInit()
72 {
73 #ifdef PLAT_UNIX
74         // make sure we create files with user access only
75         umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
76 #endif
77
78         Launcher *frame = new Launcher(NULL);
79
80         frame->Show();
81         SetTopWindow(frame);
82
83         frame->JumpToSetup();
84
85         return true;
86 }
87
88 bool wxBackgroundBitmap::ProcessEvent(wxEvent &Event)
89 {
90         if (Event.GetEventType() == wxEVT_ERASE_BACKGROUND) {
91                 wxEraseEvent &EraseEvent = dynamic_cast<wxEraseEvent &>(Event);
92                 wxDC *DC = EraseEvent.GetDC();
93                 DC->DrawBitmap(Bitmap, 0, 0, false);
94
95                 return true;
96         } else {
97                 return Inherited::ProcessEvent(Event);
98         }
99 }
100
101
102 wxBEGIN_EVENT_TABLE(wxLauncherButton, wxStaticBitmap)
103         EVT_LEFT_DOWN(wxLauncherButton::onMouseDown)
104         EVT_LEFT_UP(wxLauncherButton::onMouseUp)
105         EVT_MOTION(wxLauncherButton::onMouseEnter)
106 wxEND_EVENT_TABLE()
107
108
109 wxLauncherButton::wxLauncherButton(wxWindow *parent, wxWindowID id, const wxBitmap& label, const wxPoint& pos, const wxSize& size)
110 {
111         this->Create(parent, id, label, pos, size);
112
113         parent->Connect(wxEVT_MOTION, wxMouseEventHandler(wxLauncherButton::onMouseLeave), NULL, this);
114
115         m_bitmap = label;
116
117         m_in_hover = false;
118 }
119
120 wxLauncherButton::~wxLauncherButton()
121 {
122 }
123
124 void wxLauncherButton::onMouseEnter(wxMouseEvent& event)
125 {
126         if ( !m_in_hover ) {
127                 this->SetBitmap(m_bitmap_hover);
128
129                 ((Launcher*)GetGrandParent())->SndPlayHover();
130
131                 m_in_hover = true;
132
133                 // hack to toggle off certain buttons that don't get the onMouseLeave
134                 // call due to placement/overlap
135                 {
136                         wxMouseEvent mv;
137
138                         const wxWindowList wl = GetParent()->GetChildren();
139
140                         wxWindowList::compatibility_iterator node = wl.GetFirst();
141
142                         while (node) {
143                                 wxLauncherButton *cur = (wxLauncherButton*)node->GetData();
144
145                                 if ( cur->GetId() != event.GetId() ) {
146                                         cur->onMouseLeave(mv);
147                                 }
148
149                                 node = node->GetNext();
150                         }
151                 }
152         }
153
154         event.Skip();
155 }
156
157 void wxLauncherButton::onMouseLeave(wxMouseEvent& event)
158 {
159         if (m_in_hover) {
160                 this->SetBitmap(m_bitmap);
161
162                 m_in_hover = false;
163         }
164
165         event.Skip();
166 }
167
168 void wxLauncherButton::onMouseDown(wxMouseEvent& event)
169 {
170         this->SetBitmap(m_bitmap_pressed);
171
172         ((Launcher*)GetGrandParent())->SndPlayPressed();
173
174         event.Skip();
175 }
176
177 void wxLauncherButton::onMouseUp(wxMouseEvent& event)
178 {
179         this->SetBitmap(m_bitmap_hover);
180
181         wxCommandEvent ev(wxEVT_COMMAND_BUTTON_CLICKED, event.GetId());
182         GetGrandParent()->GetEventHandler()->ProcessEvent(ev);
183
184         event.Skip();
185 }
186
187
188 wxBEGIN_EVENT_TABLE(Launcher, wxDialog)
189         EVT_CLOSE(Launcher::OnClose)
190         EVT_BUTTON(ID_B_PLAY, Launcher::OnPlay)
191         EVT_BUTTON(ID_B_SETUP, Launcher::OnSetup)
192         EVT_BUTTON(ID_B_README, Launcher::OnReadme)
193         EVT_BUTTON(ID_B_UPDATE, Launcher::OnUpdate)
194         EVT_BUTTON(ID_B_HELP, Launcher::OnHelp)
195         EVT_BUTTON(ID_B_UNINSTALL, Launcher::OnUninstall)
196         EVT_BUTTON(ID_B_VOLITION, Launcher::OnVolition)
197         EVT_BUTTON(ID_B_PXO, Launcher::OnPXO)
198         EVT_BUTTON(ID_B_QUIT, Launcher::OnQuit)
199 wxEND_EVENT_TABLE()
200
201
202 Launcher::Launcher( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style )
203         : wxDialog( parent, id, title, pos, size, style )
204 {
205         this->SetBackgroundColour( wxColour( 0, 0, 0 ) );
206
207         use_sound = false;
208
209 #ifndef MAKE_FS1
210         this->SetClientSize(375, 440);
211 #ifdef FS2_DEMO
212         this->SetTitle( wxT("FreeSpace 2 Demo Launcher") );
213 #else
214         this->SetTitle( wxT("FreeSpace 2 Launcher") );
215 #endif
216
217         init_sound();
218
219
220         p_background = new wxBackgroundBitmap(fs2_background_xpm);
221
222         m_panel = new wxPanel(this);
223         m_panel->PushEventHandler(p_background);
224
225
226         m_btn_Play = new wxLauncherButton( m_panel, ID_B_PLAY, wxBitmap(fs2_btn_play_xpm), wxPoint(45, 102), wxSize(131, 58) );
227         m_btn_Play->SetBitmapHover( wxBitmap(fs2_btn_play_hover_xpm) );
228         m_btn_Play->SetBitmapPressed( wxBitmap(fs2_btn_play_click_xpm) );
229
230         m_btn_Setup = new wxLauncherButton( m_panel, ID_B_SETUP, wxBitmap(fs2_btn_setup_xpm), wxPoint(199, 102), wxSize(131, 58) );
231         m_btn_Setup->SetBitmapHover( wxBitmap(fs2_btn_setup_hover_xpm) );
232         m_btn_Setup->SetBitmapPressed( wxBitmap(fs2_btn_setup_click_xpm) );
233
234         m_btn_Readme = new wxLauncherButton( m_panel, ID_B_README, wxBitmap(fs2_btn_readme_xpm), wxPoint(45, 175), wxSize(131, 58) );
235         m_btn_Readme->SetBitmapHover( wxBitmap(fs2_btn_readme_hover_xpm) );
236         m_btn_Readme->SetBitmapPressed( wxBitmap(fs2_btn_readme_click_xpm) );
237
238         m_btn_Update = new wxLauncherButton( m_panel, ID_B_UPDATE, wxBitmap(fs2_btn_update_xpm), wxPoint(199, 175), wxSize(131, 58) );
239         m_btn_Update->SetBitmapHover( wxBitmap(fs2_btn_update_hover_xpm) );
240         m_btn_Update->SetBitmapPressed( wxBitmap(fs2_btn_update_click_xpm) );
241
242         m_btn_Help = new wxLauncherButton( m_panel, ID_B_HELP, wxBitmap(fs2_btn_help_xpm), wxPoint(45, 247), wxSize(131, 58) );
243         m_btn_Help->SetBitmapHover( wxBitmap(fs2_btn_help_hover_xpm) );
244         m_btn_Help->SetBitmapPressed( wxBitmap(fs2_btn_help_click_xpm) );
245
246         m_btn_Uninstall = new wxLauncherButton( m_panel, ID_B_UNINSTALL, wxBitmap(fs2_btn_uninstall_xpm), wxPoint(199, 247), wxSize(131, 58) );
247         m_btn_Uninstall->SetBitmapHover( wxBitmap(fs2_btn_uninstall_hover_xpm) );
248         m_btn_Uninstall->SetBitmapPressed( wxBitmap(fs2_btn_uninstall_click_xpm) );
249
250         m_btn_Volition = new wxLauncherButton( m_panel, ID_B_VOLITION, wxBitmap(fs2_btn_volition_xpm), wxPoint(15, 304), wxSize(90, 108) );
251         m_btn_Volition->SetBitmapHover( wxBitmap(fs2_btn_volition_hover_xpm) );
252         m_btn_Volition->SetBitmapPressed( wxBitmap(fs2_btn_volition_click_xpm) );
253
254         m_btn_PXO = new wxLauncherButton( m_panel, ID_B_PXO, wxBitmap(fs2_btn_pxo_xpm), wxPoint(249, 305), wxSize(114, 113) );
255         m_btn_PXO->SetBitmapHover( wxBitmap(fs2_btn_pxo_hover_xpm) );
256         m_btn_PXO->SetBitmapPressed( wxBitmap(fs2_btn_pxo_click_xpm) );
257
258         m_btn_Quit = new wxLauncherButton( m_panel, ID_B_QUIT, wxBitmap(fs2_btn_quit_xpm), wxPoint(116, 339), wxSize(131, 58) );
259         m_btn_Quit->SetBitmapHover( wxBitmap(fs2_btn_quit_hover_xpm) );
260         m_btn_Quit->SetBitmapPressed( wxBitmap(fs2_btn_quit_click_xpm) );
261 #else
262         this->SetSizeHints( wxDefaultSize, wxDefaultSize );
263 #ifdef FS1_DEMO
264         this->SetTitle( wxT("FreeSpace Demo Launcher") );
265 #else
266         this->SetTitle( wxT("FreeSpace Launcher") );
267 #endif
268
269         wxBoxSizer* bSizer3;
270         bSizer3 = new wxBoxSizer( wxVERTICAL );
271
272         wxStaticBitmap *m_bitmap1 = new wxStaticBitmap( this, wxID_ANY, wxBitmap( freespace_img_xpm ), wxDefaultPosition, wxDefaultSize, 0 );
273         bSizer3->Add( m_bitmap1, 0, wxALIGN_LEFT|wxALIGN_TOP|wxALL, 5 );
274
275         wxFlexGridSizer* fgSizer3;
276         fgSizer3 = new wxFlexGridSizer( 0, 2, 0, 0 );
277         fgSizer3->SetFlexibleDirection( wxBOTH );
278         fgSizer3->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
279
280         wxStaticBitmap *m_bitmap2 = new wxStaticBitmap( this, wxID_ANY, wxBitmap( volition_img_xpm ), wxDefaultPosition, wxDefaultSize, 0 );
281         fgSizer3->Add( m_bitmap2, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
282
283         wxBoxSizer* bSizer5;
284         bSizer5 = new wxBoxSizer( wxVERTICAL );
285
286         m_btn_Play = new wxButton( this, ID_B_PLAY, wxT("Play FreeSpace"), wxDefaultPosition, wxDefaultSize, 0 );
287         m_btn_Play->SetDefault();
288         bSizer5->Add( m_btn_Play, 0, wxALL|wxEXPAND, 5 );
289
290         m_btn_Setup = new wxButton( this, ID_B_SETUP, wxT("Setup"), wxDefaultPosition, wxDefaultSize, 0 );
291         bSizer5->Add( m_btn_Setup, 0, wxALL|wxEXPAND, 5 );
292
293         m_btn_Readme = new wxButton( this, ID_B_README, wxT("View README"), wxDefaultPosition, wxDefaultSize, 0 );
294         bSizer5->Add( m_btn_Readme, 0, wxALL|wxEXPAND, 5 );
295
296         m_btn_Update = new wxButton( this, ID_B_UPDATE, wxT("Update FreeSpace"), wxDefaultPosition, wxDefaultSize, 0 );
297         bSizer5->Add( m_btn_Update, 0, wxALL|wxEXPAND, 5 );
298
299         m_btn_Volition = new wxButton( this, ID_B_VOLITION, wxT("FreeSpace Webpage"), wxDefaultPosition, wxDefaultSize, 0 );
300         bSizer5->Add( m_btn_Volition, 0, wxALL|wxEXPAND, 5 );
301
302         m_btn_Uninstall = new wxButton( this, ID_B_UNINSTALL, wxT("Uninstall"), wxDefaultPosition, wxDefaultSize, 0 );
303         bSizer5->Add( m_btn_Uninstall, 0, wxALL|wxEXPAND, 5 );
304
305         m_btn_Quit = new wxButton( this, ID_B_QUIT, wxT("Quit"), wxDefaultPosition, wxDefaultSize, 0 );
306         bSizer5->Add( m_btn_Quit, 0, wxALL|wxEXPAND, 5 );
307
308         fgSizer3->Add( bSizer5, 1, wxALIGN_CENTER|wxALL, 10 );
309
310         bSizer3->Add( fgSizer3, 1, wxALIGN_BOTTOM|wxALIGN_RIGHT|wxEXPAND, 5 );
311
312         this->SetSizer( bSizer3 );
313         this->Layout();
314         bSizer3->Fit( this );
315 #endif
316
317
318         this->Centre( wxBOTH );
319 }
320
321 Launcher::~Launcher()
322 {
323         close_sound();
324 }
325
326 void Launcher::OnClose( wxCloseEvent& WXUNUSED(event) )
327 {
328 #ifndef MAKE_FS1
329         m_panel->RemoveEventHandler(p_background);
330         delete p_background;
331 #endif
332
333         Destroy();
334 }
335
336 void Launcher::OnPlay( wxCommandEvent& WXUNUSED(event) )
337 {
338         wxString epath = wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath(true);
339
340         epath.Append( wxT("fs") );
341
342 #ifndef MAKE_FS1
343         epath.Append( wxT("2") );
344 #endif
345
346 #if defined(FS1_DEMO) || defined(FS2_DEMO)
347         epath.Append( wxT("demo") );
348 #endif
349
350 #ifdef _WIN32
351         epath.Append( wxT(".exe") );
352 #endif
353
354         wxExecute(epath, wxEXEC_ASYNC | wxEXEC_MAKE_GROUP_LEADER);
355
356         this->Close();
357 }
358
359 void Launcher::OnSetup( wxCommandEvent& WXUNUSED(event) )
360 {
361         LauncherSetup setup(this);
362
363         setup.ShowModal();
364 }
365
366 void Launcher::OnReadme( wxCommandEvent& WXUNUSED(event) )
367 {
368         wxString epath = wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath(true);
369
370         epath.Append( wxT("readme.txt") );
371
372         wxLaunchDefaultApplication(epath);
373 }
374
375 void Launcher::OnUpdate( wxCommandEvent& WXUNUSED(event) )
376 {
377         wxMessageBox( wxT("Not implemented") );
378 }
379
380 void Launcher::OnHelp( wxCommandEvent& WXUNUSED(event) )
381 {
382 #ifndef MAKE_FS1
383         wxDialog *help = new wxDialog(this, wxID_ANY, wxT("Launcher Help"), wxDefaultPosition, wxDefaultSize, wxCAPTION|wxSYSTEM_MENU);
384
385         wxBoxSizer* bSizer;
386         bSizer = new wxBoxSizer( wxVERTICAL );
387
388         // stupid
389         wxSize txtsize = help->GetTextExtent( wxT("  This opens a Help document containing information about the LauncherWWWW") );
390         txtsize.SetHeight(420);
391
392         wxTextCtrl *m_help_txt = new wxTextCtrl( help, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY );
393         m_help_txt->SetMinSize(txtsize);
394 #ifdef FS2_DEMO
395         m_help_txt->AppendText(fs2demo_help_txt);
396 #else
397         m_help_txt->AppendText(fs2_help_txt);
398 #endif
399         m_help_txt->SetInsertionPoint(0);
400         bSizer->Add( m_help_txt, 0, wxALL|wxEXPAND, 5 );
401
402         wxButton *m_b_Ok = new wxButton( help, wxID_OK, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
403         bSizer->Add( m_b_Ok, 0, wxALIGN_RIGHT|wxALL, 5 );
404
405         help->SetSizer( bSizer );
406         help->Layout();
407         bSizer->Fit(help);
408
409         help->Centre( wxBOTH );
410
411         help->ShowModal();
412
413         help->Destroy();
414 #endif
415 }
416
417 void Launcher::OnUninstall( wxCommandEvent& WXUNUSED(event) )
418 {
419         wxMessageBox( wxT("Not implemented") );
420 }
421
422 void Launcher::OnVolition( wxCommandEvent& WXUNUSED(event) )
423 {
424         wxLaunchDefaultBrowser( wxT("http://www.volition-inc.com") );
425 }
426
427 void Launcher::OnPXO( wxCommandEvent& WXUNUSED(event) )
428 {
429         wxLaunchDefaultBrowser( wxT("http://www.pxo.net") );
430 }
431
432 void Launcher::OnQuit( wxCommandEvent& WXUNUSED(event) )
433 {
434         this->Close();
435 }
436
437 void Launcher::JumpToSetup()
438 {
439         if ( !os_config_read_uint(NULL, "StraightToSetup", 1) ) {
440                 return;
441         }
442
443         // FS1 doesn't do a setup jump so just go with what the user sets up
444         // and/or what the game binary will set
445
446 #ifndef MAKE_FS1
447         wxString title( wxT("Welcome to FreeSpace 2!") );
448
449         wxString message( wxT("Since this is your first time running FreeSapce2, ")
450                                           wxT("you will now be automatically taken to the Setup ")
451                                           wxT("window.") );
452
453         wxString ext_message( wxT("NOTE TO USER:\n")
454                                                   wxT("It is important that you view each section of ")
455                                                   wxT("the Setup window and configure it to your ")
456                                                   wxT("liking. Press the Help button if you have ")
457                                                   wxT("questions about a particular section. Once you ")
458                                                   wxT("are satisfied with your settings, select the OK ")
459                                                   wxT("button at the bottom of the Setup window to ")
460                                                   wxT("save them.") );
461
462         wxMessageDialog prompt(this, message, title, wxOK | wxICON_INFORMATION);
463         prompt.SetExtendedMessage(ext_message);
464
465         prompt.ShowModal();
466
467         // now jump to setup dialog
468         LauncherSetup setup(this);
469
470         setup.ShowModal();
471 #endif
472 }
473
474 void Launcher::SndPlayHover()
475 {
476         if (use_sound) {
477                 alSourcePlay(m_snd_hover_source_id);
478         }
479 }
480
481 void Launcher::SndPlayPressed()
482 {
483         if (use_sound) {
484                 alSourcePlay(m_snd_click_source_id);
485         }
486 }
487
488 void Launcher::SndEnable(bool enabled)
489 {
490         if (enabled) {
491                 init_sound();
492         } else {
493                 close_sound();
494         }
495 }
496
497 void Launcher::init_sound()
498 {
499 #ifndef MAKE_FS1
500         if (use_sound) {
501                 return;
502         }
503
504         if ( os_config_read_uint("Audio", "LauncherSoundEnabled", 1) == 0 ) {
505                 return;
506         }
507
508         al_device = alcOpenDevice(NULL);
509
510         if (al_device == NULL) {
511                 return;
512         }
513
514         al_context = alcCreateContext(al_device, NULL);
515
516         if (al_context == NULL) {
517                 alcCloseDevice(al_device);
518                 return;
519         }
520
521         alcMakeContextCurrent(al_context);
522
523         // 'hover' sound
524         alGenBuffers(1, &m_snd_hover_buf_id);
525         alBufferData(m_snd_hover_buf_id, AL_FORMAT_MONO8, fs2_snd_hover_wav, sizeof(fs2_snd_hover_wav), 22050);
526
527         alGenSources(1, &m_snd_hover_source_id);
528         alSourcef(m_snd_hover_source_id, AL_GAIN, 1.0f);
529         alSourcei(m_snd_hover_source_id, AL_BUFFER, m_snd_hover_buf_id);
530
531         // 'click' sound
532         alGenBuffers(1, &m_snd_click_buf_id);
533         alBufferData(m_snd_click_buf_id, AL_FORMAT_MONO8, fs2_snd_click_wav, sizeof(fs2_snd_click_wav), 22050);
534
535         alGenSources(1, &m_snd_click_source_id);
536         alSourcef(m_snd_click_source_id, AL_GAIN, 1.0f);
537         alSourcei(m_snd_click_source_id, AL_BUFFER, m_snd_click_buf_id);
538
539         use_sound = true;
540 #endif
541 }
542
543 void Launcher::close_sound()
544 {
545         if ( !use_sound ) {
546                 return;
547         }
548
549         alSourceStop(m_snd_click_source_id);
550
551         alSourcei(m_snd_click_source_id, AL_BUFFER, 0);
552         alDeleteSources(1, &m_snd_click_source_id);
553         alDeleteBuffers(1, &m_snd_click_buf_id);
554
555         alSourceStop(m_snd_hover_source_id);
556
557         alSourcei(m_snd_hover_source_id, AL_BUFFER, 0);
558         alDeleteSources(1, &m_snd_hover_source_id);
559         alDeleteBuffers(1, &m_snd_hover_buf_id);
560
561         alcMakeContextCurrent(NULL);
562         alcDestroyContext(al_context);
563         alcCloseDevice(al_device);
564
565         use_sound = false;
566 }