]> git.saurik.com Git - wxWidgets.git/blame_incremental - samples/mediaplayer/mediaplayer.cpp
Unicode fixes, wxWidgets coding standards, source cleaning for wxFoldBar samples.
[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// ----------------------------------------------------------------------------
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
91enum
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
114class MyApp : public wxApp
115{
116public:
117 virtual bool OnInit();
118};
119
120// ----------------------------------------------------------------------------
121// MyFrame
122// ----------------------------------------------------------------------------
123
124class MyFrame : public wxFrame
125{
126public:
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
149private:
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
175class 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
185public:
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
197class MyTimer : public wxTimer
198{
199public:
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// ----------------------------------------------------------------------------
227const 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// ----------------------------------------------------------------------------
258IMPLEMENT_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// ----------------------------------------------------------------------------
268bool 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
293MyFrame::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// ----------------------------------------------------------------------------
480MyFrame::~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// ----------------------------------------------------------------------------
502void 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// ----------------------------------------------------------------------------
521wxMediaCtrl* 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// ----------------------------------------------------------------------------
533wxSlider* 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// ----------------------------------------------------------------------------
545void 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// ----------------------------------------------------------------------------
557void 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// ----------------------------------------------------------------------------
572void 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// ----------------------------------------------------------------------------
590void 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// ----------------------------------------------------------------------------
601void 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// ----------------------------------------------------------------------------
619void 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// ----------------------------------------------------------------------------
649void 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// ----------------------------------------------------------------------------
660void 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// ----------------------------------------------------------------------------
678void 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// ----------------------------------------------------------------------------
711void 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// ----------------------------------------------------------------------------
727void 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// ----------------------------------------------------------------------------
745void 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// ----------------------------------------------------------------------------
766void 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
784void 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// ----------------------------------------------------------------------------
803void 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
841MyNotebookPage::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// ----------------------------------------------------------------------------
906void 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// ----------------------------------------------------------------------------
920void 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//