]> git.saurik.com Git - wxWidgets.git/blame_incremental - samples/mediaplayer/mediaplayer.cpp
Presentation of hiding and disabling of the items in wxRadioBox.
[wxWidgets.git] / samples / mediaplayer / mediaplayer.cpp
... / ...
CommitLineData
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
101enum
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
130class MyApp : public wxApp
131{
132public:
133 virtual bool OnInit();
134};
135
136// ----------------------------------------------------------------------------
137// MyFrame
138// ----------------------------------------------------------------------------
139
140class MyFrame : public wxFrame
141{
142public:
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
165private:
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
191class 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
201public:
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
213class MyTimer : public wxTimer
214{
215public:
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// ----------------------------------------------------------------------------
243const 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// ----------------------------------------------------------------------------
274IMPLEMENT_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// ----------------------------------------------------------------------------
284bool 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
309MyFrame::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// ----------------------------------------------------------------------------
502MyFrame::~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// ----------------------------------------------------------------------------
524void 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// ----------------------------------------------------------------------------
543wxMediaCtrl* 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// ----------------------------------------------------------------------------
555wxSlider* 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// ----------------------------------------------------------------------------
567void 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// ----------------------------------------------------------------------------
579void 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// ----------------------------------------------------------------------------
594void 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// ----------------------------------------------------------------------------
612void 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// ----------------------------------------------------------------------------
623void 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// ----------------------------------------------------------------------------
641void 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// ----------------------------------------------------------------------------
670void 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// ----------------------------------------------------------------------------
681void 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// ----------------------------------------------------------------------------
699void 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// ----------------------------------------------------------------------------
730void 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// ----------------------------------------------------------------------------
746void 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// ----------------------------------------------------------------------------
764void 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// ----------------------------------------------------------------------------
785void 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
803void 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// ----------------------------------------------------------------------------
822void 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
860MyNotebookPage::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
879 vertsizer->Add(m_mediactrl, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
880
881 //
882 // Create our slider
883 //
884 m_slider = new wxSlider(this, wxID_SLIDER, 0, //init
885 0, //start
886 0, //end
887 wxDefaultPosition, wxDefaultSize,
888 wxSL_HORIZONTAL );
889 vertsizer->Add(m_slider, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5);
890
891
892 //
893 // Create the second sizer which will position things
894 // vertically -
895 //
896 // -------Menu----------
897 // [m_mediactrl]
898 //
899 // [m_slider]
900 //
901 wxBoxSizer* horzsizer = new wxBoxSizer(wxHORIZONTAL);
902 vertsizer->Add(horzsizer, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
903
904 //
905 // Slider events
906 //
907 this->Connect(wxID_SLIDER, wxEVT_COMMAND_SLIDER_UPDATED,
908 (wxObjectEventFunction) (wxEventFunction)
909 (wxCommandEventFunction) &MyNotebookPage::OnSeek);
910
911 //
912 // Media Control events
913 //
914 this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_FINISHED,
915 (wxObjectEventFunction) (wxEventFunction)
916 (wxMediaEventFunction) &MyNotebookPage::OnMediaFinished);
917}
918
919// ----------------------------------------------------------------------------
920// MyNotebook::OnSeek
921//
922// Called from file->seek.
923// Called when the user moves the slider -
924// seeks to a position within the media
925// ----------------------------------------------------------------------------
926void MyNotebookPage::OnSeek(wxCommandEvent& WXUNUSED(event))
927{
928 if( m_mediactrl->Seek(
929 m_slider->GetValue() * 1000
930 ) == wxInvalidOffset )
931 wxMessageBox(wxT("Couldn't seek in movie!"));
932}
933
934// ----------------------------------------------------------------------------
935// OnMediaFinished
936//
937// Called when the media stops playing.
938// Here we loop it if the user wants to (has been selected from file menu)
939// ----------------------------------------------------------------------------
940void MyNotebookPage::OnMediaFinished(wxMediaEvent& WXUNUSED(event))
941{
942 if(m_bLoop)
943 {
944 if ( !m_mediactrl->Play() )
945 wxMessageBox(wxT("Couldn't loop movie!"));
946 else
947 ++m_nLoops;
948 }
949}
950
951//
952// End of MediaPlayer sample
953//