]> git.saurik.com Git - wxWidgets.git/blame - samples/mediaplayer/mediaplayer.cpp
Presentation of hiding and disabling of the items in wxRadioBox.
[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,
10a53520
RN
19// select the file you want to play - and MediaPlayer will play the file in a
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:
28//
bc036010
RN
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.
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
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
ff4aedc5 79// ----------------------------------------------------------------------------
226ec5a7 80// Bail out if the user doesn't want one of the
ff4aedc5
RN
81// things we need
82// ----------------------------------------------------------------------------
eaf0d558 83
ff4aedc5
RN
84#if !wxUSE_GUI
85#error "This is a GUI sample"
eaf0d558
RN
86#endif
87
ecd20d4a
RN
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!"
ff4aedc5
RN
90#endif
91
92// ============================================================================
d0b9eaa2 93// Declarations
ff4aedc5
RN
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,
10a53520
RN
105 wxID_OPENFILESAMEPAGE,
106 wxID_OPENFILENEWPAGE,
107 wxID_OPENURLSAMEPAGE,
108 wxID_OPENURLNEWPAGE,
109 wxID_CLOSECURRENTPAGE,
ff4aedc5
RN
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
10a53520 116 // event id for our slider
ff4aedc5
RN
117 wxID_SLIDER,
118
10a53520 119 // event id for our notebook
ecd20d4a 120 wxID_NOTEBOOK,
10a53520
RN
121
122 // event id for our wxMediaCtrl
ff4aedc5
RN
123 wxID_MEDIACTRL
124};
125
126// ----------------------------------------------------------------------------
127// MyApp
eaf0d558
RN
128// ----------------------------------------------------------------------------
129
eaf0d558
RN
130class MyApp : public wxApp
131{
132public:
eaf0d558
RN
133 virtual bool OnInit();
134};
135
ff4aedc5
RN
136// ----------------------------------------------------------------------------
137// MyFrame
138// ----------------------------------------------------------------------------
139
eaf0d558
RN
140class MyFrame : public wxFrame
141{
142public:
ff4aedc5 143 // Ctor/Dtor
eaf0d558
RN
144 MyFrame(const wxString& title);
145 ~MyFrame();
146
ff4aedc5 147 // Menu event handlers
eaf0d558
RN
148 void OnQuit(wxCommandEvent& event);
149 void OnAbout(wxCommandEvent& event);
150 void OnLoop(wxCommandEvent& event);
151
10a53520
RN
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);
eaf0d558
RN
157
158 void OnPlay(wxCommandEvent& event);
159 void OnPause(wxCommandEvent& event);
160 void OnStop(wxCommandEvent& event);
161
10a53520 162 // Notebook event handlers
ecd20d4a 163 void OnPageChange(wxNotebookEvent& event);
eaf0d558
RN
164
165private:
ff4aedc5 166 // Rebuild base status string (see Implementation)
d0b9eaa2
RN
167 void ResetStatus();
168
10a53520
RN
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
ff4aedc5
RN
177 class MyTimer* m_timer; //Timer to write info to status bar
178 wxString m_basestatus; //Base status string (see ResetStatus())
ecd20d4a 179 wxNotebook* m_notebook;
ff4aedc5
RN
180
181 // So that mytimer can access MyFrame's members
eaf0d558 182 friend class MyTimer;
ff4aedc5 183};
eaf0d558 184
10a53520
RN
185
186
187// ----------------------------------------------------------------------------
188// MyNotebookPage
189// ----------------------------------------------------------------------------
190
ecd20d4a
RN
191class MyNotebookPage : public wxPanel
192{
10a53520 193 MyNotebookPage(wxNotebook* book);
ecd20d4a 194
10a53520
RN
195 // Slider event handlers
196 void OnSeek(wxCommandEvent& event);
197
198 // Media event handlers
bc036010 199 void OnMediaFinished(wxMediaEvent& event);
ecd20d4a
RN
200
201public:
10a53520 202 friend class MyFrame; //make MyFrame able to access private members
ecd20d4a
RN
203 wxMediaCtrl* m_mediactrl; //Our media control
204 wxSlider* m_slider; //The slider below our media control
10a53520 205 int m_nLoops; //Number of times media has looped
bc036010 206 bool m_bLoop; //Whether we are looping or not
ecd20d4a
RN
207};
208
ff4aedc5
RN
209// ----------------------------------------------------------------------------
210// MyTimer
211// ----------------------------------------------------------------------------
212
213class MyTimer : public wxTimer
214{
215public:
216 //Ctor
217 MyTimer(MyFrame* frame) {m_frame = frame;}
eaf0d558 218
ff4aedc5
RN
219 //Called each time the timer's timeout expires
220 void Notify();
221
222 MyFrame* m_frame; //The MyFrame
eaf0d558
RN
223};
224
ff4aedc5 225// ============================================================================
d0b9eaa2 226//
ff4aedc5 227// Implementation
d0b9eaa2 228//
ff4aedc5 229// ============================================================================
d0b9eaa2 230
ff4aedc5
RN
231// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
232//
233// [Functions]
d0b9eaa2 234//
ff4aedc5
RN
235// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
236
237// ----------------------------------------------------------------------------
238// wxGetMediaStateText
d0b9eaa2 239//
ff4aedc5
RN
240// Converts a wxMediaCtrl state into something useful that we can display
241// to the user
242// ----------------------------------------------------------------------------
eaf0d558
RN
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
ff4aedc5
RN
257// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
258//
259// MyApp
260//
261// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
eaf0d558
RN
262
263// ----------------------------------------------------------------------------
ff4aedc5
RN
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
226ec5a7 271// routine, such as main or WinMain(). Use IMPLEMENT_APP_NO_MAIN if you do
ff4aedc5 272// not desire this behavior.
eaf0d558 273// ----------------------------------------------------------------------------
eaf0d558
RN
274IMPLEMENT_APP(MyApp)
275
eaf0d558
RN
276
277// ----------------------------------------------------------------------------
ff4aedc5
RN
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
eaf0d558 283// ----------------------------------------------------------------------------
eaf0d558
RN
284bool MyApp::OnInit()
285{
ff4aedc5 286 MyFrame *frame = new MyFrame(_T("MediaPlayer wxWidgets Sample"));
eaf0d558
RN
287 frame->Show(true);
288
eaf0d558
RN
289 return true;
290}
291
eaf0d558 292
ff4aedc5
RN
293// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
294//
295// MyFrame
d0b9eaa2 296//
ff4aedc5
RN
297// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
298
299// ----------------------------------------------------------------------------
300// MyFrame Constructor
d0b9eaa2 301//
ff4aedc5 302// 1) Create our menus
10a53520 303// 2) Create our notebook control and add it to the frame
ff4aedc5
RN
304// 3) Create our status bar
305// 4) Connect our events
306// 5) Start our timer
307// ----------------------------------------------------------------------------
9180b535 308
eaf0d558 309MyFrame::MyFrame(const wxString& title)
ff4aedc5 310 : wxFrame(NULL, wxID_ANY, title)
eaf0d558 311{
d0b9eaa2
RN
312 //
313 // Create Menus
314 //
eaf0d558
RN
315 wxMenu *menuFile = new wxMenu;
316
eaf0d558 317 wxMenu *helpMenu = new wxMenu;
226ec5a7
WS
318 helpMenu->Append(wxID_ABOUT,
319 _T("&About...\tF1"),
ff4aedc5 320 _T("Show about dialog"));
eaf0d558 321
10a53520
RN
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"));
eaf0d558 335 menuFile->AppendSeparator();
ff4aedc5
RN
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"));
eaf0d558 339 menuFile->AppendSeparator();
226ec5a7
WS
340 menuFile->AppendCheckItem(wxID_LOOP,
341 _T("&Loop"),
ff4aedc5 342 _T("Loop Selected Media"));
eaf0d558 343 menuFile->AppendSeparator();
226ec5a7
WS
344 menuFile->Append(wxID_EXIT,
345 _T("E&xit\tAlt-X"),
ff4aedc5 346 _T("Quit this program"));
eaf0d558 347
eaf0d558
RN
348 wxMenuBar *menuBar = new wxMenuBar();
349 menuBar->Append(menuFile, _T("&File"));
350 menuBar->Append(helpMenu, _T("&Help"));
351
eaf0d558 352 SetMenuBar(menuBar);
eaf0d558 353
10a53520
RN
354 //
355 // Create our notebook - using wxNotebook is luckily pretty
356 // simple and self-explanatory in most cases
357 //
ecd20d4a 358 m_notebook = new wxNotebook(this, wxID_NOTEBOOK);
eaf0d558 359
d0b9eaa2
RN
360 //
361 // Create our status bar
362 //
eaf0d558
RN
363#if wxUSE_STATUSBAR
364 // create a status bar just for fun (by default with 1 pane only)
365 CreateStatusBar(1);
eaf0d558 366#endif // wxUSE_STATUSBAR
226ec5a7 367
ff4aedc5
RN
368 //
369 // Connect events.
226ec5a7 370 //
ff4aedc5
RN
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
226ec5a7 384 // in it. EVT_XXX(XXX) are each of your handlers, such
ff4aedc5
RN
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
226ec5a7 411 // type, then to a wxEventFunction, then to a
ff4aedc5
RN
412 // wxObjectEventFunction - I.E.
413 // (wxObjectEventFunction)(wxEventFunction)
414 // (wxCommandEventFunction) &MyFrame::MyHandler
415 //
226ec5a7 416 // The fourth is an optional userdata param -
ff4aedc5 417 // this is of historical relevance only and is
00a1d2e0 418 // there only for backwards compatibility.
ff4aedc5
RN
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
226ec5a7 423 // if you were to call "this->MyFunc()"
ff4aedc5
RN
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 //
d0b9eaa2
RN
430
431 //
ff4aedc5 432 // Menu events
d0b9eaa2 433 //
226ec5a7
WS
434 this->Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED,
435 (wxObjectEventFunction) (wxEventFunction)
ff4aedc5 436 (wxCommandEventFunction) &MyFrame::OnQuit);
226ec5a7
WS
437
438 this->Connect(wxID_ABOUT, wxEVT_COMMAND_MENU_SELECTED,
439 (wxObjectEventFunction) (wxEventFunction)
ff4aedc5
RN
440 (wxCommandEventFunction) &MyFrame::OnAbout);
441
226ec5a7
WS
442 this->Connect(wxID_LOOP, wxEVT_COMMAND_MENU_SELECTED,
443 (wxObjectEventFunction) (wxEventFunction)
ff4aedc5
RN
444 (wxCommandEventFunction) &MyFrame::OnLoop);
445
10a53520
RN
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,
226ec5a7 451 (wxObjectEventFunction) (wxEventFunction)
10a53520
RN
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);
d0b9eaa2 465
226ec5a7
WS
466 this->Connect(wxID_PLAY, wxEVT_COMMAND_MENU_SELECTED,
467 (wxObjectEventFunction) (wxEventFunction)
ff4aedc5
RN
468 (wxCommandEventFunction) &MyFrame::OnPlay);
469
226ec5a7
WS
470 this->Connect(wxID_PAUSE, wxEVT_COMMAND_MENU_SELECTED,
471 (wxObjectEventFunction) (wxEventFunction)
ff4aedc5
RN
472 (wxCommandEventFunction) &MyFrame::OnPause);
473
226ec5a7
WS
474 this->Connect(wxID_STOP, wxEVT_COMMAND_MENU_SELECTED,
475 (wxObjectEventFunction) (wxEventFunction)
ff4aedc5
RN
476 (wxCommandEventFunction) &MyFrame::OnStop);
477
ff4aedc5 478 //
10a53520 479 // Notebook events
ff4aedc5 480 //
ecd20d4a
RN
481 this->Connect(wxID_NOTEBOOK, wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
482 (wxObjectEventFunction) (wxEventFunction)
483 (wxNotebookEventFunction) &MyFrame::OnPageChange);
484
ff4aedc5
RN
485 //
486 // End of Events
487 //
488
ff4aedc5
RN
489 //
490 // Create a timer to update our status bar
491 //
d0b9eaa2
RN
492 m_timer = new MyTimer(this);
493 m_timer->Start(100);
eaf0d558
RN
494}
495
ff4aedc5
RN
496// ----------------------------------------------------------------------------
497// MyFrame Destructor
d0b9eaa2 498//
226ec5a7 499// 1) Deletes child objects implicitly
ff4aedc5
RN
500// 2) Delete our timer explicitly
501// ----------------------------------------------------------------------------
eaf0d558
RN
502MyFrame::~MyFrame()
503{
d0b9eaa2 504 delete m_timer;
eaf0d558
RN
505}
506
ff4aedc5
RN
507// ----------------------------------------------------------------------------
508// MyFrame::ResetStatus
509//
226ec5a7 510// Here we just make a simple status string with some useful info about
ff4aedc5
RN
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
226ec5a7 514// set the status bar to this text.
d0b9eaa2 515//
ff4aedc5
RN
516// In real applications, you'd want to find a better way to do this,
517// such as static text controls (wxStaticText).
226ec5a7
WS
518//
519// We display info here in seconds (wxMediaCtrl uses milliseconds - that's why
ff4aedc5
RN
520// we divide by 1000).
521//
522// We also reset our loop counter here.
523// ----------------------------------------------------------------------------
524void MyFrame::ResetStatus()
525{
10a53520 526 wxMediaCtrl* currentMediaCtrl = GetCurrentMediaCtrl();
ecd20d4a 527
ff4aedc5
RN
528 m_basestatus = wxString::Format(_T("Size(x,y):%i,%i ")
529 _T("Length(Seconds):%u Speed:%1.1fx"),
10a53520
RN
530 currentMediaCtrl->GetBestSize().x,
531 currentMediaCtrl->GetBestSize().y,
532 (unsigned)((currentMediaCtrl->Length() / 1000)),
533 currentMediaCtrl->GetPlaybackRate()
ff4aedc5 534 );
10a53520 535}
ff4aedc5 536
10a53520
RN
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}
ff4aedc5 548
10a53520
RN
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;
ff4aedc5
RN
559}
560
561// ----------------------------------------------------------------------------
562// MyFrame::OnQuit
d0b9eaa2 563//
ff4aedc5
RN
564// Called from file->quit.
565// Closes this application.
566// ----------------------------------------------------------------------------
eaf0d558
RN
567void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
568{
569 // true is to force the frame to close
570 Close(true);
571}
572
ff4aedc5
RN
573// ----------------------------------------------------------------------------
574// MyFrame::OnAbout
226ec5a7 575//
ff4aedc5
RN
576// Called from help->about.
577// Gets some info about this application.
578// ----------------------------------------------------------------------------
eaf0d558
RN
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
ff4aedc5
RN
588// ----------------------------------------------------------------------------
589// MyFrame::OnLoop
d0b9eaa2 590//
ff4aedc5
RN
591// Called from file->loop.
592// Changes the state of whether we want to loop or not.
593// ----------------------------------------------------------------------------
eaf0d558
RN
594void MyFrame::OnLoop(wxCommandEvent& WXUNUSED(event))
595{
10a53520
RN
596 if(!m_notebook->GetCurrentPage())
597 {
598 wxMessageBox(wxT("No files are currently open!"));
599 return;
600 }
bc036010
RN
601
602 ((MyNotebookPage*)m_notebook->GetCurrentPage())->m_bLoop =
603 !((MyNotebookPage*)m_notebook->GetCurrentPage())->m_bLoop;
eaf0d558
RN
604}
605
ff4aedc5 606// ----------------------------------------------------------------------------
10a53520 607// MyFrame::OnOpenFileSamePage
d0b9eaa2 608//
ff4aedc5 609// Called from file->openfile.
10a53520
RN
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
ff4aedc5 628// ----------------------------------------------------------------------------
10a53520
RN
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)
eaf0d558
RN
642{
643 wxFileDialog fd(this);
644
645 if(fd.ShowModal() == wxID_OK)
646 {
10a53520
RN
647 if(bNewPage || !m_notebook->GetCurrentPage())
648 m_notebook->AddPage(new MyNotebookPage(m_notebook), fd.GetPath(), true);
ecd20d4a 649
10a53520 650 if( !GetCurrentMediaCtrl()->Load(fd.GetPath()) )
eaf0d558
RN
651 wxMessageBox(wxT("Couldn't load file!"));
652
10a53520 653 if( !GetCurrentMediaCtrl()->Play() )
ceefc965
WS
654 wxMessageBox(wxT("Couldn't play movie!"));
655
eaf0d558 656 ResetStatus();
10a53520
RN
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));
eaf0d558
RN
718 }
719}
720
10a53520
RN
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
ff4aedc5
RN
740// ----------------------------------------------------------------------------
741// MyFrame::OnPlay
226ec5a7 742//
ff4aedc5
RN
743// Called from file->play.
744// Resumes the media if it is paused or stopped.
745// ----------------------------------------------------------------------------
eaf0d558
RN
746void MyFrame::OnPlay(wxCommandEvent& WXUNUSED(event))
747{
10a53520
RN
748 if(!m_notebook->GetCurrentPage())
749 {
750 wxMessageBox(wxT("No files are currently open!"));
751 return;
752 }
753
754 if( !GetCurrentMediaCtrl()->Play() )
eaf0d558
RN
755 wxMessageBox(wxT("Couldn't play movie!"));
756}
757
ff4aedc5
RN
758// ----------------------------------------------------------------------------
759// MyFrame::OnPause
226ec5a7 760//
ff4aedc5
RN
761// Called from file->pause.
762// Pauses the media in-place.
763// ----------------------------------------------------------------------------
eaf0d558
RN
764void MyFrame::OnPause(wxCommandEvent& WXUNUSED(event))
765{
10a53520
RN
766 if(!m_notebook->GetCurrentPage())
767 {
768 wxMessageBox(wxT("No files are currently open!"));
769 return;
770 }
771
772 if( !GetCurrentMediaCtrl()->Pause() )
eaf0d558
RN
773 wxMessageBox(wxT("Couldn't pause movie!"));
774}
775
ff4aedc5
RN
776// ----------------------------------------------------------------------------
777// MyFrame::OnStop
226ec5a7 778//
ff4aedc5
RN
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// ----------------------------------------------------------------------------
eaf0d558
RN
785void MyFrame::OnStop(wxCommandEvent& WXUNUSED(event))
786{
10a53520
RN
787 if(!m_notebook->GetCurrentPage())
788 {
789 wxMessageBox(wxT("No files are currently open!"));
790 return;
791 }
eaf0d558 792
10a53520
RN
793 if( !GetCurrentMediaCtrl()->Stop() )
794 wxMessageBox(wxT("Couldn't stop movie!"));
eaf0d558
RN
795}
796
ff4aedc5 797// ----------------------------------------------------------------------------
10a53520 798// MyFrame::OnCloseCurrentPage
226ec5a7 799//
10a53520 800// Called when the user wants to closes the current notebook page
ff4aedc5 801// ----------------------------------------------------------------------------
ecd20d4a
RN
802
803void MyFrame::OnPageChange(wxNotebookEvent& WXUNUSED(event))
804{
805 ResetStatus();
806}
807
ff4aedc5 808// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
d0b9eaa2 809//
ff4aedc5 810// MyTimer
d0b9eaa2 811//
ff4aedc5
RN
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,
226ec5a7 819// append some non-static (changing) info to it, then set the
ff4aedc5
RN
820// status bar text to that result
821// ----------------------------------------------------------------------------
822void MyTimer::Notify()
eaf0d558 823{
10a53520 824 if (!m_frame->m_notebook->GetCurrentPage()) return;
ecd20d4a
RN
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);
ff4aedc5
RN
831
832#if wxUSE_STATUSBAR
833 m_frame->SetStatusText(wxString::Format(
10a53520 834 _T("%s Pos:%u State:%s Loops:%i"),
ff4aedc5
RN
835 m_frame->m_basestatus.c_str(),
836 (unsigned int)lPosition,
10a53520
RN
837 wxGetMediaStateText(m_mediactrl->GetState()),
838 ((MyNotebookPage*)m_frame->m_notebook->GetCurrentPage())->m_nLoops
ecd20d4a 839
ff4aedc5
RN
840 )
841 );
842#endif
ecd20d4a
RN
843
844}
845
846
10a53520
RN
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
ecd20d4a 860MyNotebookPage::MyNotebookPage(wxNotebook* theBook) :
bc036010 861 wxPanel(theBook, wxID_ANY), m_nLoops(0), m_bLoop(false)
ecd20d4a 862{
ecd20d4a
RN
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 //
dae87f93
RN
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
ecd20d4a
RN
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
10a53520
RN
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 //
bc036010 914 this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_FINISHED,
10a53520 915 (wxObjectEventFunction) (wxEventFunction)
bc036010 916 (wxMediaEventFunction) &MyNotebookPage::OnMediaFinished);
10a53520
RN
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!"));
ceefc965 932}
ff4aedc5 933
10a53520 934// ----------------------------------------------------------------------------
bc036010 935// OnMediaFinished
10a53520 936//
bc036010
RN
937// Called when the media stops playing.
938// Here we loop it if the user wants to (has been selected from file menu)
10a53520 939// ----------------------------------------------------------------------------
bc036010 940void MyNotebookPage::OnMediaFinished(wxMediaEvent& WXUNUSED(event))
10a53520 941{
bc036010
RN
942 if(m_bLoop)
943 {
944 if ( !m_mediactrl->Play() )
945 wxMessageBox(wxT("Couldn't loop movie!"));
946 else
947 ++m_nLoops;
948 }
10a53520 949}
ecd20d4a 950
ff4aedc5
RN
951//
952// End of MediaPlayer sample
953//