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