comment/explain a lot
[wxWidgets.git] / samples / mediaplayer / mediaplayer.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: mediactrltest.
3 // Purpose: wxMediaCtrl sample
4 // Author: Ryan Norton
5 // Modified by:
6 // Created: 11/10/04
7 // RCS-ID: $Id$
8 // Copyright: (c) Ryan Norton
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #ifndef WX_PRECOMP
27 #include "wx/wx.h"
28 #endif
29
30 // ----------------------------------------------------------------------------
31 // resources
32 // ----------------------------------------------------------------------------
33
34 #include "wx/mediactrl.h" //for wxMediaCtrl
35 #include "wx/filedlg.h" //for opening files from OpenFile
36 #include "wx/slider.h" //for a slider for seeking within media
37 #include "wx/sizer.h" //for positioning controls/wxBoxSizer
38 #include "wx/timer.h" //timer for updating status bar
39 #include "wx/textdlg.h" //for getting user text from OpenURL
40
41
42 #if !wxUSE_MEDIACTRL
43 #error "wxUSE_MEDIACTRL must be enabled to use this sample!"
44 #endif
45
46 // ----------------------------------------------------------------------------
47 // Declarations
48 // ----------------------------------------------------------------------------
49
50 class MyApp : public wxApp
51 {
52 public:
53 virtual bool OnInit();
54 };
55
56 class MyFrame : public wxFrame
57 {
58 public:
59 // ctor(s)
60 MyFrame(const wxString& title);
61 ~MyFrame();
62
63 // event handlers (these functions should _not_ be virtual)
64 void OnQuit(wxCommandEvent& event);
65 void OnAbout(wxCommandEvent& event);
66 void OnLoop(wxCommandEvent& event);
67
68 void OnOpenFile(wxCommandEvent& event);
69 void OnOpenURL(wxCommandEvent& event);
70
71 void OnPlay(wxCommandEvent& event);
72 void OnPause(wxCommandEvent& event);
73 void OnStop(wxCommandEvent& event);
74
75 void OnSeek(wxCommandEvent& event);
76
77 void OnMediaFinished(wxMediaEvent& event);
78
79 private:
80 void ResetStatus();
81
82 wxMediaCtrl* m_mediactrl;
83 wxSlider* m_slider;
84 wxBoxSizer* m_sizer;
85 class MyTimer* m_timer;
86 friend class MyTimer;
87 wxString m_basestatus;
88
89 bool m_bLoop;
90
91 // any class wishing to process wxWidgets events must use this macro
92 DECLARE_EVENT_TABLE()
93 };
94
95 //
96 //ResetStatus
97 //-----------
98 //Here we just make a simple status string
99 //with some useful info about the media
100 //We display info here in seconds (wxMediaCtrl
101 //uses milliseconds - that's why we divide by 1000)
102 //
103 void MyFrame::ResetStatus()
104 {
105 m_basestatus = wxString::Format(_T("Size(x,y):%i,%i Length(Seconds):%u Speed:%1.1fx"),
106 m_mediactrl->GetBestSize().x,
107 m_mediactrl->GetBestSize().y,
108 m_mediactrl->GetDuration() / 1000,
109 m_mediactrl->GetPlaybackRate()
110 );
111
112 m_slider->SetRange(0, m_mediactrl->GetDuration() / 1000);
113 }
114
115 //
116 //wxGetMediaStateText
117 //-------------------
118 //Converts a wxMediaCtrl state into something
119 //useful that we can display
120 //
121 const wxChar* wxGetMediaStateText(int nState)
122 {
123 switch(nState)
124 {
125 case wxMEDIASTATE_PLAYING:
126 return wxT("Playing");
127 case wxMEDIASTATE_STOPPED:
128 return wxT("Stopped");
129 ///case wxMEDIASTATE_PAUSED:
130 default:
131 return wxT("Paused");
132 }
133 }
134
135 class MyTimer : public wxTimer
136 {
137 public:
138 MyTimer(MyFrame* frame) {m_frame = frame;}
139
140 //
141 //Notify
142 //-----------
143 //Updates the main frame's status bar with the current
144 //position within the media and state the media is in
145 //
146 void Notify()
147 {
148 long lPosition = m_frame->m_mediactrl->GetPosition() / 1000;
149 m_frame->m_slider->SetValue(lPosition);
150
151
152 m_frame->SetStatusText(wxString::Format(_T("%s Pos:%u State:%s"),
153 m_frame->m_basestatus.c_str(),
154 lPosition,
155 wxGetMediaStateText(m_frame->m_mediactrl->GetState())
156 )
157 );
158
159 }
160
161 MyFrame* m_frame;
162 };
163
164
165 // ----------------------------------------------------------------------------
166 // constants
167 // ----------------------------------------------------------------------------
168
169 // IDs for the controls and the menu commands
170 enum
171 {
172 // menu items
173 Minimal_Quit = wxID_EXIT,
174 Minimal_Loop,
175 Minimal_OpenFile,
176 Minimal_OpenURL,
177 Minimal_Play,
178 Minimal_Pause,
179 Minimal_Stop,
180 Minimal_About = wxID_ABOUT,
181
182 // id for our slider
183 Minimal_Slider = 1,
184
185 // id for our wxMediaCtrl
186 Minimal_Media
187 };
188
189 // ----------------------------------------------------------------------------
190 // event tables and other macros for wxWidgets
191 // ----------------------------------------------------------------------------
192
193 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
194 //Menu events
195 EVT_MENU(Minimal_Quit, MyFrame::OnQuit)
196 EVT_MENU(Minimal_About, MyFrame::OnAbout)
197 EVT_MENU(Minimal_Loop, MyFrame::OnLoop)
198 EVT_MENU(Minimal_OpenFile, MyFrame::OnOpenFile)
199 EVT_MENU(Minimal_OpenURL, MyFrame::OnOpenURL)
200 EVT_MENU(Minimal_Play, MyFrame::OnPlay)
201 EVT_MENU(Minimal_Pause, MyFrame::OnPause)
202 EVT_MENU(Minimal_Stop, MyFrame::OnStop)
203
204 //Slider events
205 EVT_SLIDER(Minimal_Slider, MyFrame::OnSeek)
206
207 //wxMediaCtrl events
208 EVT_MEDIA_FINISHED(Minimal_Media, MyFrame::OnMediaFinished)
209 END_EVENT_TABLE()
210
211 //main/WinMain()
212 IMPLEMENT_APP(MyApp)
213
214 // ============================================================================
215 // implementation
216 // ============================================================================
217
218 // ----------------------------------------------------------------------------
219 // MyApp
220 // ----------------------------------------------------------------------------
221
222 // 'Main program' equivalent: the program execution "starts" here
223 bool MyApp::OnInit()
224 {
225 MyFrame *frame = new MyFrame(_T("Minimal wxWidgets App"));
226 frame->Show(true);
227
228 return true;
229 }
230
231 // ----------------------------------------------------------------------------
232 // main frame
233 // ----------------------------------------------------------------------------
234
235 //
236 //MyFrame
237 //-------
238 //Creates our menus and controls
239 //
240 MyFrame::MyFrame(const wxString& title)
241 : wxFrame(NULL, wxID_ANY, title), m_timer(NULL)
242 {
243 //
244 // Create Menus
245 //
246 #if wxUSE_MENUS
247 wxMenu *menuFile = new wxMenu;
248
249 wxMenu *helpMenu = new wxMenu;
250 helpMenu->Append(Minimal_About, _T("&About...\tF1"), _T("Show about dialog"));
251
252 menuFile->Append(Minimal_OpenFile, _T("&Open File"), _T("Open a File"));
253 menuFile->Append(Minimal_OpenURL, _T("Open &URL"), _T("Open a URL"));
254 menuFile->AppendSeparator();
255 menuFile->Append(Minimal_Play, _T("&Play"), _T("Resume playback"));
256 menuFile->Append(Minimal_Pause, _T("P&ause"), _T("Pause playback"));
257 menuFile->Append(Minimal_Stop, _T("&Stop"), _T("Stop playback"));
258 menuFile->AppendSeparator();
259 menuFile->AppendCheckItem(Minimal_Loop, _T("&Loop"), _T("Loop Selected Media"));
260 menuFile->AppendSeparator();
261 menuFile->Append(Minimal_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
262
263 wxMenuBar *menuBar = new wxMenuBar();
264 menuBar->Append(menuFile, _T("&File"));
265 menuBar->Append(helpMenu, _T("&Help"));
266
267 SetMenuBar(menuBar);
268 #endif // wxUSE_MENUS
269
270 //
271 // Create and attach the first/main sizer
272 //
273
274 m_sizer = new wxBoxSizer(wxVERTICAL);
275 this->SetSizer(m_sizer);
276 this->SetAutoLayout(true);
277
278 //
279 // Create our media control
280 //
281
282 m_mediactrl = new wxMediaCtrl(this, Minimal_Media, wxT(""));
283 m_sizer->Add(m_mediactrl, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
284
285 //
286 // Create our slider
287 //
288
289 m_slider = new wxSlider(this, Minimal_Slider, 0, //init
290 0, //start
291 0, //end
292 wxDefaultPosition, wxDefaultSize,
293 wxSL_HORIZONTAL );
294 m_sizer->Add(m_slider, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5);
295
296
297 //
298 // Create the second sizer which will position things
299 // vertically -
300 //
301 // -------Menu----------
302 // [m_mediactrl]
303 //
304 // [m_slider]
305 //
306
307 wxBoxSizer* horzsizer = new wxBoxSizer(wxHORIZONTAL);
308 m_sizer->Add(horzsizer, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
309
310 //
311 // We arn't looping initially
312 //
313
314 m_bLoop = false;
315
316 //
317 // Create our status bar
318 //
319 #if wxUSE_STATUSBAR
320 // create a status bar just for fun (by default with 1 pane only)
321 CreateStatusBar(1);
322 ResetStatus();
323 SetStatusText(m_basestatus);
324 #endif // wxUSE_STATUSBAR
325
326 //
327 // Create a timer to update our status bar
328 //
329
330 m_timer = new MyTimer(this);
331 m_timer->Start(100);
332 }
333
334 //
335 //~MyFrame
336 //-------
337 //Deletes child objects implicitly and our timer explicitly
338 //
339 MyFrame::~MyFrame()
340 {
341 delete m_timer;
342 }
343
344 //
345 //OnQuit
346 //-------
347 //Called from file->quit.
348 //Closes this application.
349 //
350 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
351 {
352 // true is to force the frame to close
353 Close(true);
354 }
355
356 //
357 //OnAbout
358 //-------
359 //Called from help->about.
360 //Gets some info about this application.
361 //
362 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
363 {
364 wxString msg;
365 msg.Printf( _T("This is a test of wxMediaCtrl.\n")
366 _T("Welcome to %s"), wxVERSION_STRING);
367
368 wxMessageBox(msg, _T("About wxMediaCtrl test"), wxOK | wxICON_INFORMATION, this);
369 }
370
371 //
372 //OnLoop
373 //-------
374 //Called from file->loop.
375 //Changes the state of whether we want to loop or not.
376 //
377 void MyFrame::OnLoop(wxCommandEvent& WXUNUSED(event))
378 {
379 m_bLoop = !m_bLoop;
380 }
381
382 //
383 //OnOpenFile
384 //-------
385 //Called from file->openfile.
386 //Opens and plays a media file
387 //
388 void MyFrame::OnOpenFile(wxCommandEvent& WXUNUSED(event))
389 {
390 wxFileDialog fd(this);
391
392 if(fd.ShowModal() == wxID_OK)
393 {
394 if( !m_mediactrl->Load(fd.GetPath()) )
395 wxMessageBox(wxT("Couldn't load file!"));
396
397 if( !m_mediactrl->Play() )
398 wxMessageBox(wxT("Couldn't play movie!"));
399
400 ResetStatus();
401 }
402 }
403
404
405 //
406 //OnOpenURL
407 //-------
408 //Called from file->openurl.
409 //Opens a URL.
410 //Windows DirectShow only.
411 //
412 void MyFrame::OnOpenURL(wxCommandEvent& WXUNUSED(event))
413 {
414 wxString theURL = wxGetTextFromUser(wxT("Enter the URL that has the movie to play"));
415
416 #if defined(__WXMSW__) && wxUSE_DIRECTSHOW
417 if(!theURL.empty())
418 {
419 if( !m_mediactrl->Load(wxURI(theURL)) )
420 wxMessageBox(wxT("Couldn't load URL!"));
421
422 if( !m_mediactrl->Play() )
423 wxMessageBox(wxT("Couldn't play movie!"));
424
425 ResetStatus();
426 }
427 #else
428 wxMessageBox(wxT("Not supported!"));
429 #endif
430 }
431
432 //
433 //OnPlay
434 //-------
435 //Called from file->play.
436 //Resumes the media if it is paused or stopped.
437 //
438 void MyFrame::OnPlay(wxCommandEvent& WXUNUSED(event))
439 {
440 if( !m_mediactrl->Play() )
441 wxMessageBox(wxT("Couldn't play movie!"));
442 }
443
444 //
445 //OnPause
446 //-------
447 //Called from file->pause.
448 //Pauses the media in-place.
449 //
450 void MyFrame::OnPause(wxCommandEvent& WXUNUSED(event))
451 {
452 if( !m_mediactrl->Pause() )
453 wxMessageBox(wxT("Couldn't pause movie!"));
454 }
455
456 //
457 //OnStop
458 //-------
459 //Called from file->stop.
460 //Note that where the media stops is undefined -
461 //it could stop at the end or beginning.
462 //
463 void MyFrame::OnStop(wxCommandEvent& WXUNUSED(event))
464 {
465 if( !m_mediactrl->Stop() )
466 wxMessageBox(wxT("Couldn't stop movie!"));
467 }
468
469 //
470 //OnSeek
471 //-------
472 //Called from file->seek.
473 //Called when the user moves the slider -
474 //seeks to a position within the media
475 //
476 void MyFrame::OnSeek(wxCommandEvent& WXUNUSED(event))
477 {
478 if( !m_mediactrl->SetPosition( m_slider->GetValue() * 1000 ) )
479 wxMessageBox(wxT("Couldn't seek in movie!"));
480 }
481
482 //
483 //OnMediaFinished
484 //-------
485 //Called when the media stops playing.
486 //Here we loop it if the user wants to (has been selected from file menu)
487 //
488 void MyFrame::OnMediaFinished(wxMediaEvent& WXUNUSED(event))
489 {
490 if(m_bLoop)
491 {
492 if ( !m_mediactrl->SetPosition(0) || !m_mediactrl->Play() )
493 wxMessageBox(wxT("Couldn't seek or play to loop movie!"));
494 }
495 }