]> git.saurik.com Git - wxWidgets.git/blame - samples/mediaplayer/mediaplayer.cpp
use wxUSE_DATEPICKCTRL
[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//
29// 1) Not available on Unix :\.
30// 2) Certain backends can't play the same media file at the same time (MCI,
31// Cocoa NSMovieView/Quicktime).
32// 3) Positioning on Mac Carbon is messed up if put in a sub-control like a
33// Notebook (like this sample does).
34// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35
eaf0d558 36// ============================================================================
ff4aedc5 37// Definitions
eaf0d558
RN
38// ============================================================================
39
40// ----------------------------------------------------------------------------
ff4aedc5 41// Pre-compiled header stuff
eaf0d558
RN
42// ----------------------------------------------------------------------------
43
eaf0d558
RN
44#include "wx/wxprec.h"
45
46#ifdef __BORLANDC__
47 #pragma hdrstop
48#endif
49
eaf0d558
RN
50#ifndef WX_PRECOMP
51 #include "wx/wx.h"
52#endif
53
54// ----------------------------------------------------------------------------
ff4aedc5 55// Headers
eaf0d558
RN
56// ----------------------------------------------------------------------------
57
d0b9eaa2
RN
58#include "wx/mediactrl.h" //for wxMediaCtrl
59#include "wx/filedlg.h" //for opening files from OpenFile
60#include "wx/slider.h" //for a slider for seeking within media
61#include "wx/sizer.h" //for positioning controls/wxBoxSizer
62#include "wx/timer.h" //timer for updating status bar
63#include "wx/textdlg.h" //for getting user text from OpenURL
ecd20d4a 64#include "wx/notebook.h" //for wxNotebook and putting movies in pages
eaf0d558 65
10a53520
RN
66// Use some stuff that's not part of the current API, such as loading
67// media from a URL, etc.
68#define wxUSE_UNOFFICIALSTUFF 0
69
70//Libraries for MSVC with optional backends
71#ifdef _MSC_VER
72 #if wxUSE_DIRECTSHOW
73 #pragma comment(lib,"strmiids.lib")
74 #endif
75 #if wxUSE_QUICKTIME
76 #pragma comment(lib,"qtmlClient.lib")
77 #endif
78#endif
79
ff4aedc5 80// ----------------------------------------------------------------------------
226ec5a7 81// Bail out if the user doesn't want one of the
ff4aedc5
RN
82// things we need
83// ----------------------------------------------------------------------------
eaf0d558 84
ff4aedc5
RN
85#if !wxUSE_GUI
86#error "This is a GUI sample"
eaf0d558
RN
87#endif
88
ecd20d4a
RN
89#if !wxUSE_MEDIACTRL || !wxUSE_MENUS || !wxUSE_SLIDER || !wxUSE_TIMER || !wxUSE_NOTEBOOK
90#error "menus, slider, mediactrl, notebook, and timers must all be enabled for this sample!"
ff4aedc5
RN
91#endif
92
93// ============================================================================
d0b9eaa2 94// Declarations
ff4aedc5
RN
95// ============================================================================
96
97// ----------------------------------------------------------------------------
98// Enumurations
99// ----------------------------------------------------------------------------
100
101// IDs for the controls and the menu commands
102enum
103{
104 // menu items
105 wxID_LOOP = 1,
10a53520
RN
106 wxID_OPENFILESAMEPAGE,
107 wxID_OPENFILENEWPAGE,
108 wxID_OPENURLSAMEPAGE,
109 wxID_OPENURLNEWPAGE,
110 wxID_CLOSECURRENTPAGE,
ff4aedc5
RN
111 wxID_PLAY,
112 wxID_PAUSE,
113// wxID_STOP, [built-in to wxWidgets]
114// wxID_ABOUT, [built-in to wxWidgets]
115// wxID_EXIT, [built-in to wxWidgets]
116
10a53520 117 // event id for our slider
ff4aedc5
RN
118 wxID_SLIDER,
119
10a53520 120 // event id for our notebook
ecd20d4a 121 wxID_NOTEBOOK,
10a53520
RN
122
123 // event id for our wxMediaCtrl
ff4aedc5
RN
124 wxID_MEDIACTRL
125};
126
127// ----------------------------------------------------------------------------
128// MyApp
eaf0d558
RN
129// ----------------------------------------------------------------------------
130
eaf0d558
RN
131class MyApp : public wxApp
132{
133public:
eaf0d558
RN
134 virtual bool OnInit();
135};
136
ff4aedc5
RN
137// ----------------------------------------------------------------------------
138// MyFrame
139// ----------------------------------------------------------------------------
140
eaf0d558
RN
141class MyFrame : public wxFrame
142{
143public:
ff4aedc5 144 // Ctor/Dtor
eaf0d558
RN
145 MyFrame(const wxString& title);
146 ~MyFrame();
147
ff4aedc5 148 // Menu event handlers
eaf0d558
RN
149 void OnQuit(wxCommandEvent& event);
150 void OnAbout(wxCommandEvent& event);
151 void OnLoop(wxCommandEvent& event);
152
10a53520
RN
153 void OnOpenFileSamePage(wxCommandEvent& event);
154 void OnOpenFileNewPage(wxCommandEvent& event);
155 void OnOpenURLSamePage(wxCommandEvent& event);
156 void OnOpenURLNewPage(wxCommandEvent& event);
157 void OnCloseCurrentPage(wxCommandEvent& event);
eaf0d558
RN
158
159 void OnPlay(wxCommandEvent& event);
160 void OnPause(wxCommandEvent& event);
161 void OnStop(wxCommandEvent& event);
162
10a53520 163 // Notebook event handlers
ecd20d4a 164 void OnPageChange(wxNotebookEvent& event);
eaf0d558
RN
165
166private:
ff4aedc5 167 // Rebuild base status string (see Implementation)
d0b9eaa2
RN
168 void ResetStatus();
169
10a53520
RN
170 // Common open file code
171 void OpenFile(bool bNewPage);
172 void OpenURL(bool bNewPage);
173
174 // Get the media control and slider of current notebook page
175 wxMediaCtrl* GetCurrentMediaCtrl();
176 wxSlider* GetCurrentSlider();
177
ff4aedc5
RN
178 class MyTimer* m_timer; //Timer to write info to status bar
179 wxString m_basestatus; //Base status string (see ResetStatus())
ecd20d4a 180 wxNotebook* m_notebook;
ff4aedc5
RN
181
182 // So that mytimer can access MyFrame's members
eaf0d558 183 friend class MyTimer;
ff4aedc5 184};
eaf0d558 185
10a53520
RN
186
187
188// ----------------------------------------------------------------------------
189// MyNotebookPage
190// ----------------------------------------------------------------------------
191
ecd20d4a
RN
192class MyNotebookPage : public wxPanel
193{
10a53520 194 MyNotebookPage(wxNotebook* book);
ecd20d4a 195
10a53520
RN
196 // Slider event handlers
197 void OnSeek(wxCommandEvent& event);
198
199 // Media event handlers
200 void OnMediaStop(wxMediaEvent& event);
ecd20d4a
RN
201
202public:
10a53520 203 friend class MyFrame; //make MyFrame able to access private members
ecd20d4a
RN
204 wxMediaCtrl* m_mediactrl; //Our media control
205 wxSlider* m_slider; //The slider below our media control
10a53520 206 int m_nLoops; //Number of times media has looped
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
RN
417 // this is of historical relevance only and is
418 // there only for backwards compatability.
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 }
601 GetCurrentMediaCtrl()->Loop( !GetCurrentMediaCtrl()->IsLooped() );
eaf0d558
RN
602}
603
ff4aedc5 604// ----------------------------------------------------------------------------
10a53520 605// MyFrame::OnOpenFileSamePage
d0b9eaa2 606//
ff4aedc5 607// Called from file->openfile.
10a53520
RN
608// Opens and plays a media file in the current notebook page
609// ----------------------------------------------------------------------------
610void MyFrame::OnOpenFileSamePage(wxCommandEvent& WXUNUSED(event))
611{
612 OpenFile(false);
613}
614
615// ----------------------------------------------------------------------------
616// MyFrame::OnOpenFileNewPage
617//
618// Called from file->openfileinnewpage.
619// Opens and plays a media file in a new notebook page
620// ----------------------------------------------------------------------------
621void MyFrame::OnOpenFileNewPage(wxCommandEvent& WXUNUSED(event))
622{
623 OpenFile(true);
624}
625
ff4aedc5 626// ----------------------------------------------------------------------------
10a53520
RN
627// MyFrame::OpenFile
628//
629// Code to actually open the media file
630//
631// 1) Create file dialog and ask the user for input file
632// 2) If the user didn't want anything, break out
633// 3) Create a new page if the user wanted one or there isn't a current page
634// 4) Load the media
635// 5) Play the media
636// 6) Reset the text on the status bar
637// 7) Set the slider of the current page to accurately reflect media length
638// ----------------------------------------------------------------------------
639void MyFrame::OpenFile(bool bNewPage)
eaf0d558
RN
640{
641 wxFileDialog fd(this);
642
643 if(fd.ShowModal() == wxID_OK)
644 {
10a53520
RN
645 if(bNewPage || !m_notebook->GetCurrentPage())
646 m_notebook->AddPage(new MyNotebookPage(m_notebook), fd.GetPath(), true);
ecd20d4a 647
10a53520 648 if( !GetCurrentMediaCtrl()->Load(fd.GetPath()) )
eaf0d558
RN
649 wxMessageBox(wxT("Couldn't load file!"));
650
10a53520 651 if( !GetCurrentMediaCtrl()->Play() )
ceefc965
WS
652 wxMessageBox(wxT("Couldn't play movie!"));
653
eaf0d558 654 ResetStatus();
10a53520
RN
655
656 GetCurrentSlider()->SetRange(0,
657 (int)(GetCurrentMediaCtrl()->Length() / 1000));
658
659 }
660}
661
662// ----------------------------------------------------------------------------
663// MyFrame::OnOpenURLSamePage
664//
665// Called from file->openurl.
666// Opens and plays a media file from a URL in the current notebook page
667// ----------------------------------------------------------------------------
668void MyFrame::OnOpenURLSamePage(wxCommandEvent& WXUNUSED(event))
669{
670 OpenURL(false);
671}
672
673// ----------------------------------------------------------------------------
674// MyFrame::OnOpenURLNewPage
675//
676// Called from file->openurlinnewpage.
677// Opens and plays a media file from a URL in a new notebook page
678// ----------------------------------------------------------------------------
679void MyFrame::OnOpenURLNewPage(wxCommandEvent& WXUNUSED(event))
680{
681 OpenURL(true);
682}
683
684// ----------------------------------------------------------------------------
685// MyFrame::OpenURL
686//
687// Code to actually open the media file from a URL
688//
689// 1) Create text input dialog and ask the user for an input URL
690// 2) If the user didn't want anything, break out
691// 3) Create a new page if the user wanted one or there isn't a current page
692// 4) Load the media
693// 5) Play the media
694// 6) Reset the text on the status bar
695// 7) Set the slider of the current page to accurately reflect media length
696// ----------------------------------------------------------------------------
697void MyFrame::OpenURL(bool bNewPage)
698{
699 wxString theURL = wxGetTextFromUser(wxT("Enter the URL that has the movie to play"));
700
701 if(!theURL.empty())
702 {
703 if(bNewPage || !m_notebook->GetCurrentPage())
704 m_notebook->AddPage(new MyNotebookPage(m_notebook), theURL, true);
705
706 if( !GetCurrentMediaCtrl()->Load(wxURI(theURL)) )
707 wxMessageBox(wxT("Couldn't load URL!"));
708
709 if( !GetCurrentMediaCtrl()->Play() )
710 wxMessageBox(wxT("Couldn't play movie!"));
711
712 ResetStatus();
713
714 GetCurrentSlider()->SetRange(0,
715 (int)(GetCurrentMediaCtrl()->Length() / 1000));
eaf0d558
RN
716 }
717}
718
10a53520
RN
719// ----------------------------------------------------------------------------
720// MyFrame::OnCloseCurrentPage
721//
722// Called when the user wants to close the current notebook page
723//
724// 1) Get the current page number (wxControl::GetSelection)
725// 2) If there is no current page, break out
726// 3) Delete the current page
727// ----------------------------------------------------------------------------
728void MyFrame::OnCloseCurrentPage(wxCommandEvent& WXUNUSED(event))
729{
730 int sel = m_notebook->GetSelection();
731
732 if (sel != wxNOT_FOUND)
733 {
734 m_notebook->DeletePage(sel);
735 }
736}
737
ff4aedc5
RN
738// ----------------------------------------------------------------------------
739// MyFrame::OnPlay
226ec5a7 740//
ff4aedc5
RN
741// Called from file->play.
742// Resumes the media if it is paused or stopped.
743// ----------------------------------------------------------------------------
eaf0d558
RN
744void MyFrame::OnPlay(wxCommandEvent& WXUNUSED(event))
745{
10a53520
RN
746 if(!m_notebook->GetCurrentPage())
747 {
748 wxMessageBox(wxT("No files are currently open!"));
749 return;
750 }
751
752 if( !GetCurrentMediaCtrl()->Play() )
eaf0d558
RN
753 wxMessageBox(wxT("Couldn't play movie!"));
754}
755
ff4aedc5
RN
756// ----------------------------------------------------------------------------
757// MyFrame::OnPause
226ec5a7 758//
ff4aedc5
RN
759// Called from file->pause.
760// Pauses the media in-place.
761// ----------------------------------------------------------------------------
eaf0d558
RN
762void MyFrame::OnPause(wxCommandEvent& WXUNUSED(event))
763{
10a53520
RN
764 if(!m_notebook->GetCurrentPage())
765 {
766 wxMessageBox(wxT("No files are currently open!"));
767 return;
768 }
769
770 if( !GetCurrentMediaCtrl()->Pause() )
eaf0d558
RN
771 wxMessageBox(wxT("Couldn't pause movie!"));
772}
773
ff4aedc5
RN
774// ----------------------------------------------------------------------------
775// MyFrame::OnStop
226ec5a7 776//
ff4aedc5
RN
777// Called from file->stop.
778// Where it stops depends on whether you can seek in the
779// media control or not - if you can it stops and seeks to the beginning,
780// otherwise it will appear to be at the end - but it will start over again
781// when Play() is called
782// ----------------------------------------------------------------------------
eaf0d558
RN
783void MyFrame::OnStop(wxCommandEvent& WXUNUSED(event))
784{
10a53520
RN
785 if(!m_notebook->GetCurrentPage())
786 {
787 wxMessageBox(wxT("No files are currently open!"));
788 return;
789 }
eaf0d558 790
10a53520
RN
791 if( !GetCurrentMediaCtrl()->Stop() )
792 wxMessageBox(wxT("Couldn't stop movie!"));
eaf0d558
RN
793}
794
ff4aedc5 795// ----------------------------------------------------------------------------
10a53520 796// MyFrame::OnCloseCurrentPage
226ec5a7 797//
10a53520 798// Called when the user wants to closes the current notebook page
ff4aedc5 799// ----------------------------------------------------------------------------
ecd20d4a
RN
800
801void MyFrame::OnPageChange(wxNotebookEvent& WXUNUSED(event))
802{
803 ResetStatus();
804}
805
ff4aedc5 806// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
d0b9eaa2 807//
ff4aedc5 808// MyTimer
d0b9eaa2 809//
ff4aedc5
RN
810// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
811
812// ----------------------------------------------------------------------------
813// MyTimer::Notify
814//
815// 1) Update our slider with the position were are in in the media
816// 2) Update our status bar with the base text from MyFrame::ResetStatus,
226ec5a7 817// append some non-static (changing) info to it, then set the
ff4aedc5
RN
818// status bar text to that result
819// ----------------------------------------------------------------------------
820void MyTimer::Notify()
eaf0d558 821{
10a53520 822 if (!m_frame->m_notebook->GetCurrentPage()) return;
ecd20d4a
RN
823 wxMediaCtrl* m_mediactrl = ((MyNotebookPage*)m_frame->m_notebook->GetCurrentPage())->m_mediactrl;
824 wxSlider* m_slider = ((MyNotebookPage*)m_frame->m_notebook->GetCurrentPage())->m_slider;
825 if (!m_mediactrl) return;
826
827 long lPosition = (long)( m_mediactrl->Tell() / 1000 );
828 m_slider->SetValue(lPosition);
ff4aedc5
RN
829
830#if wxUSE_STATUSBAR
831 m_frame->SetStatusText(wxString::Format(
10a53520 832 _T("%s Pos:%u State:%s Loops:%i"),
ff4aedc5
RN
833 m_frame->m_basestatus.c_str(),
834 (unsigned int)lPosition,
10a53520
RN
835 wxGetMediaStateText(m_mediactrl->GetState()),
836 ((MyNotebookPage*)m_frame->m_notebook->GetCurrentPage())->m_nLoops
ecd20d4a 837
ff4aedc5
RN
838 )
839 );
840#endif
ecd20d4a
RN
841
842}
843
844
10a53520
RN
845// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
846//
847// MyNotebookPage
848//
849// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
850
851// ----------------------------------------------------------------------------
852// MyNotebookPage Constructor
853//
854// Creates a media control and slider and adds it to this panel,
855// along with some sizers for positioning
856// ----------------------------------------------------------------------------
857
ecd20d4a 858MyNotebookPage::MyNotebookPage(wxNotebook* theBook) :
10a53520 859 wxPanel(theBook, wxID_ANY), m_nLoops(0)
ecd20d4a 860{
ecd20d4a
RN
861 //
862 // Create and attach the first/main sizer
863 //
864 wxBoxSizer* vertsizer = new wxBoxSizer(wxVERTICAL);
865 this->SetSizer(vertsizer);
866 this->SetAutoLayout(true);
867
868 //
869 // Create our media control
870 //
871 m_mediactrl = new wxMediaCtrl(this, wxID_MEDIACTRL);
872 vertsizer->Add(m_mediactrl, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
873
874 //
875 // Create our slider
876 //
877 m_slider = new wxSlider(this, wxID_SLIDER, 0, //init
878 0, //start
879 0, //end
880 wxDefaultPosition, wxDefaultSize,
881 wxSL_HORIZONTAL );
882 vertsizer->Add(m_slider, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5);
883
884
885 //
886 // Create the second sizer which will position things
887 // vertically -
888 //
889 // -------Menu----------
890 // [m_mediactrl]
891 //
892 // [m_slider]
893 //
894 wxBoxSizer* horzsizer = new wxBoxSizer(wxHORIZONTAL);
895 vertsizer->Add(horzsizer, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
896
10a53520
RN
897 //
898 // Slider events
899 //
900 this->Connect(wxID_SLIDER, wxEVT_COMMAND_SLIDER_UPDATED,
901 (wxObjectEventFunction) (wxEventFunction)
902 (wxCommandEventFunction) &MyNotebookPage::OnSeek);
903
904 //
905 // Media Control events
906 //
907 this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_STOP,
908 (wxObjectEventFunction) (wxEventFunction)
909 (wxMediaEventFunction) &MyNotebookPage::OnMediaStop);
910}
911
912// ----------------------------------------------------------------------------
913// MyNotebook::OnSeek
914//
915// Called from file->seek.
916// Called when the user moves the slider -
917// seeks to a position within the media
918// ----------------------------------------------------------------------------
919void MyNotebookPage::OnSeek(wxCommandEvent& WXUNUSED(event))
920{
921 if( m_mediactrl->Seek(
922 m_slider->GetValue() * 1000
923 ) == wxInvalidOffset )
924 wxMessageBox(wxT("Couldn't seek in movie!"));
ceefc965 925}
ff4aedc5 926
10a53520
RN
927// ----------------------------------------------------------------------------
928// MyNotebookPage::OnMediaStop
929//
930// Called when the media is about to stop playing.
931// ----------------------------------------------------------------------------
932void MyNotebookPage::OnMediaStop(wxMediaEvent& WXUNUSED(event))
933{
934 if(m_mediactrl->IsLooped())
935 ++m_nLoops;
936}
ecd20d4a 937
ff4aedc5
RN
938//
939// End of MediaPlayer sample
940//