]> git.saurik.com Git - wxWidgets.git/blame - samples/mediaplayer/mediaplayer.cpp
Unicode fixes, wxWidgets coding standards, source cleaning for wxFoldBar samples.
[wxWidgets.git] / samples / mediaplayer / mediaplayer.cpp
CommitLineData
ff4aedc5 1///////////////////////////////////////////////////////////////////////////////
a2d9b7d0 2// Name: mediaplayer.cpp
eaf0d558
RN
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
ff4aedc5
RN
10///////////////////////////////////////////////////////////////////////////////
11
12// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13// MediaPlayer
14//
226ec5a7 15// This is a simple example of how to use all the funtionality of
ff4aedc5
RN
16// the wxMediaCtrl class in wxWidgets.
17//
18// To use this sample, simply select Open File from the file menu,
cdc93e0c 19// select the file you want to play - and MediaPlayer will play the file in a
10a53520 20// new notebook page, showing video if neccessary.
ff4aedc5
RN
21//
22// You can select one of the menu options, or move the slider around
23// to manipulate what is playing.
24// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
eaf0d558 25
10a53520
RN
26// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
27// Known bugs with wxMediaCtrl:
cdc93e0c 28//
bc036010
RN
29// 1) Certain backends can't play the same media file at the same time (MCI,
30// Cocoa NSMovieView-Quicktime).
cdc93e0c 31// 2) Positioning on Mac Carbon is messed up if put in a sub-control like a
bc036010 32// Notebook (like this sample does) on OS versions < 10.2.
10a53520
RN
33// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34
eaf0d558 35// ============================================================================
ff4aedc5 36// Definitions
eaf0d558
RN
37// ============================================================================
38
39// ----------------------------------------------------------------------------
ff4aedc5 40// Pre-compiled header stuff
eaf0d558
RN
41// ----------------------------------------------------------------------------
42
eaf0d558
RN
43#include "wx/wxprec.h"
44
45#ifdef __BORLANDC__
46 #pragma hdrstop
47#endif
48
eaf0d558
RN
49#ifndef WX_PRECOMP
50 #include "wx/wx.h"
51#endif
52
53// ----------------------------------------------------------------------------
ff4aedc5 54// Headers
eaf0d558
RN
55// ----------------------------------------------------------------------------
56
d0b9eaa2
RN
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
ecd20d4a 63#include "wx/notebook.h" //for wxNotebook and putting movies in pages
eaf0d558 64
10a53520
RN
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
ff4aedc5 69// ----------------------------------------------------------------------------
226ec5a7 70// Bail out if the user doesn't want one of the
ff4aedc5
RN
71// things we need
72// ----------------------------------------------------------------------------
eaf0d558 73
ff4aedc5
RN
74#if !wxUSE_GUI
75#error "This is a GUI sample"
eaf0d558
RN
76#endif
77
ecd20d4a
RN
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!"
ff4aedc5
RN
80#endif
81
82// ============================================================================
d0b9eaa2 83// Declarations
ff4aedc5
RN
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,
10a53520
RN
95 wxID_OPENFILESAMEPAGE,
96 wxID_OPENFILENEWPAGE,
97 wxID_OPENURLSAMEPAGE,
98 wxID_OPENURLNEWPAGE,
99 wxID_CLOSECURRENTPAGE,
ff4aedc5
RN
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]
14af6816
RN
105 wxID_SLIDER, // event id for our slider
106 wxID_NOTEBOOK, // event id for our notebook
107 wxID_MEDIACTRL // event id for our wxMediaCtrl
ff4aedc5
RN
108};
109
110// ----------------------------------------------------------------------------
111// MyApp
eaf0d558
RN
112// ----------------------------------------------------------------------------
113
eaf0d558
RN
114class MyApp : public wxApp
115{
116public:
eaf0d558
RN
117 virtual bool OnInit();
118};
119
ff4aedc5
RN
120// ----------------------------------------------------------------------------
121// MyFrame
122// ----------------------------------------------------------------------------
123
eaf0d558
RN
124class MyFrame : public wxFrame
125{
126public:
ff4aedc5 127 // Ctor/Dtor
eaf0d558
RN
128 MyFrame(const wxString& title);
129 ~MyFrame();
130
ff4aedc5 131 // Menu event handlers
eaf0d558
RN
132 void OnQuit(wxCommandEvent& event);
133 void OnAbout(wxCommandEvent& event);
134 void OnLoop(wxCommandEvent& event);
135
10a53520
RN
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);
eaf0d558
RN
141
142 void OnPlay(wxCommandEvent& event);
143 void OnPause(wxCommandEvent& event);
144 void OnStop(wxCommandEvent& event);
145
10a53520 146 // Notebook event handlers
ecd20d4a 147 void OnPageChange(wxNotebookEvent& event);
eaf0d558
RN
148
149private:
ff4aedc5 150 // Rebuild base status string (see Implementation)
d0b9eaa2
RN
151 void ResetStatus();
152
10a53520
RN
153 // Common open file code
154 void OpenFile(bool bNewPage);
155 void OpenURL(bool bNewPage);
cdc93e0c 156
10a53520
RN
157 // Get the media control and slider of current notebook page
158 wxMediaCtrl* GetCurrentMediaCtrl();
159 wxSlider* GetCurrentSlider();
160
ff4aedc5
RN
161 class MyTimer* m_timer; //Timer to write info to status bar
162 wxString m_basestatus; //Base status string (see ResetStatus())
14af6816 163 wxNotebook* m_notebook; //Notebook containing our pages
ff4aedc5
RN
164
165 // So that mytimer can access MyFrame's members
eaf0d558 166 friend class MyTimer;
ff4aedc5 167};
eaf0d558 168
10a53520
RN
169
170
171// ----------------------------------------------------------------------------
172// MyNotebookPage
173// ----------------------------------------------------------------------------
174
ecd20d4a
RN
175class MyNotebookPage : public wxPanel
176{
10a53520 177 MyNotebookPage(wxNotebook* book);
cdc93e0c 178
10a53520
RN
179 // Slider event handlers
180 void OnSeek(wxCommandEvent& event);
181
182 // Media event handlers
bc036010 183 void OnMediaFinished(wxMediaEvent& event);
cdc93e0c 184
ecd20d4a 185public:
10a53520 186 friend class MyFrame; //make MyFrame able to access private members
ecd20d4a
RN
187 wxMediaCtrl* m_mediactrl; //Our media control
188 wxSlider* m_slider; //The slider below our media control
10a53520 189 int m_nLoops; //Number of times media has looped
bc036010 190 bool m_bLoop; //Whether we are looping or not
ecd20d4a
RN
191};
192
ff4aedc5
RN
193// ----------------------------------------------------------------------------
194// MyTimer
195// ----------------------------------------------------------------------------
196
197class MyTimer : public wxTimer
198{
199public:
200 //Ctor
201 MyTimer(MyFrame* frame) {m_frame = frame;}
eaf0d558 202
ff4aedc5
RN
203 //Called each time the timer's timeout expires
204 void Notify();
205
206 MyFrame* m_frame; //The MyFrame
eaf0d558
RN
207};
208
ff4aedc5 209// ============================================================================
d0b9eaa2 210//
ff4aedc5 211// Implementation
d0b9eaa2 212//
ff4aedc5 213// ============================================================================
d0b9eaa2 214
ff4aedc5
RN
215// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
216//
217// [Functions]
d0b9eaa2 218//
ff4aedc5
RN
219// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
220
221// ----------------------------------------------------------------------------
222// wxGetMediaStateText
d0b9eaa2 223//
ff4aedc5
RN
224// Converts a wxMediaCtrl state into something useful that we can display
225// to the user
226// ----------------------------------------------------------------------------
eaf0d558
RN
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
ff4aedc5
RN
241// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
242//
243// MyApp
244//
245// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
eaf0d558
RN
246
247// ----------------------------------------------------------------------------
ff4aedc5
RN
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
226ec5a7 255// routine, such as main or WinMain(). Use IMPLEMENT_APP_NO_MAIN if you do
ff4aedc5 256// not desire this behavior.
eaf0d558 257// ----------------------------------------------------------------------------
eaf0d558
RN
258IMPLEMENT_APP(MyApp)
259
eaf0d558
RN
260
261// ----------------------------------------------------------------------------
ff4aedc5
RN
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
eaf0d558 267// ----------------------------------------------------------------------------
eaf0d558
RN
268bool MyApp::OnInit()
269{
ff4aedc5 270 MyFrame *frame = new MyFrame(_T("MediaPlayer wxWidgets Sample"));
eaf0d558
RN
271 frame->Show(true);
272
eaf0d558
RN
273 return true;
274}
275
eaf0d558 276
ff4aedc5
RN
277// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
278//
279// MyFrame
d0b9eaa2 280//
ff4aedc5
RN
281// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
282
283// ----------------------------------------------------------------------------
284// MyFrame Constructor
d0b9eaa2 285//
ff4aedc5 286// 1) Create our menus
10a53520 287// 2) Create our notebook control and add it to the frame
ff4aedc5
RN
288// 3) Create our status bar
289// 4) Connect our events
290// 5) Start our timer
291// ----------------------------------------------------------------------------
9180b535 292
eaf0d558 293MyFrame::MyFrame(const wxString& title)
ff4aedc5 294 : wxFrame(NULL, wxID_ANY, title)
eaf0d558 295{
d0b9eaa2
RN
296 //
297 // Create Menus
298 //
eaf0d558
RN
299 wxMenu *menuFile = new wxMenu;
300
eaf0d558 301 wxMenu *helpMenu = new wxMenu;
226ec5a7
WS
302 helpMenu->Append(wxID_ABOUT,
303 _T("&About...\tF1"),
ff4aedc5 304 _T("Show about dialog"));
eaf0d558 305
cdc93e0c 306 menuFile->Append(wxID_OPENFILESAMEPAGE, _T("&Open File"),
10a53520 307 _T("Open a File in the current notebook page"));
cdc93e0c 308 menuFile->Append(wxID_OPENFILENEWPAGE, _T("&Open File in a new page"),
10a53520
RN
309 _T("Open a File in a new notebook page"));
310#if wxUSE_UNOFFICIALSTUFF
cdc93e0c 311 menuFile->Append(wxID_OPENURLSAMEPAGE, _T("&Open URL"),
10a53520 312 _T("Open a URL in the current notebook page"));
cdc93e0c 313 menuFile->Append(wxID_OPENURLNEWPAGE, _T("&Open URL in a new page"),
10a53520
RN
314 _T("Open a URL in a new notebook page"));
315#endif
316 menuFile->AppendSeparator();
cdc93e0c 317 menuFile->Append(wxID_CLOSECURRENTPAGE, _T("&Close Current Page"),
10a53520 318 _T("Close current notebook page"));
eaf0d558 319 menuFile->AppendSeparator();
ff4aedc5
RN
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"));
eaf0d558 323 menuFile->AppendSeparator();
226ec5a7
WS
324 menuFile->AppendCheckItem(wxID_LOOP,
325 _T("&Loop"),
ff4aedc5 326 _T("Loop Selected Media"));
eaf0d558 327 menuFile->AppendSeparator();
226ec5a7
WS
328 menuFile->Append(wxID_EXIT,
329 _T("E&xit\tAlt-X"),
ff4aedc5 330 _T("Quit this program"));
eaf0d558 331
eaf0d558
RN
332 wxMenuBar *menuBar = new wxMenuBar();
333 menuBar->Append(menuFile, _T("&File"));
334 menuBar->Append(helpMenu, _T("&Help"));
335
eaf0d558 336 SetMenuBar(menuBar);
eaf0d558 337
10a53520 338 //
cdc93e0c 339 // Create our notebook - using wxNotebook is luckily pretty
10a53520
RN
340 // simple and self-explanatory in most cases
341 //
ecd20d4a 342 m_notebook = new wxNotebook(this, wxID_NOTEBOOK);
eaf0d558 343
d0b9eaa2
RN
344 //
345 // Create our status bar
346 //
eaf0d558
RN
347#if wxUSE_STATUSBAR
348 // create a status bar just for fun (by default with 1 pane only)
349 CreateStatusBar(1);
eaf0d558 350#endif // wxUSE_STATUSBAR
226ec5a7 351
ff4aedc5
RN
352 //
353 // Connect events.
226ec5a7 354 //
ff4aedc5
RN
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
226ec5a7 368 // in it. EVT_XXX(XXX) are each of your handlers, such
ff4aedc5
RN
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
226ec5a7 395 // type, then to a wxEventFunction, then to a
ff4aedc5
RN
396 // wxObjectEventFunction - I.E.
397 // (wxObjectEventFunction)(wxEventFunction)
398 // (wxCommandEventFunction) &MyFrame::MyHandler
399 //
14af6816
RN
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 //
226ec5a7 406 // The fourth is an optional userdata param -
ff4aedc5 407 // this is of historical relevance only and is
00a1d2e0 408 // there only for backwards compatibility.
ff4aedc5
RN
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
226ec5a7 413 // if you were to call "this->MyFunc()"
ff4aedc5
RN
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 //
d0b9eaa2
RN
420
421 //
ff4aedc5 422 // Menu events
d0b9eaa2 423 //
226ec5a7 424 this->Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED,
14af6816 425 wxCommandEventHandler(MyFrame::OnQuit));
226ec5a7
WS
426
427 this->Connect(wxID_ABOUT, wxEVT_COMMAND_MENU_SELECTED,
14af6816 428 wxCommandEventHandler(MyFrame::OnAbout));
ff4aedc5 429
226ec5a7 430 this->Connect(wxID_LOOP, wxEVT_COMMAND_MENU_SELECTED,
14af6816 431 wxCommandEventHandler(MyFrame::OnLoop));
ff4aedc5 432
10a53520 433 this->Connect(wxID_OPENFILENEWPAGE, wxEVT_COMMAND_MENU_SELECTED,
14af6816 434 wxCommandEventHandler(MyFrame::OnOpenFileNewPage));
10a53520
RN
435
436 this->Connect(wxID_OPENFILESAMEPAGE, wxEVT_COMMAND_MENU_SELECTED,
14af6816 437 wxCommandEventHandler(MyFrame::OnOpenFileSamePage));
10a53520
RN
438
439 this->Connect(wxID_OPENURLNEWPAGE, wxEVT_COMMAND_MENU_SELECTED,
14af6816 440 wxCommandEventHandler(MyFrame::OnOpenURLNewPage));
10a53520
RN
441
442 this->Connect(wxID_OPENURLSAMEPAGE, wxEVT_COMMAND_MENU_SELECTED,
14af6816 443 wxCommandEventHandler(MyFrame::OnOpenURLSamePage));
10a53520
RN
444
445 this->Connect(wxID_CLOSECURRENTPAGE, wxEVT_COMMAND_MENU_SELECTED,
14af6816 446 wxCommandEventHandler(MyFrame::OnCloseCurrentPage));
d0b9eaa2 447
226ec5a7 448 this->Connect(wxID_PLAY, wxEVT_COMMAND_MENU_SELECTED,
14af6816 449 wxCommandEventHandler(MyFrame::OnPlay));
ff4aedc5 450
226ec5a7 451 this->Connect(wxID_PAUSE, wxEVT_COMMAND_MENU_SELECTED,
14af6816 452 wxCommandEventHandler(MyFrame::OnPause));
ff4aedc5 453
226ec5a7 454 this->Connect(wxID_STOP, wxEVT_COMMAND_MENU_SELECTED,
14af6816 455 wxCommandEventHandler(MyFrame::OnStop));
ff4aedc5 456
ff4aedc5 457 //
10a53520 458 // Notebook events
ff4aedc5 459 //
ecd20d4a 460 this->Connect(wxID_NOTEBOOK, wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
14af6816 461 wxNotebookEventHandler(MyFrame::OnPageChange));
cdc93e0c 462
ff4aedc5
RN
463 //
464 // End of Events
465 //
466
ff4aedc5
RN
467 //
468 // Create a timer to update our status bar
469 //
d0b9eaa2
RN
470 m_timer = new MyTimer(this);
471 m_timer->Start(100);
eaf0d558
RN
472}
473
ff4aedc5
RN
474// ----------------------------------------------------------------------------
475// MyFrame Destructor
d0b9eaa2 476//
226ec5a7 477// 1) Deletes child objects implicitly
ff4aedc5
RN
478// 2) Delete our timer explicitly
479// ----------------------------------------------------------------------------
eaf0d558
RN
480MyFrame::~MyFrame()
481{
d0b9eaa2 482 delete m_timer;
eaf0d558
RN
483}
484
ff4aedc5
RN
485// ----------------------------------------------------------------------------
486// MyFrame::ResetStatus
487//
226ec5a7 488// Here we just make a simple status string with some useful info about
ff4aedc5
RN
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
226ec5a7 492// set the status bar to this text.
d0b9eaa2 493//
ff4aedc5
RN
494// In real applications, you'd want to find a better way to do this,
495// such as static text controls (wxStaticText).
226ec5a7
WS
496//
497// We display info here in seconds (wxMediaCtrl uses milliseconds - that's why
ff4aedc5
RN
498// we divide by 1000).
499//
500// We also reset our loop counter here.
501// ----------------------------------------------------------------------------
502void MyFrame::ResetStatus()
503{
10a53520 504 wxMediaCtrl* currentMediaCtrl = GetCurrentMediaCtrl();
ecd20d4a 505
ff4aedc5
RN
506 m_basestatus = wxString::Format(_T("Size(x,y):%i,%i ")
507 _T("Length(Seconds):%u Speed:%1.1fx"),
10a53520
RN
508 currentMediaCtrl->GetBestSize().x,
509 currentMediaCtrl->GetBestSize().y,
510 (unsigned)((currentMediaCtrl->Length() / 1000)),
511 currentMediaCtrl->GetPlaybackRate()
ff4aedc5 512 );
10a53520 513}
ff4aedc5 514
10a53520
RN
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}
ff4aedc5 526
10a53520
RN
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;
ff4aedc5
RN
537}
538
539// ----------------------------------------------------------------------------
540// MyFrame::OnQuit
d0b9eaa2 541//
ff4aedc5
RN
542// Called from file->quit.
543// Closes this application.
544// ----------------------------------------------------------------------------
eaf0d558
RN
545void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
546{
547 // true is to force the frame to close
548 Close(true);
549}
550
ff4aedc5
RN
551// ----------------------------------------------------------------------------
552// MyFrame::OnAbout
226ec5a7 553//
ff4aedc5
RN
554// Called from help->about.
555// Gets some info about this application.
556// ----------------------------------------------------------------------------
eaf0d558
RN
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
ff4aedc5
RN
566// ----------------------------------------------------------------------------
567// MyFrame::OnLoop
d0b9eaa2 568//
ff4aedc5
RN
569// Called from file->loop.
570// Changes the state of whether we want to loop or not.
571// ----------------------------------------------------------------------------
eaf0d558
RN
572void MyFrame::OnLoop(wxCommandEvent& WXUNUSED(event))
573{
10a53520
RN
574 if(!m_notebook->GetCurrentPage())
575 {
576 wxMessageBox(wxT("No files are currently open!"));
577 return;
578 }
bc036010 579
cdc93e0c 580 ((MyNotebookPage*)m_notebook->GetCurrentPage())->m_bLoop =
bc036010 581 !((MyNotebookPage*)m_notebook->GetCurrentPage())->m_bLoop;
eaf0d558
RN
582}
583
ff4aedc5 584// ----------------------------------------------------------------------------
10a53520 585// MyFrame::OnOpenFileSamePage
d0b9eaa2 586//
ff4aedc5 587// Called from file->openfile.
10a53520
RN
588// Opens and plays a media file in the current notebook page
589// ----------------------------------------------------------------------------
590void MyFrame::OnOpenFileSamePage(wxCommandEvent& WXUNUSED(event))
cdc93e0c
WS
591{
592 OpenFile(false);
10a53520
RN
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))
cdc93e0c
WS
602{
603 OpenFile(true);
10a53520
RN
604}
605
ff4aedc5 606// ----------------------------------------------------------------------------
10a53520
RN
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)
eaf0d558
RN
620{
621 wxFileDialog fd(this);
622
623 if(fd.ShowModal() == wxID_OK)
624 {
10a53520
RN
625 if(bNewPage || !m_notebook->GetCurrentPage())
626 m_notebook->AddPage(new MyNotebookPage(m_notebook), fd.GetPath(), true);
14af6816
RN
627 else //don't forget to update notebook page title
628 m_notebook->SetPageText(m_notebook->GetSelection(), fd.GetPath());
cdc93e0c 629
10a53520 630 if( !GetCurrentMediaCtrl()->Load(fd.GetPath()) )
eaf0d558
RN
631 wxMessageBox(wxT("Couldn't load file!"));
632
10a53520 633 if( !GetCurrentMediaCtrl()->Play() )
ceefc965
WS
634 wxMessageBox(wxT("Couldn't play movie!"));
635
eaf0d558 636 ResetStatus();
cdc93e0c
WS
637
638 GetCurrentSlider()->SetRange(0,
10a53520 639 (int)(GetCurrentMediaCtrl()->Length() / 1000));
10a53520
RN
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))
cdc93e0c
WS
650{
651 OpenURL(false);
10a53520
RN
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))
cdc93e0c
WS
661{
662 OpenURL(true);
10a53520
RN
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);
14af6816
RN
686 else //don't forget to update notebook page title
687 m_notebook->SetPageText(m_notebook->GetSelection(), theURL);
10a53520
RN
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!"));
cdc93e0c 694
10a53520
RN
695 ResetStatus();
696
cdc93e0c 697 GetCurrentSlider()->SetRange(0,
10a53520 698 (int)(GetCurrentMediaCtrl()->Length() / 1000));
eaf0d558
RN
699 }
700}
701
10a53520
RN
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);
cdc93e0c 718 }
10a53520
RN
719}
720
ff4aedc5
RN
721// ----------------------------------------------------------------------------
722// MyFrame::OnPlay
226ec5a7 723//
ff4aedc5
RN
724// Called from file->play.
725// Resumes the media if it is paused or stopped.
726// ----------------------------------------------------------------------------
eaf0d558
RN
727void MyFrame::OnPlay(wxCommandEvent& WXUNUSED(event))
728{
10a53520
RN
729 if(!m_notebook->GetCurrentPage())
730 {
731 wxMessageBox(wxT("No files are currently open!"));
732 return;
733 }
734
735 if( !GetCurrentMediaCtrl()->Play() )
eaf0d558
RN
736 wxMessageBox(wxT("Couldn't play movie!"));
737}
738
ff4aedc5
RN
739// ----------------------------------------------------------------------------
740// MyFrame::OnPause
226ec5a7 741//
ff4aedc5
RN
742// Called from file->pause.
743// Pauses the media in-place.
744// ----------------------------------------------------------------------------
eaf0d558
RN
745void MyFrame::OnPause(wxCommandEvent& WXUNUSED(event))
746{
10a53520
RN
747 if(!m_notebook->GetCurrentPage())
748 {
749 wxMessageBox(wxT("No files are currently open!"));
750 return;
751 }
752
753 if( !GetCurrentMediaCtrl()->Pause() )
eaf0d558
RN
754 wxMessageBox(wxT("Couldn't pause movie!"));
755}
756
ff4aedc5
RN
757// ----------------------------------------------------------------------------
758// MyFrame::OnStop
226ec5a7 759//
ff4aedc5
RN
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// ----------------------------------------------------------------------------
eaf0d558
RN
766void MyFrame::OnStop(wxCommandEvent& WXUNUSED(event))
767{
10a53520
RN
768 if(!m_notebook->GetCurrentPage())
769 {
770 wxMessageBox(wxT("No files are currently open!"));
771 return;
772 }
eaf0d558 773
10a53520
RN
774 if( !GetCurrentMediaCtrl()->Stop() )
775 wxMessageBox(wxT("Couldn't stop movie!"));
eaf0d558
RN
776}
777
ff4aedc5 778// ----------------------------------------------------------------------------
10a53520 779// MyFrame::OnCloseCurrentPage
226ec5a7 780//
10a53520 781// Called when the user wants to closes the current notebook page
ff4aedc5 782// ----------------------------------------------------------------------------
ecd20d4a
RN
783
784void MyFrame::OnPageChange(wxNotebookEvent& WXUNUSED(event))
785{
786 ResetStatus();
787}
788
ff4aedc5 789// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
d0b9eaa2 790//
ff4aedc5 791// MyTimer
d0b9eaa2 792//
ff4aedc5
RN
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,
226ec5a7 800// append some non-static (changing) info to it, then set the
ff4aedc5
RN
801// status bar text to that result
802// ----------------------------------------------------------------------------
803void MyTimer::Notify()
eaf0d558 804{
10a53520 805 if (!m_frame->m_notebook->GetCurrentPage()) return;
cdc93e0c
WS
806 wxMediaCtrl* m_mediactrl = ((MyNotebookPage*)m_frame->m_notebook->GetCurrentPage())->m_mediactrl;
807 wxSlider* m_slider = ((MyNotebookPage*)m_frame->m_notebook->GetCurrentPage())->m_slider;
ecd20d4a
RN
808 if (!m_mediactrl) return;
809
810 long lPosition = (long)( m_mediactrl->Tell() / 1000 );
811 m_slider->SetValue(lPosition);
ff4aedc5
RN
812
813#if wxUSE_STATUSBAR
814 m_frame->SetStatusText(wxString::Format(
10a53520 815 _T("%s Pos:%u State:%s Loops:%i"),
ff4aedc5
RN
816 m_frame->m_basestatus.c_str(),
817 (unsigned int)lPosition,
10a53520
RN
818 wxGetMediaStateText(m_mediactrl->GetState()),
819 ((MyNotebookPage*)m_frame->m_notebook->GetCurrentPage())->m_nLoops
cdc93e0c 820
ff4aedc5
RN
821 )
822 );
823#endif
ecd20d4a
RN
824
825}
826
827
10a53520
RN
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
ecd20d4a 841MyNotebookPage::MyNotebookPage(wxNotebook* theBook) :
bc036010 842 wxPanel(theBook, wxID_ANY), m_nLoops(0), m_bLoop(false)
ecd20d4a 843{
ecd20d4a
RN
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 //
dae87f93 854 m_mediactrl = new wxMediaCtrl();
cdc93e0c 855
dae87f93
RN
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!"));
cdc93e0c
WS
859 wxUnusedVar(bOK);
860
ecd20d4a
RN
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
10a53520
RN
886 //
887 // Slider events
888 //
889 this->Connect(wxID_SLIDER, wxEVT_COMMAND_SLIDER_UPDATED,
14af6816 890 wxCommandEventHandler(MyNotebookPage::OnSeek));
10a53520
RN
891
892 //
893 // Media Control events
894 //
bc036010 895 this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_FINISHED,
14af6816 896 wxMediaEventHandler(MyNotebookPage::OnMediaFinished));
10a53520
RN
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{
cdc93e0c
WS
908 if( m_mediactrl->Seek(
909 m_slider->GetValue() * 1000
10a53520
RN
910 ) == wxInvalidOffset )
911 wxMessageBox(wxT("Couldn't seek in movie!"));
ceefc965 912}
ff4aedc5 913
10a53520 914// ----------------------------------------------------------------------------
bc036010 915// OnMediaFinished
10a53520 916//
bc036010
RN
917// Called when the media stops playing.
918// Here we loop it if the user wants to (has been selected from file menu)
10a53520 919// ----------------------------------------------------------------------------
bc036010 920void MyNotebookPage::OnMediaFinished(wxMediaEvent& WXUNUSED(event))
10a53520 921{
bc036010
RN
922 if(m_bLoop)
923 {
924 if ( !m_mediactrl->Play() )
925 wxMessageBox(wxT("Couldn't loop movie!"));
926 else
927 ++m_nLoops;
928 }
10a53520 929}
ecd20d4a 930
ff4aedc5
RN
931//
932// End of MediaPlayer sample
933//