Warning fix.
[wxWidgets.git] / samples / mediaplayer / mediaplayer.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: mediaplayer.cpp
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 // MediaPlayer
14 //
15 // This is a simple example of how to use all the funtionality of
16 // the wxMediaCtrl class in wxWidgets.
17 //
18 // To use this sample, simply select Open File from the file menu,
19 // select the file you want to play - and MediaPlayer will play the file in a
20 // new notebook page, showing video if neccessary.
21 //
22 // You can select one of the menu options, or move the slider around
23 // to manipulate what is playing.
24 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
25
26 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
27 // Known bugs with wxMediaCtrl:
28 //
29 // 1) Certain backends can't play the same media file at the same time (MCI,
30 // Cocoa NSMovieView-Quicktime).
31 // 2) Positioning on Mac Carbon is messed up if put in a sub-control like a
32 // Notebook (like this sample does) on OS versions < 10.2.
33 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34
35 // ============================================================================
36 // Definitions
37 // ============================================================================
38
39 // ----------------------------------------------------------------------------
40 // Pre-compiled header stuff
41 // ----------------------------------------------------------------------------
42
43 #include "wx/wxprec.h"
44
45 #ifdef __BORLANDC__
46 #pragma hdrstop
47 #endif
48
49 #ifndef WX_PRECOMP
50 #include "wx/wx.h"
51 #endif
52
53 // ----------------------------------------------------------------------------
54 // Headers
55 // ----------------------------------------------------------------------------
56
57 #include "wx/mediactrl.h" //for wxMediaCtrl
58 #include "wx/filedlg.h" //for opening files from OpenFile
59 #include "wx/slider.h" //for a slider for seeking within media
60 #include "wx/sizer.h" //for positioning controls/wxBoxSizer
61 #include "wx/timer.h" //timer for updating status bar
62 #include "wx/textdlg.h" //for getting user text from OpenURL
63 #include "wx/notebook.h" //for wxNotebook and putting movies in pages
64
65 // Use some stuff that's not part of the current API, such as loading
66 // media from a URL, etc.
67 #define wxUSE_UNOFFICIALSTUFF 0
68
69 //Libraries for MSVC with optional backends
70 #ifdef _MSC_VER
71 #if wxUSE_DIRECTSHOW
72 #pragma comment(lib,"strmiids.lib")
73 #endif
74 #if wxUSE_QUICKTIME
75 #pragma comment(lib,"qtmlClient.lib")
76 #endif
77 #endif
78
79 // ----------------------------------------------------------------------------
80 // Bail out if the user doesn't want one of the
81 // things we need
82 // ----------------------------------------------------------------------------
83
84 #if !wxUSE_GUI
85 #error "This is a GUI sample"
86 #endif
87
88 #if !wxUSE_MEDIACTRL || !wxUSE_MENUS || !wxUSE_SLIDER || !wxUSE_TIMER || !wxUSE_NOTEBOOK
89 #error "menus, slider, mediactrl, notebook, and timers must all be enabled for this sample!"
90 #endif
91
92 // ============================================================================
93 // Declarations
94 // ============================================================================
95
96 // ----------------------------------------------------------------------------
97 // Enumurations
98 // ----------------------------------------------------------------------------
99
100 // IDs for the controls and the menu commands
101 enum
102 {
103 // menu items
104 wxID_LOOP = 1,
105 wxID_OPENFILESAMEPAGE,
106 wxID_OPENFILENEWPAGE,
107 wxID_OPENURLSAMEPAGE,
108 wxID_OPENURLNEWPAGE,
109 wxID_CLOSECURRENTPAGE,
110 wxID_PLAY,
111 wxID_PAUSE,
112 // wxID_STOP, [built-in to wxWidgets]
113 // wxID_ABOUT, [built-in to wxWidgets]
114 // wxID_EXIT, [built-in to wxWidgets]
115
116 // event id for our slider
117 wxID_SLIDER,
118
119 // event id for our notebook
120 wxID_NOTEBOOK,
121
122 // event id for our wxMediaCtrl
123 wxID_MEDIACTRL
124 };
125
126 // ----------------------------------------------------------------------------
127 // MyApp
128 // ----------------------------------------------------------------------------
129
130 class MyApp : public wxApp
131 {
132 public:
133 virtual bool OnInit();
134 };
135
136 // ----------------------------------------------------------------------------
137 // MyFrame
138 // ----------------------------------------------------------------------------
139
140 class MyFrame : public wxFrame
141 {
142 public:
143 // Ctor/Dtor
144 MyFrame(const wxString& title);
145 ~MyFrame();
146
147 // Menu event handlers
148 void OnQuit(wxCommandEvent& event);
149 void OnAbout(wxCommandEvent& event);
150 void OnLoop(wxCommandEvent& event);
151
152 void OnOpenFileSamePage(wxCommandEvent& event);
153 void OnOpenFileNewPage(wxCommandEvent& event);
154 void OnOpenURLSamePage(wxCommandEvent& event);
155 void OnOpenURLNewPage(wxCommandEvent& event);
156 void OnCloseCurrentPage(wxCommandEvent& event);
157
158 void OnPlay(wxCommandEvent& event);
159 void OnPause(wxCommandEvent& event);
160 void OnStop(wxCommandEvent& event);
161
162 // Notebook event handlers
163 void OnPageChange(wxNotebookEvent& event);
164
165 private:
166 // Rebuild base status string (see Implementation)
167 void ResetStatus();
168
169 // Common open file code
170 void OpenFile(bool bNewPage);
171 void OpenURL(bool bNewPage);
172
173 // Get the media control and slider of current notebook page
174 wxMediaCtrl* GetCurrentMediaCtrl();
175 wxSlider* GetCurrentSlider();
176
177 class MyTimer* m_timer; //Timer to write info to status bar
178 wxString m_basestatus; //Base status string (see ResetStatus())
179 wxNotebook* m_notebook;
180
181 // So that mytimer can access MyFrame's members
182 friend class MyTimer;
183 };
184
185
186
187 // ----------------------------------------------------------------------------
188 // MyNotebookPage
189 // ----------------------------------------------------------------------------
190
191 class MyNotebookPage : public wxPanel
192 {
193 MyNotebookPage(wxNotebook* book);
194
195 // Slider event handlers
196 void OnSeek(wxCommandEvent& event);
197
198 // Media event handlers
199 void OnMediaFinished(wxMediaEvent& event);
200
201 public:
202 friend class MyFrame; //make MyFrame able to access private members
203 wxMediaCtrl* m_mediactrl; //Our media control
204 wxSlider* m_slider; //The slider below our media control
205 int m_nLoops; //Number of times media has looped
206 bool m_bLoop; //Whether we are looping or not
207 };
208
209 // ----------------------------------------------------------------------------
210 // MyTimer
211 // ----------------------------------------------------------------------------
212
213 class MyTimer : public wxTimer
214 {
215 public:
216 //Ctor
217 MyTimer(MyFrame* frame) {m_frame = frame;}
218
219 //Called each time the timer's timeout expires
220 void Notify();
221
222 MyFrame* m_frame; //The MyFrame
223 };
224
225 // ============================================================================
226 //
227 // Implementation
228 //
229 // ============================================================================
230
231 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
232 //
233 // [Functions]
234 //
235 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
236
237 // ----------------------------------------------------------------------------
238 // wxGetMediaStateText
239 //
240 // Converts a wxMediaCtrl state into something useful that we can display
241 // to the user
242 // ----------------------------------------------------------------------------
243 const wxChar* wxGetMediaStateText(int nState)
244 {
245 switch(nState)
246 {
247 case wxMEDIASTATE_PLAYING:
248 return wxT("Playing");
249 case wxMEDIASTATE_STOPPED:
250 return wxT("Stopped");
251 ///case wxMEDIASTATE_PAUSED:
252 default:
253 return wxT("Paused");
254 }
255 }
256
257 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
258 //
259 // MyApp
260 //
261 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
262
263 // ----------------------------------------------------------------------------
264 // This sets up this wxApp as the global wxApp that gui calls in wxWidgets
265 // use. For example, if you were to be in windows and use a file dialog,
266 // wxWidgets would use wxTheApp->GetHInstance() which would get the instance
267 // handle of the application. These routines in wx _DO NOT_ check to see if
268 // the wxApp exists, and thus will crash the application if you try it.
269 //
270 // IMPLEMENT_APP does this, and also implements the platform-specific entry
271 // routine, such as main or WinMain(). Use IMPLEMENT_APP_NO_MAIN if you do
272 // not desire this behavior.
273 // ----------------------------------------------------------------------------
274 IMPLEMENT_APP(MyApp)
275
276
277 // ----------------------------------------------------------------------------
278 // MyApp::OnInit
279 //
280 // Where execution starts - akin to a main or WinMain.
281 // 1) Create the frame and show it to the user
282 // 2) return true specifying that we want execution to continue past OnInit
283 // ----------------------------------------------------------------------------
284 bool MyApp::OnInit()
285 {
286 MyFrame *frame = new MyFrame(_T("MediaPlayer wxWidgets Sample"));
287 frame->Show(true);
288
289 return true;
290 }
291
292
293 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
294 //
295 // MyFrame
296 //
297 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
298
299 // ----------------------------------------------------------------------------
300 // MyFrame Constructor
301 //
302 // 1) Create our menus
303 // 2) Create our notebook control and add it to the frame
304 // 3) Create our status bar
305 // 4) Connect our events
306 // 5) Start our timer
307 // ----------------------------------------------------------------------------
308
309 MyFrame::MyFrame(const wxString& title)
310 : wxFrame(NULL, wxID_ANY, title)
311 {
312 //
313 // Create Menus
314 //
315 wxMenu *menuFile = new wxMenu;
316
317 wxMenu *helpMenu = new wxMenu;
318 helpMenu->Append(wxID_ABOUT,
319 _T("&About...\tF1"),
320 _T("Show about dialog"));
321
322 menuFile->Append(wxID_OPENFILESAMEPAGE, _T("&Open File"),
323 _T("Open a File in the current notebook page"));
324 menuFile->Append(wxID_OPENFILENEWPAGE, _T("&Open File in a new page"),
325 _T("Open a File in a new notebook page"));
326 #if wxUSE_UNOFFICIALSTUFF
327 menuFile->Append(wxID_OPENURLSAMEPAGE, _T("&Open URL"),
328 _T("Open a URL in the current notebook page"));
329 menuFile->Append(wxID_OPENURLNEWPAGE, _T("&Open URL in a new page"),
330 _T("Open a URL in a new notebook page"));
331 #endif
332 menuFile->AppendSeparator();
333 menuFile->Append(wxID_CLOSECURRENTPAGE, _T("&Close Current Page"),
334 _T("Close current notebook page"));
335 menuFile->AppendSeparator();
336 menuFile->Append(wxID_PLAY, _T("&Play"), _T("Resume playback"));
337 menuFile->Append(wxID_PAUSE, _T("P&ause"), _T("Pause playback"));
338 menuFile->Append(wxID_STOP, _T("&Stop"), _T("Stop playback"));
339 menuFile->AppendSeparator();
340 menuFile->AppendCheckItem(wxID_LOOP,
341 _T("&Loop"),
342 _T("Loop Selected Media"));
343 menuFile->AppendSeparator();
344 menuFile->Append(wxID_EXIT,
345 _T("E&xit\tAlt-X"),
346 _T("Quit this program"));
347
348 wxMenuBar *menuBar = new wxMenuBar();
349 menuBar->Append(menuFile, _T("&File"));
350 menuBar->Append(helpMenu, _T("&Help"));
351
352 SetMenuBar(menuBar);
353
354 //
355 // Create our notebook - using wxNotebook is luckily pretty
356 // simple and self-explanatory in most cases
357 //
358 m_notebook = new wxNotebook(this, wxID_NOTEBOOK);
359
360 //
361 // Create our status bar
362 //
363 #if wxUSE_STATUSBAR
364 // create a status bar just for fun (by default with 1 pane only)
365 CreateStatusBar(1);
366 #endif // wxUSE_STATUSBAR
367
368 //
369 // Connect events.
370 //
371 // There are two ways in wxWidgets to use events -
372 // Message Maps and Connections.
373 //
374 // Message Maps are implemented by putting
375 // DECLARE_MESSAGE_MAP in your wxEvtHandler-derived
376 // class you want to use for events, such as MyFrame.
377 //
378 // Then after your class declaration you put
379 // BEGIN_EVENT_TABLE(MyFrame, wxFrame)
380 // EVT_XXX(XXX)...
381 // END_EVENT_TABLE()
382 //
383 // Where MyFrame is the class with the DECLARE_MESSAGE_MAP
384 // in it. EVT_XXX(XXX) are each of your handlers, such
385 // as EVT_MENU for menu events and the XXX inside
386 // is the parameters to the event macro - in the case
387 // of EVT_MENU the menu id and then the function to call.
388 //
389 // However, with wxEvtHandler::Connect you can avoid a
390 // global message map for your class and those annoying
391 // macros. You can also change the context in which
392 // the call the handler (more later).
393 //
394 // The downside is that due to the limitation that
395 // wxWidgets doesn't use templates in certain areas,
396 // You have to triple-cast the event function.
397 //
398 // There are five parameters to wxEvtHandler::Connect -
399 //
400 // The first is the id of the instance whose events
401 // you want to handle - i.e. a menu id for menus,
402 // a control id for controls (wxControl::GetId())
403 // and so on.
404 //
405 // The second is the event id. This is the same
406 // as the message maps (EVT_MENU) except prefixed
407 // with "wx" (wxEVT_MENU).
408 //
409 // The third is the function handler for the event -
410 // You need to cast it to the specific event handler
411 // type, then to a wxEventFunction, then to a
412 // wxObjectEventFunction - I.E.
413 // (wxObjectEventFunction)(wxEventFunction)
414 // (wxCommandEventFunction) &MyFrame::MyHandler
415 //
416 // The fourth is an optional userdata param -
417 // this is of historical relevance only and is
418 // there only for backwards compatibility.
419 //
420 // The fifth is the context in which to call the
421 // handler - by default (this param is optional)
422 // this. For example in your event handler
423 // if you were to call "this->MyFunc()"
424 // it would literally do this->MyFunc. However,
425 // if you were to pass myHandler as the fifth
426 // parameter, for instance, you would _really_
427 // be calling myHandler->MyFunc, even though
428 // the compiler doesn't really know it.
429 //
430
431 //
432 // Menu events
433 //
434 this->Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED,
435 (wxObjectEventFunction) (wxEventFunction)
436 (wxCommandEventFunction) &MyFrame::OnQuit);
437
438 this->Connect(wxID_ABOUT, wxEVT_COMMAND_MENU_SELECTED,
439 (wxObjectEventFunction) (wxEventFunction)
440 (wxCommandEventFunction) &MyFrame::OnAbout);
441
442 this->Connect(wxID_LOOP, wxEVT_COMMAND_MENU_SELECTED,
443 (wxObjectEventFunction) (wxEventFunction)
444 (wxCommandEventFunction) &MyFrame::OnLoop);
445
446 this->Connect(wxID_OPENFILENEWPAGE, wxEVT_COMMAND_MENU_SELECTED,
447 (wxObjectEventFunction) (wxEventFunction)
448 (wxCommandEventFunction) &MyFrame::OnOpenFileNewPage);
449
450 this->Connect(wxID_OPENFILESAMEPAGE, wxEVT_COMMAND_MENU_SELECTED,
451 (wxObjectEventFunction) (wxEventFunction)
452 (wxCommandEventFunction) &MyFrame::OnOpenFileSamePage);
453
454 this->Connect(wxID_OPENURLNEWPAGE, wxEVT_COMMAND_MENU_SELECTED,
455 (wxObjectEventFunction) (wxEventFunction)
456 (wxCommandEventFunction) &MyFrame::OnOpenURLNewPage);
457
458 this->Connect(wxID_OPENURLSAMEPAGE, wxEVT_COMMAND_MENU_SELECTED,
459 (wxObjectEventFunction) (wxEventFunction)
460 (wxCommandEventFunction) &MyFrame::OnOpenURLSamePage);
461
462 this->Connect(wxID_CLOSECURRENTPAGE, wxEVT_COMMAND_MENU_SELECTED,
463 (wxObjectEventFunction) (wxEventFunction)
464 (wxCommandEventFunction) &MyFrame::OnCloseCurrentPage);
465
466 this->Connect(wxID_PLAY, wxEVT_COMMAND_MENU_SELECTED,
467 (wxObjectEventFunction) (wxEventFunction)
468 (wxCommandEventFunction) &MyFrame::OnPlay);
469
470 this->Connect(wxID_PAUSE, wxEVT_COMMAND_MENU_SELECTED,
471 (wxObjectEventFunction) (wxEventFunction)
472 (wxCommandEventFunction) &MyFrame::OnPause);
473
474 this->Connect(wxID_STOP, wxEVT_COMMAND_MENU_SELECTED,
475 (wxObjectEventFunction) (wxEventFunction)
476 (wxCommandEventFunction) &MyFrame::OnStop);
477
478 //
479 // Notebook events
480 //
481 this->Connect(wxID_NOTEBOOK, wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
482 (wxObjectEventFunction) (wxEventFunction)
483 (wxNotebookEventFunction) &MyFrame::OnPageChange);
484
485 //
486 // End of Events
487 //
488
489 //
490 // Create a timer to update our status bar
491 //
492 m_timer = new MyTimer(this);
493 m_timer->Start(100);
494 }
495
496 // ----------------------------------------------------------------------------
497 // MyFrame Destructor
498 //
499 // 1) Deletes child objects implicitly
500 // 2) Delete our timer explicitly
501 // ----------------------------------------------------------------------------
502 MyFrame::~MyFrame()
503 {
504 delete m_timer;
505 }
506
507 // ----------------------------------------------------------------------------
508 // MyFrame::ResetStatus
509 //
510 // Here we just make a simple status string with some useful info about
511 // the media that we won't change later - such as the length of the media.
512 //
513 // We then append some other info that changes in MyTimer::Notify, then
514 // set the status bar to this text.
515 //
516 // In real applications, you'd want to find a better way to do this,
517 // such as static text controls (wxStaticText).
518 //
519 // We display info here in seconds (wxMediaCtrl uses milliseconds - that's why
520 // we divide by 1000).
521 //
522 // We also reset our loop counter here.
523 // ----------------------------------------------------------------------------
524 void MyFrame::ResetStatus()
525 {
526 wxMediaCtrl* currentMediaCtrl = GetCurrentMediaCtrl();
527
528 m_basestatus = wxString::Format(_T("Size(x,y):%i,%i ")
529 _T("Length(Seconds):%u Speed:%1.1fx"),
530 currentMediaCtrl->GetBestSize().x,
531 currentMediaCtrl->GetBestSize().y,
532 (unsigned)((currentMediaCtrl->Length() / 1000)),
533 currentMediaCtrl->GetPlaybackRate()
534 );
535 }
536
537 // ----------------------------------------------------------------------------
538 // MyFrame::GetCurrentMediaCtrl
539 //
540 // Obtains the media control of the current page, or NULL if there are no
541 // pages open
542 // ----------------------------------------------------------------------------
543 wxMediaCtrl* MyFrame::GetCurrentMediaCtrl()
544 {
545 wxASSERT(m_notebook->GetCurrentPage() != NULL);
546 return ((MyNotebookPage*)m_notebook->GetCurrentPage())->m_mediactrl;
547 }
548
549 // ----------------------------------------------------------------------------
550 // MyFrame::GetCurrentSlider
551 //
552 // Obtains the slider of the current page, or NULL if there are no
553 // pages open
554 // ----------------------------------------------------------------------------
555 wxSlider* MyFrame::GetCurrentSlider()
556 {
557 wxASSERT(m_notebook->GetCurrentPage() != NULL);
558 return ((MyNotebookPage*)m_notebook->GetCurrentPage())->m_slider;
559 }
560
561 // ----------------------------------------------------------------------------
562 // MyFrame::OnQuit
563 //
564 // Called from file->quit.
565 // Closes this application.
566 // ----------------------------------------------------------------------------
567 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
568 {
569 // true is to force the frame to close
570 Close(true);
571 }
572
573 // ----------------------------------------------------------------------------
574 // MyFrame::OnAbout
575 //
576 // Called from help->about.
577 // Gets some info about this application.
578 // ----------------------------------------------------------------------------
579 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
580 {
581 wxString msg;
582 msg.Printf( _T("This is a test of wxMediaCtrl.\n")
583 _T("Welcome to %s"), wxVERSION_STRING);
584
585 wxMessageBox(msg, _T("About wxMediaCtrl test"), wxOK | wxICON_INFORMATION, this);
586 }
587
588 // ----------------------------------------------------------------------------
589 // MyFrame::OnLoop
590 //
591 // Called from file->loop.
592 // Changes the state of whether we want to loop or not.
593 // ----------------------------------------------------------------------------
594 void MyFrame::OnLoop(wxCommandEvent& WXUNUSED(event))
595 {
596 if(!m_notebook->GetCurrentPage())
597 {
598 wxMessageBox(wxT("No files are currently open!"));
599 return;
600 }
601
602 ((MyNotebookPage*)m_notebook->GetCurrentPage())->m_bLoop =
603 !((MyNotebookPage*)m_notebook->GetCurrentPage())->m_bLoop;
604 }
605
606 // ----------------------------------------------------------------------------
607 // MyFrame::OnOpenFileSamePage
608 //
609 // Called from file->openfile.
610 // Opens and plays a media file in the current notebook page
611 // ----------------------------------------------------------------------------
612 void MyFrame::OnOpenFileSamePage(wxCommandEvent& WXUNUSED(event))
613 {
614 OpenFile(false);
615 }
616
617 // ----------------------------------------------------------------------------
618 // MyFrame::OnOpenFileNewPage
619 //
620 // Called from file->openfileinnewpage.
621 // Opens and plays a media file in a new notebook page
622 // ----------------------------------------------------------------------------
623 void MyFrame::OnOpenFileNewPage(wxCommandEvent& WXUNUSED(event))
624 {
625 OpenFile(true);
626 }
627
628 // ----------------------------------------------------------------------------
629 // MyFrame::OpenFile
630 //
631 // Code to actually open the media file
632 //
633 // 1) Create file dialog and ask the user for input file
634 // 2) If the user didn't want anything, break out
635 // 3) Create a new page if the user wanted one or there isn't a current page
636 // 4) Load the media
637 // 5) Play the media
638 // 6) Reset the text on the status bar
639 // 7) Set the slider of the current page to accurately reflect media length
640 // ----------------------------------------------------------------------------
641 void MyFrame::OpenFile(bool bNewPage)
642 {
643 wxFileDialog fd(this);
644
645 if(fd.ShowModal() == wxID_OK)
646 {
647 if(bNewPage || !m_notebook->GetCurrentPage())
648 m_notebook->AddPage(new MyNotebookPage(m_notebook), fd.GetPath(), true);
649
650 if( !GetCurrentMediaCtrl()->Load(fd.GetPath()) )
651 wxMessageBox(wxT("Couldn't load file!"));
652
653 if( !GetCurrentMediaCtrl()->Play() )
654 wxMessageBox(wxT("Couldn't play movie!"));
655
656 ResetStatus();
657
658 GetCurrentSlider()->SetRange(0,
659 (int)(GetCurrentMediaCtrl()->Length() / 1000));
660
661 }
662 }
663
664 // ----------------------------------------------------------------------------
665 // MyFrame::OnOpenURLSamePage
666 //
667 // Called from file->openurl.
668 // Opens and plays a media file from a URL in the current notebook page
669 // ----------------------------------------------------------------------------
670 void MyFrame::OnOpenURLSamePage(wxCommandEvent& WXUNUSED(event))
671 {
672 OpenURL(false);
673 }
674
675 // ----------------------------------------------------------------------------
676 // MyFrame::OnOpenURLNewPage
677 //
678 // Called from file->openurlinnewpage.
679 // Opens and plays a media file from a URL in a new notebook page
680 // ----------------------------------------------------------------------------
681 void MyFrame::OnOpenURLNewPage(wxCommandEvent& WXUNUSED(event))
682 {
683 OpenURL(true);
684 }
685
686 // ----------------------------------------------------------------------------
687 // MyFrame::OpenURL
688 //
689 // Code to actually open the media file from a URL
690 //
691 // 1) Create text input dialog and ask the user for an input URL
692 // 2) If the user didn't want anything, break out
693 // 3) Create a new page if the user wanted one or there isn't a current page
694 // 4) Load the media
695 // 5) Play the media
696 // 6) Reset the text on the status bar
697 // 7) Set the slider of the current page to accurately reflect media length
698 // ----------------------------------------------------------------------------
699 void MyFrame::OpenURL(bool bNewPage)
700 {
701 wxString theURL = wxGetTextFromUser(wxT("Enter the URL that has the movie to play"));
702
703 if(!theURL.empty())
704 {
705 if(bNewPage || !m_notebook->GetCurrentPage())
706 m_notebook->AddPage(new MyNotebookPage(m_notebook), theURL, true);
707
708 if( !GetCurrentMediaCtrl()->Load(wxURI(theURL)) )
709 wxMessageBox(wxT("Couldn't load URL!"));
710
711 if( !GetCurrentMediaCtrl()->Play() )
712 wxMessageBox(wxT("Couldn't play movie!"));
713
714 ResetStatus();
715
716 GetCurrentSlider()->SetRange(0,
717 (int)(GetCurrentMediaCtrl()->Length() / 1000));
718 }
719 }
720
721 // ----------------------------------------------------------------------------
722 // MyFrame::OnCloseCurrentPage
723 //
724 // Called when the user wants to close the current notebook page
725 //
726 // 1) Get the current page number (wxControl::GetSelection)
727 // 2) If there is no current page, break out
728 // 3) Delete the current page
729 // ----------------------------------------------------------------------------
730 void MyFrame::OnCloseCurrentPage(wxCommandEvent& WXUNUSED(event))
731 {
732 int sel = m_notebook->GetSelection();
733
734 if (sel != wxNOT_FOUND)
735 {
736 m_notebook->DeletePage(sel);
737 }
738 }
739
740 // ----------------------------------------------------------------------------
741 // MyFrame::OnPlay
742 //
743 // Called from file->play.
744 // Resumes the media if it is paused or stopped.
745 // ----------------------------------------------------------------------------
746 void MyFrame::OnPlay(wxCommandEvent& WXUNUSED(event))
747 {
748 if(!m_notebook->GetCurrentPage())
749 {
750 wxMessageBox(wxT("No files are currently open!"));
751 return;
752 }
753
754 if( !GetCurrentMediaCtrl()->Play() )
755 wxMessageBox(wxT("Couldn't play movie!"));
756 }
757
758 // ----------------------------------------------------------------------------
759 // MyFrame::OnPause
760 //
761 // Called from file->pause.
762 // Pauses the media in-place.
763 // ----------------------------------------------------------------------------
764 void MyFrame::OnPause(wxCommandEvent& WXUNUSED(event))
765 {
766 if(!m_notebook->GetCurrentPage())
767 {
768 wxMessageBox(wxT("No files are currently open!"));
769 return;
770 }
771
772 if( !GetCurrentMediaCtrl()->Pause() )
773 wxMessageBox(wxT("Couldn't pause movie!"));
774 }
775
776 // ----------------------------------------------------------------------------
777 // MyFrame::OnStop
778 //
779 // Called from file->stop.
780 // Where it stops depends on whether you can seek in the
781 // media control or not - if you can it stops and seeks to the beginning,
782 // otherwise it will appear to be at the end - but it will start over again
783 // when Play() is called
784 // ----------------------------------------------------------------------------
785 void MyFrame::OnStop(wxCommandEvent& WXUNUSED(event))
786 {
787 if(!m_notebook->GetCurrentPage())
788 {
789 wxMessageBox(wxT("No files are currently open!"));
790 return;
791 }
792
793 if( !GetCurrentMediaCtrl()->Stop() )
794 wxMessageBox(wxT("Couldn't stop movie!"));
795 }
796
797 // ----------------------------------------------------------------------------
798 // MyFrame::OnCloseCurrentPage
799 //
800 // Called when the user wants to closes the current notebook page
801 // ----------------------------------------------------------------------------
802
803 void MyFrame::OnPageChange(wxNotebookEvent& WXUNUSED(event))
804 {
805 ResetStatus();
806 }
807
808 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
809 //
810 // MyTimer
811 //
812 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
813
814 // ----------------------------------------------------------------------------
815 // MyTimer::Notify
816 //
817 // 1) Update our slider with the position were are in in the media
818 // 2) Update our status bar with the base text from MyFrame::ResetStatus,
819 // append some non-static (changing) info to it, then set the
820 // status bar text to that result
821 // ----------------------------------------------------------------------------
822 void MyTimer::Notify()
823 {
824 if (!m_frame->m_notebook->GetCurrentPage()) return;
825 wxMediaCtrl* m_mediactrl = ((MyNotebookPage*)m_frame->m_notebook->GetCurrentPage())->m_mediactrl;
826 wxSlider* m_slider = ((MyNotebookPage*)m_frame->m_notebook->GetCurrentPage())->m_slider;
827 if (!m_mediactrl) return;
828
829 long lPosition = (long)( m_mediactrl->Tell() / 1000 );
830 m_slider->SetValue(lPosition);
831
832 #if wxUSE_STATUSBAR
833 m_frame->SetStatusText(wxString::Format(
834 _T("%s Pos:%u State:%s Loops:%i"),
835 m_frame->m_basestatus.c_str(),
836 (unsigned int)lPosition,
837 wxGetMediaStateText(m_mediactrl->GetState()),
838 ((MyNotebookPage*)m_frame->m_notebook->GetCurrentPage())->m_nLoops
839
840 )
841 );
842 #endif
843
844 }
845
846
847 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
848 //
849 // MyNotebookPage
850 //
851 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
852
853 // ----------------------------------------------------------------------------
854 // MyNotebookPage Constructor
855 //
856 // Creates a media control and slider and adds it to this panel,
857 // along with some sizers for positioning
858 // ----------------------------------------------------------------------------
859
860 MyNotebookPage::MyNotebookPage(wxNotebook* theBook) :
861 wxPanel(theBook, wxID_ANY), m_nLoops(0), m_bLoop(false)
862 {
863 //
864 // Create and attach the first/main sizer
865 //
866 wxBoxSizer* vertsizer = new wxBoxSizer(wxVERTICAL);
867 this->SetSizer(vertsizer);
868 this->SetAutoLayout(true);
869
870 //
871 // Create our media control
872 //
873 m_mediactrl = new wxMediaCtrl();
874
875 // Make sure creation was successful
876 bool bOK = m_mediactrl->Create(this, wxID_MEDIACTRL);
877 wxASSERT_MSG(bOK, wxT("Could not create media control!"));
878 wxUnusedVar(bOK);
879
880 vertsizer->Add(m_mediactrl, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
881
882 //
883 // Create our slider
884 //
885 m_slider = new wxSlider(this, wxID_SLIDER, 0, //init
886 0, //start
887 0, //end
888 wxDefaultPosition, wxDefaultSize,
889 wxSL_HORIZONTAL );
890 vertsizer->Add(m_slider, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5);
891
892
893 //
894 // Create the second sizer which will position things
895 // vertically -
896 //
897 // -------Menu----------
898 // [m_mediactrl]
899 //
900 // [m_slider]
901 //
902 wxBoxSizer* horzsizer = new wxBoxSizer(wxHORIZONTAL);
903 vertsizer->Add(horzsizer, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
904
905 //
906 // Slider events
907 //
908 this->Connect(wxID_SLIDER, wxEVT_COMMAND_SLIDER_UPDATED,
909 (wxObjectEventFunction) (wxEventFunction)
910 (wxCommandEventFunction) &MyNotebookPage::OnSeek);
911
912 //
913 // Media Control events
914 //
915 this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_FINISHED,
916 (wxObjectEventFunction) (wxEventFunction)
917 (wxMediaEventFunction) &MyNotebookPage::OnMediaFinished);
918 }
919
920 // ----------------------------------------------------------------------------
921 // MyNotebook::OnSeek
922 //
923 // Called from file->seek.
924 // Called when the user moves the slider -
925 // seeks to a position within the media
926 // ----------------------------------------------------------------------------
927 void MyNotebookPage::OnSeek(wxCommandEvent& WXUNUSED(event))
928 {
929 if( m_mediactrl->Seek(
930 m_slider->GetValue() * 1000
931 ) == wxInvalidOffset )
932 wxMessageBox(wxT("Couldn't seek in movie!"));
933 }
934
935 // ----------------------------------------------------------------------------
936 // OnMediaFinished
937 //
938 // Called when the media stops playing.
939 // Here we loop it if the user wants to (has been selected from file menu)
940 // ----------------------------------------------------------------------------
941 void MyNotebookPage::OnMediaFinished(wxMediaEvent& WXUNUSED(event))
942 {
943 if(m_bLoop)
944 {
945 if ( !m_mediactrl->Play() )
946 wxMessageBox(wxT("Couldn't loop movie!"));
947 else
948 ++m_nLoops;
949 }
950 }
951
952 //
953 // End of MediaPlayer sample
954 //