1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        mediaplayer.cpp
3 // Purpose:     wxMediaCtrl sample
4 // Author:      Ryan Norton
5 // Modified by:
6 // Created:     11/10/04
7 // RCS-ID:      $Id: mediaplayer.cpp 37461 2006-02-10 19:37:40Z VZ $
8 // Copyright:   (c) Ryan Norton
9 // Licence:     wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11 
12 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 // MediaPlayer
14 //
15 // This is a somewhat comprehensive example of how to use all the funtionality
16 // of the wxMediaCtrl class in wxWidgets.
17 //
18 // To use this sample, simply select Open File from the file menu,
19 // select the file you want to play - and MediaPlayer will play the file in a
20 // the current notebook page, showing video if necessary.
21 //
22 // You can select one of the menu options, or move the slider around
23 // to manipulate what is playing.
24 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
25 
26 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
27 // Known bugs with wxMediaCtrl:
28 //
29 // 1) Certain backends can't play the same media file at the same time (MCI,
30 //    Cocoa NSMovieView-Quicktime).
31 // 2) Positioning on Mac Carbon is messed up if put in a sub-control like a
32 //    Notebook (like this sample does).
33 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34 
35 // ============================================================================
36 // Definitions
37 // ============================================================================
38 
39 // ----------------------------------------------------------------------------
40 // Pre-compiled header stuff
41 // ----------------------------------------------------------------------------
42 
43 #include "wx/wxprec.h"
44 
45 #ifdef __BORLANDC__
46     #pragma hdrstop
47 #endif
48 
49 #ifndef WX_PRECOMP
50     #include "wx/wx.h"
51 #endif
52 
53 // ----------------------------------------------------------------------------
54 // Headers
55 // ----------------------------------------------------------------------------
56 
57 #include "wx/mediactrl.h"   //for wxMediaCtrl
58 #include "wx/filedlg.h"     //for opening files from OpenFile
59 #include "wx/slider.h"      //for a slider for seeking within media
60 #include "wx/sizer.h"       //for positioning controls/wxBoxSizer
61 #include "wx/timer.h"       //timer for updating status bar
62 #include "wx/textdlg.h"     //for getting user text from OpenURL/Debug
63 #include "wx/notebook.h"    //for wxNotebook and putting movies in pages
64 #include "wx/cmdline.h"     //for wxCmdLineParser (optional)
65 #include "wx/listctrl.h"    //for wxListCtrl
66 #include "wx/dnd.h"         //drag and drop for the playlist
67 #include "wx/filename.h"    //For wxFileName::GetName()
68 #include "wx/config.h"      //for native wxConfig
69 
70 // ----------------------------------------------------------------------------
71 // Bail out if the user doesn't want one of the
72 // things we need
73 // ----------------------------------------------------------------------------
74 
75 // RN:  I'm not sure why this is here - even minimal doesn't check for
76 //      wxUSE_GUI.  I may have added it myself though...
77 #if !wxUSE_GUI
78 #error "This is a GUI sample"
79 #endif
80 
81 #if !wxUSE_MEDIACTRL || !wxUSE_MENUS || !wxUSE_SLIDER || !wxUSE_TIMER || \
82     !wxUSE_NOTEBOOK || !wxUSE_LISTCTRL
83 #error "Not all required elements are enabled.  Please modify setup.h!"
84 #endif
85 
86 // ============================================================================
87 // Declarations
88 // ============================================================================
89 
90 // ----------------------------------------------------------------------------
91 // Enumurations
92 // ----------------------------------------------------------------------------
93 
94 // IDs for the controls and the menu commands
95 enum
96 {
97     // Menu event IDs
98     wxID_LOOP = 1,
99     wxID_OPENFILESAMEPAGE,
100     wxID_OPENFILENEWPAGE,
101     wxID_OPENURLSAMEPAGE,
102     wxID_OPENURLNEWPAGE,
103     wxID_CLOSECURRENTPAGE,
104     wxID_PLAY,
105     wxID_PAUSE,
106     wxID_NEXT,
107     wxID_PREV,
108     wxID_SELECTBACKEND,
109     wxID_SHOWINTERFACE,
110 //    wxID_STOP,   [built-in to wxWidgets]
111 //    wxID_ABOUT,  [built-in to wxWidgets]
112 //    wxID_EXIT,   [built-in to wxWidgets]
113     // Control event IDs
114     wxID_SLIDER,
115     wxID_PBSLIDER,
116     wxID_VOLSLIDER,
117     wxID_NOTEBOOK,
118     wxID_MEDIACTRL,
119     wxID_BUTTONNEXT,
120     wxID_BUTTONPREV,
121     wxID_BUTTONSTOP,
122     wxID_BUTTONPLAY,
123     wxID_BUTTONVD,
124     wxID_BUTTONVU,
125     wxID_LISTCTRL,
126     wxID_GAUGE
127 };
128 
129 // ----------------------------------------------------------------------------
130 // wxMediaPlayerApp
131 // ----------------------------------------------------------------------------
132 
133 class wxMediaPlayerApp : public wxApp
134 {
135 public:
136 #ifdef __WXMAC__
137     virtual void MacOpenFile(const wxString & fileName );
138 #endif
139 
140     virtual bool OnInit();
141 
142 protected:
143     class wxMediaPlayerFrame* m_frame;
144 };
145 
146 // ----------------------------------------------------------------------------
147 // wxMediaPlayerFrame
148 // ----------------------------------------------------------------------------
149 
150 class wxMediaPlayerFrame : public wxFrame
151 {
152 public:
153     // Ctor/Dtor
154     wxMediaPlayerFrame(const wxString& title);
155     ~wxMediaPlayerFrame();
156 
157     // Menu event handlers
158     void OnQuit(wxCommandEvent& event);
159     void OnAbout(wxCommandEvent& event);
160 
161     void OnOpenFileSamePage(wxCommandEvent& event);
162     void OnOpenFileNewPage(wxCommandEvent& event);
163     void OnOpenURLSamePage(wxCommandEvent& event);
164     void OnOpenURLNewPage(wxCommandEvent& event);
165     void OnCloseCurrentPage(wxCommandEvent& event);
166 
167     void OnPlay(wxCommandEvent& event);
168     void OnPause(wxCommandEvent& event);
169     void OnStop(wxCommandEvent& event);
170     void OnNext(wxCommandEvent& event);
171     void OnPrev(wxCommandEvent& event);
172     void OnVolumeDown(wxCommandEvent& event);
173     void OnVolumeUp(wxCommandEvent& event);
174 
175     void OnLoop(wxCommandEvent& event);
176     void OnShowInterface(wxCommandEvent& event);
177 
178     void OnSelectBackend(wxCommandEvent& event);
179 
180     // Key event handlers
181     void OnKeyDown(wxKeyEvent& event);
182 
183     // Quickie for playing from command line
184     void AddToPlayList(const wxString& szString);
185 
186     // ListCtrl event handlers
187     void OnChangeSong(wxListEvent& event);
188 
189     // Media event handlers
190     void OnMediaLoaded(wxMediaEvent& event);
191 
192     // Close event handlers
193     void OnClose(wxCloseEvent& event);
194 
195 private:
196     // Common open file code
197     void OpenFile(bool bNewPage);
198     void OpenURL(bool bNewPage);
199     void DoOpenFile(const wxString& path, bool bNewPage);
200     void DoPlayFile(const wxString& path);
201 
202     class wxMediaPlayerTimer* m_timer;     //Timer to write info to status bar
203     wxNotebook* m_notebook;     //Notebook containing our pages
204 
205     // Maybe I should use more accessors, but for simplicity
206     // I'll allow the other classes access to our members
207     friend class wxMediaPlayerApp;
208     friend class wxMediaPlayerNotebookPage;
209     friend class wxMediaPlayerTimer;
210 };
211 
212 
213 
214 // ----------------------------------------------------------------------------
215 // wxMediaPlayerNotebookPage
216 // ----------------------------------------------------------------------------
217 
218 class wxMediaPlayerNotebookPage : public wxPanel
219 {
220     wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentFrame,
221         wxNotebook* book, const wxString& be = wxEmptyString);
222 
223     // Slider event handlers
224     void OnBeginSeek(wxScrollEvent& event);
225     void OnEndSeek(wxScrollEvent& event);
226     void OnPBChange(wxScrollEvent& event);
227     void OnVolChange(wxScrollEvent& event);
228 
229     // Media event handlers
230     void OnMediaPlay(wxMediaEvent& event);
231     void OnMediaPause(wxMediaEvent& event);
232     void OnMediaStop(wxMediaEvent& event);
233     void OnMediaFinished(wxMediaEvent& event);
234 
235 public:
236     bool IsBeingDragged();      //accessor for m_bIsBeingDragged
237 
238     //make wxMediaPlayerFrame able to access the private members
239     friend class wxMediaPlayerFrame;
240 
241     int      m_nLastFileId;     //List ID of played file in listctrl
242     wxString m_szFile;          //Name of currently playing file/location
243 
244     wxMediaCtrl* m_mediactrl;   //Our media control
245     class wxMediaPlayerListCtrl* m_playlist;  //Our playlist
246     wxSlider* m_slider;         //The slider below our media control
247     wxSlider* m_pbSlider;       //Lower-left slider for adjusting speed
248     wxSlider* m_volSlider;      //Lower-right slider for adjusting volume
249     int m_nLoops;               //Number of times media has looped
250     bool m_bLoop;               //Whether we are looping or not
251     bool m_bIsBeingDragged;     //Whether the user is dragging the scroll bar
252     wxMediaPlayerFrame* m_parentFrame;  //Main wxFrame of our sample
253     wxButton* m_prevButton;     //Go to previous file button
254     wxButton* m_playButton;     //Play/pause file button
255     wxButton* m_stopButton;     //Stop playing file button
256     wxButton* m_nextButton;     //Next file button
257     wxButton* m_vdButton;       //Volume down button
258     wxButton* m_vuButton;       //Volume up button
259     wxGauge*  m_gauge;          //Gauge to keep in line with slider
260 };
261 
262 // ----------------------------------------------------------------------------
263 // wxMediaPlayerTimer
264 // ----------------------------------------------------------------------------
265 
266 class wxMediaPlayerTimer : public wxTimer
267 {
268 public:
269     //Ctor
wxMediaPlayerTimer(wxMediaPlayerFrame * frame)270     wxMediaPlayerTimer(wxMediaPlayerFrame* frame) {m_frame = frame;}
271 
272     //Called each time the timer's timeout expires
273     void Notify();
274 
275     wxMediaPlayerFrame* m_frame;       //The wxMediaPlayerFrame
276 };
277 
278 // ----------------------------------------------------------------------------
279 // wxMediaPlayerListCtrl
280 // ----------------------------------------------------------------------------
281 class wxMediaPlayerListCtrl : public wxListCtrl
282 {
283 public:
AddToPlayList(const wxString & szString)284     void AddToPlayList(const wxString& szString)
285     {
286         wxListItem kNewItem;
287         kNewItem.SetAlign(wxLIST_FORMAT_LEFT);
288 
289         int nID = this->GetItemCount();
290         kNewItem.SetId(nID);
291         kNewItem.SetMask(wxLIST_MASK_DATA);
292         kNewItem.SetData(new wxString(szString));
293 
294         this->InsertItem(kNewItem);
295         this->SetItem(nID, 0, wxT("*"));
296         this->SetItem(nID, 1, wxFileName(szString).GetName());
297 
298         if (nID % 2)
299         {
300             kNewItem.SetBackgroundColour(wxColour(192,192,192));
301             this->SetItem(kNewItem);
302         }
303     }
304 
GetSelectedItem(wxListItem & listitem)305     void GetSelectedItem(wxListItem& listitem)
306     {
307         listitem.SetMask(wxLIST_MASK_TEXT |  wxLIST_MASK_DATA);
308         int nLast = -1, nLastSelected = -1;
309         while ((nLast = this->GetNextItem(nLast,
310                                          wxLIST_NEXT_ALL,
311                                          wxLIST_STATE_SELECTED)) != -1)
312         {
313             listitem.SetId(nLast);
314             this->GetItem(listitem);
315             if ((listitem.GetState() & wxLIST_STATE_FOCUSED) )
316                 break;
317             nLastSelected = nLast;
318         }
319         if (nLast == -1 && nLastSelected == -1)
320             return;
321         listitem.SetId(nLastSelected == -1 ? nLast : nLastSelected);
322         this->GetItem(listitem);
323     }
324 };
325 
326 // ----------------------------------------------------------------------------
327 // wxPlayListDropTarget
328 //
329 //  Drop target for playlist (i.e. user drags a file from explorer unto
330 //  playlist it adds the file)
331 // ----------------------------------------------------------------------------
332 #if wxUSE_DRAG_AND_DROP
333 class wxPlayListDropTarget : public wxFileDropTarget
334 {
335 public:
wxPlayListDropTarget(wxMediaPlayerListCtrl & list)336     wxPlayListDropTarget(wxMediaPlayerListCtrl& list) : m_list(list) {}
~wxPlayListDropTarget()337     ~wxPlayListDropTarget(){}
OnDropFiles(wxCoord WXUNUSED (x),wxCoord WXUNUSED (y),const wxArrayString & files)338         virtual bool OnDropFiles(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
339                          const wxArrayString& files)
340     {
341         for (size_t i = 0; i < files.GetCount(); ++i)
342         {
343             m_list.AddToPlayList(files[i]);
344         }
345         return true;
346     }
347     wxMediaPlayerListCtrl& m_list;
348 };
349 #endif
350 
351 // ============================================================================
352 //
353 // Implementation
354 //
355 // ============================================================================
356 
357 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
358 //
359 // [Functions]
360 //
361 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
362 
363 // ----------------------------------------------------------------------------
364 // wxGetMediaStateText
365 //
366 // Converts a wxMediaCtrl state into something useful that we can display
367 // to the user
368 // ----------------------------------------------------------------------------
wxGetMediaStateText(int nState)369 const wxChar* wxGetMediaStateText(int nState)
370 {
371     switch(nState)
372     {
373         case wxMEDIASTATE_PLAYING:
374             return wxT("Playing");
375         case wxMEDIASTATE_STOPPED:
376             return wxT("Stopped");
377         ///case wxMEDIASTATE_PAUSED:
378         default:
379             return wxT("Paused");
380     }
381 }
382 
383 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
384 //
385 // wxMediaPlayerApp
386 //
387 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
388 
389 // ----------------------------------------------------------------------------
390 // This sets up this wxApp as the global wxApp that gui calls in wxWidgets
391 // use.  For example, if you were to be in windows and use a file dialog,
392 // wxWidgets would use wxTheApp->GetHInstance() which would get the instance
393 // handle of the application.  These routines in wx _DO NOT_ check to see if
394 // the wxApp exists, and thus will crash the application if you try it.
395 //
396 // IMPLEMENT_APP does this, and also implements the platform-specific entry
397 // routine, such as main or WinMain().  Use IMPLEMENT_APP_NO_MAIN if you do
398 // not desire this behavior.
399 // ----------------------------------------------------------------------------
IMPLEMENT_APP(wxMediaPlayerApp)400 IMPLEMENT_APP(wxMediaPlayerApp)
401 
402 // ----------------------------------------------------------------------------
403 // wxMediaPlayerApp::OnInit
404 //
405 // Where execution starts - akin to a main or WinMain.
406 // 1) Create the frame and show it to the user
407 // 2) Process filenames from the commandline
408 // 3) return true specifying that we want execution to continue past OnInit
409 // ----------------------------------------------------------------------------
410 bool wxMediaPlayerApp::OnInit()
411 {
412     // SetAppName() lets wxConfig and others know where to write
413     SetAppName(wxT("wxMediaPlayer"));
414 
415     wxMediaPlayerFrame *frame =
416         new wxMediaPlayerFrame(wxT("MediaPlayer wxWidgets Sample"));
417     frame->Show(true);
418 
419 #if wxUSE_CMDLINE_PARSER
420     //
421     //  What this does is get all the command line arguments
422     //  and treat each one as a file to put to the initial playlist
423     //
424     wxCmdLineEntryDesc cmdLineDesc[2];
425     cmdLineDesc[0].kind = wxCMD_LINE_PARAM;
426     cmdLineDesc[0].shortName = NULL;
427     cmdLineDesc[0].longName = NULL;
428     cmdLineDesc[0].description = wxT("input files");
429     cmdLineDesc[0].type = wxCMD_LINE_VAL_STRING;
430     cmdLineDesc[0].flags = wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE;
431 
432     cmdLineDesc[1].kind = wxCMD_LINE_NONE;
433 
434     //gets the passed media files from cmd line
435     wxCmdLineParser parser (cmdLineDesc, argc, argv);
436 
437     // get filenames from the commandline
438     if (parser.Parse() == 0)
439     {
440         for (size_t paramNr=0; paramNr < parser.GetParamCount(); ++paramNr)
441         {
442             frame->AddToPlayList((parser.GetParam (paramNr)));
443         }
444         wxCommandEvent theEvent(wxEVT_COMMAND_MENU_SELECTED, wxID_NEXT);
445         frame->AddPendingEvent(theEvent);
446     }
447 #endif
448 
449     return true;
450 }
451 
452 #ifdef __WXMAC__
453 
MacOpenFile(const wxString & fileName)454 void wxMediaPlayerApp::MacOpenFile(const wxString & fileName )
455 {
456     //Called when a user drags a file over our app
457     m_frame->DoOpenFile(fileName, true /* new page */);
458 }
459 
460 #endif // __WXMAC__
461 
462 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
463 //
464 // wxMediaPlayerFrame
465 //
466 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
467 
468 // ----------------------------------------------------------------------------
469 // wxMediaPlayerFrame Constructor
470 //
471 // 1) Create our menus
472 // 2) Create our notebook control and add it to the frame
473 // 3) Create our status bar
474 // 4) Connect our events
475 // 5) Start our timer
476 // ----------------------------------------------------------------------------
477 
wxMediaPlayerFrame(const wxString & title)478 wxMediaPlayerFrame::wxMediaPlayerFrame(const wxString& title)
479        : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(600,600))
480 {
481     //
482     //  Create Menus
483     //
484     wxMenu *fileMenu = new wxMenu;
485     wxMenu *controlsMenu = new wxMenu;
486     wxMenu *optionsMenu = new wxMenu;
487     wxMenu *helpMenu = new wxMenu;
488     wxMenu *debugMenu = new wxMenu;
489 
490     fileMenu->Append(wxID_OPENFILESAMEPAGE, wxT("&Open File\tCtrl-Shift-O"),
491                         wxT("Open a File in the current notebook page"));
492     fileMenu->Append(wxID_OPENFILENEWPAGE, wxT("&Open File in a new page"),
493                         wxT("Open a File in a new notebook page"));
494     fileMenu->Append(wxID_OPENURLSAMEPAGE, wxT("&Open URL"),
495                         wxT("Open a URL in the current notebook page"));
496     fileMenu->Append(wxID_OPENURLNEWPAGE, wxT("&Open URL in a new page"),
497                         wxT("Open a URL in a new notebook page"));
498     fileMenu->AppendSeparator();
499     fileMenu->Append(wxID_CLOSECURRENTPAGE, wxT("&Close Current Page\tCtrl-C"),
500                         wxT("Close current notebook page"));
501     fileMenu->AppendSeparator();
502     fileMenu->Append(wxID_EXIT,
503                      wxT("E&xit\tAlt-X"),
504                      wxT("Quit this program"));
505 
506     controlsMenu->Append(wxID_PLAY, wxT("&Play/Pause\tCtrl-P"), wxT("Resume/Pause playback"));
507     controlsMenu->Append(wxID_STOP, wxT("&Stop\tCtrl-S"), wxT("Stop playback"));
508     controlsMenu->AppendSeparator();
509     controlsMenu->Append(wxID_PREV, wxT("&Previous\tCtrl-B"), wxT("Go to previous track"));
510     controlsMenu->Append(wxID_NEXT, wxT("&Next\tCtrl-N"), wxT("Skip to next track"));
511 
512     optionsMenu->AppendCheckItem(wxID_LOOP,
513                               wxT("&Loop\tCtrl-L"),
514                               wxT("Loop Selected Media"));
515     optionsMenu->AppendCheckItem(wxID_SHOWINTERFACE,
516                               wxT("&Show Interface\tCtrl-I"),
517                               wxT("Show wxMediaCtrl native controls"));
518 
519     debugMenu->Append(wxID_SELECTBACKEND,
520                      wxT("&Select Backend...\tCtrl-D"),
521                      wxT("Select a backend manually"));
522 
523     helpMenu->Append(wxID_ABOUT,
524                      wxT("&About...\tF1"),
525                      wxT("Show about dialog"));
526 
527 
528     wxMenuBar *menuBar = new wxMenuBar();
529     menuBar->Append(fileMenu, wxT("&File"));
530     menuBar->Append(controlsMenu, wxT("&Controls"));
531     menuBar->Append(optionsMenu, wxT("&Options"));
532     menuBar->Append(debugMenu, wxT("&Debug"));
533     menuBar->Append(helpMenu, wxT("&Help"));
534     SetMenuBar(menuBar);
535 
536     //
537     // Create our notebook - using wxNotebook is luckily pretty
538     // simple and self-explanatory in most cases
539     //
540     m_notebook = new wxNotebook(this, wxID_NOTEBOOK);
541 
542     //
543     //  Create our status bar
544     //
545 #if wxUSE_STATUSBAR
546     // create a status bar just for fun (by default with 1 pane only)
547     CreateStatusBar(1);
548 #endif // wxUSE_STATUSBAR
549 
550     //
551     //  Connect events.
552     //
553     //  There are two ways in wxWidgets to use events -
554     //  Message Maps and Connections.
555     //
556     //  Message Maps are implemented by putting
557     //  DECLARE_MESSAGE_MAP in your wxEvtHandler-derived
558     //  class you want to use for events, such as wxMediaPlayerFrame.
559     //
560     //  Then after your class declaration you put
561     //  BEGIN_EVENT_TABLE(wxMediaPlayerFrame, wxFrame)
562     //  EVT_XXX(XXX)...
563     //  END_EVENT_TABLE()
564     //
565     //  Where wxMediaPlayerFrame is the class with the DECLARE_MESSAGE_MAP
566     //  in it.  EVT_XXX(XXX) are each of your handlers, such
567     //  as EVT_MENU for menu events and the XXX inside
568     //  is the parameters to the event macro - in the case
569     //  of EVT_MENU the menu id and then the function to call.
570     //
571     //  However, with wxEvtHandler::Connect you can avoid a
572     //  global message map for your class and those annoying
573     //  macros.  You can also change the context in which
574     //  the call the handler (more later).
575     //
576     //  The downside is that due to the limitation that
577     //  wxWidgets doesn't use templates in certain areas,
578     //  You have to triple-cast the event function.
579     //
580     //  There are five parameters to wxEvtHandler::Connect -
581     //
582     //  The first is the id of the instance whose events
583     //  you want to handle - i.e. a menu id for menus,
584     //  a control id for controls (wxControl::GetId())
585     //  and so on.
586     //
587     //  The second is the event id.  This is the same
588     //  as the message maps (EVT_MENU) except prefixed
589     //  with "wx" (wxEVT_MENU).
590     //
591     //  The third is the function handler for the event -
592     //  You need to cast it to the specific event handler
593     //  type, then to a wxEventFunction, then to a
594     //  wxObjectEventFunction - I.E.
595     //  (wxObjectEventFunction)(wxEventFunction)
596     //  (wxCommandEventFunction) &wxMediaPlayerFrame::MyHandler
597     //
598     //  Or, you can use the new (2.5.5+) event handler
599     //  conversion macros - for instance the above could
600     //  be done as
601     //  wxCommandEventHandler(wxMediaPlayerFrame::MyHandler)
602     //  pretty simple, eh?
603     //
604     //  The fourth is an optional userdata param -
605     //  this is of historical relevance only and is
606     //  there only for backwards compatibility.
607     //
608     //  The fifth is the context in which to call the
609     //  handler - by default (this param is optional)
610     //  this.  For example in your event handler
611     //  if you were to call "this->MyFunc()"
612     //  it would literally do this->MyFunc.  However,
613     //  if you were to pass myHandler as the fifth
614     //  parameter, for instance, you would _really_
615     //  be calling myHandler->MyFunc, even though
616     //  the compiler doesn't really know it.
617     //
618 
619     //
620     // Menu events
621     //
622     this->Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED,
623                   wxCommandEventHandler(wxMediaPlayerFrame::OnQuit));
624 
625     this->Connect(wxID_ABOUT, wxEVT_COMMAND_MENU_SELECTED,
626                   wxCommandEventHandler(wxMediaPlayerFrame::OnAbout));
627 
628     this->Connect(wxID_LOOP, wxEVT_COMMAND_MENU_SELECTED,
629                   wxCommandEventHandler(wxMediaPlayerFrame::OnLoop));
630 
631     this->Connect(wxID_SHOWINTERFACE, wxEVT_COMMAND_MENU_SELECTED,
632                   wxCommandEventHandler(wxMediaPlayerFrame::OnShowInterface));
633 
634     this->Connect(wxID_OPENFILENEWPAGE, wxEVT_COMMAND_MENU_SELECTED,
635                   wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileNewPage));
636 
637     this->Connect(wxID_OPENFILESAMEPAGE, wxEVT_COMMAND_MENU_SELECTED,
638                   wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileSamePage));
639 
640     this->Connect(wxID_OPENURLNEWPAGE, wxEVT_COMMAND_MENU_SELECTED,
641                   wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLNewPage));
642 
643     this->Connect(wxID_OPENURLSAMEPAGE, wxEVT_COMMAND_MENU_SELECTED,
644                   wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLSamePage));
645 
646     this->Connect(wxID_CLOSECURRENTPAGE, wxEVT_COMMAND_MENU_SELECTED,
647                   wxCommandEventHandler(wxMediaPlayerFrame::OnCloseCurrentPage));
648 
649     this->Connect(wxID_PLAY, wxEVT_COMMAND_MENU_SELECTED,
650                   wxCommandEventHandler(wxMediaPlayerFrame::OnPlay));
651 
652     this->Connect(wxID_STOP, wxEVT_COMMAND_MENU_SELECTED,
653                   wxCommandEventHandler(wxMediaPlayerFrame::OnStop));
654 
655     this->Connect(wxID_NEXT, wxEVT_COMMAND_MENU_SELECTED,
656                   wxCommandEventHandler(wxMediaPlayerFrame::OnNext));
657 
658     this->Connect(wxID_PREV, wxEVT_COMMAND_MENU_SELECTED,
659                   wxCommandEventHandler(wxMediaPlayerFrame::OnPrev));
660 
661     this->Connect(wxID_SELECTBACKEND, wxEVT_COMMAND_MENU_SELECTED,
662                   wxCommandEventHandler(wxMediaPlayerFrame::OnSelectBackend));
663 
664     //
665     // Key events
666     //
667     wxTheApp->Connect(wxID_ANY, wxEVT_KEY_DOWN,
668                   wxKeyEventHandler(wxMediaPlayerFrame::OnKeyDown),
669                   (wxObject*)0, this);
670 
671     //
672     // Close events
673     //
674     this->Connect(wxID_ANY, wxEVT_CLOSE_WINDOW,
675                 wxCloseEventHandler(wxMediaPlayerFrame::OnClose));
676 
677     //
678     // End of Events
679     //
680 
681     //
682     //  Create an initial notebook page so the user has something
683     //  to work with without having to go file->open every time :).
684     //
685     wxMediaPlayerNotebookPage* page =
686         new wxMediaPlayerNotebookPage(this, m_notebook);
687     m_notebook->AddPage(page,
688                         wxT(""),
689                         true);
690 
691     //
692     //  Here we load the our configuration -
693     //  in our case we load all the files that were left in
694     //  the playlist the last time the user closed our application
695     //
696     //  As an exercise to the reader try modifying it so that
697     //  it properly loads the playlist for each page without
698     //  conflicting (loading the same data) with the other ones.
699     //
700     wxConfig conf;
701     wxString key, outstring;
702     for(int i = 0; ; ++i)
703     {
704         key.clear();
705         key << i;
706         if(!conf.Read(key, &outstring))
707             break;
708         page->m_playlist->AddToPlayList(outstring);
709     }
710 
711     //
712     //  Create a timer to update our status bar
713     //
714     m_timer = new wxMediaPlayerTimer(this);
715     m_timer->Start(500);
716 }
717 
718 // ----------------------------------------------------------------------------
719 // wxMediaPlayerFrame Destructor
720 //
721 // 1) Deletes child objects implicitly
722 // 2) Delete our timer explicitly
723 // ----------------------------------------------------------------------------
~wxMediaPlayerFrame()724 wxMediaPlayerFrame::~wxMediaPlayerFrame()
725 {
726     //  Shut down our timer
727     delete m_timer;
728 
729     //
730     //  Here we save our info to the registry or whatever
731     //  mechanism the OS uses.
732     //
733     //  This makes it so that when mediaplayer loads up again
734     //  it restores the same files that were in the playlist
735     //  this time, rather than the user manually re-adding them.
736     //
737     //  We need to do conf->DeleteAll() here because by default
738     //  the config still contains the same files as last time
739     //  so we need to clear it before writing our new ones.
740     //
741     //  TODO:  Maybe you could add a menu option to the
742     //  options menu to delete the configuration on exit -
743     //  all you'd need to do is just remove everything after
744     //  conf->DeleteAll() here
745     //
746     //  As an exercise to the reader, try modifying this so
747     //  that it saves the data for each notebook page
748     //
749     wxMediaPlayerListCtrl* playlist =
750         ((wxMediaPlayerNotebookPage*)m_notebook->GetPage(0))->m_playlist;
751 
752     wxConfig conf;
753     conf.DeleteAll();
754 
755     for(int i = 0; i < playlist->GetItemCount(); ++i)
756     {
757         wxString* pData = (wxString*) playlist->GetItemData(i);
758         wxString s;
759         s << i;
760         conf.Write(s, *(pData));
761         delete pData;
762     }
763 }
764 
765 // ----------------------------------------------------------------------------
766 // wxMediaPlayerFrame::OnClose
767 // ----------------------------------------------------------------------------
OnClose(wxCloseEvent & event)768 void wxMediaPlayerFrame::OnClose(wxCloseEvent& event)
769 {
770     event.Skip(); //really close the frame
771 }
772 
773 // ----------------------------------------------------------------------------
774 // wxMediaPlayerFrame::AddToPlayList
775 // ----------------------------------------------------------------------------
AddToPlayList(const wxString & szString)776 void wxMediaPlayerFrame::AddToPlayList(const wxString& szString)
777 {
778     wxMediaPlayerNotebookPage* currentpage =
779         ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage());
780 
781     currentpage->m_playlist->AddToPlayList(szString);
782 }
783 
784 // ----------------------------------------------------------------------------
785 // wxMediaPlayerFrame::OnQuit
786 //
787 // Called from file->quit.
788 // Closes this application.
789 // ----------------------------------------------------------------------------
OnQuit(wxCommandEvent & WXUNUSED (event))790 void wxMediaPlayerFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
791 {
792     // true is to force the frame to close
793     Close(true);
794 }
795 
796 // ----------------------------------------------------------------------------
797 // wxMediaPlayerFrame::OnAbout
798 //
799 // Called from help->about.
800 // Gets some info about this application.
801 // ----------------------------------------------------------------------------
OnAbout(wxCommandEvent & WXUNUSED (event))802 void wxMediaPlayerFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
803 {
804     wxString msg;
805     msg.Printf( wxT("This is a test of wxMediaCtrl.\n\n")
806 
807                 wxT("Intructions:\n")
808 
809                 wxT("The top slider shows the current the current position, ")
810                 wxT("which you can change by dragging and releasing it.\n")
811 
812                 wxT("The gauge (progress bar) shows the progress in ")
813                 wxT("downloading data of the current file - it may always be ")
814                 wxT("Empty due to lack of support from the current backend.\n")
815 
816                 wxT("The lower-left slider controls the volume and the lower-")
817                 wxT("right slider controls the playback rate/speed of the ")
818                 wxT("media\n\n")
819 
820                 wxT("Currently using: %s"), wxVERSION_STRING);
821 
822     wxMessageBox(msg, wxT("About wxMediaCtrl test"),
823                  wxOK | wxICON_INFORMATION, this);
824 }
825 
826 // ----------------------------------------------------------------------------
827 // wxMediaPlayerFrame::OnLoop
828 //
829 // Called from file->loop.
830 // Changes the state of whether we want to loop or not.
831 // ----------------------------------------------------------------------------
OnLoop(wxCommandEvent & WXUNUSED (event))832 void wxMediaPlayerFrame::OnLoop(wxCommandEvent& WXUNUSED(event))
833 {
834     wxMediaPlayerNotebookPage* currentpage =
835         ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage());
836 
837     currentpage->m_bLoop = !currentpage->m_bLoop;
838 }
839 
840 // ----------------------------------------------------------------------------
841 // wxMediaPlayerFrame::OnLoop
842 //
843 // Called from file->loop.
844 // Changes the state of whether we want to loop or not.
845 // ----------------------------------------------------------------------------
OnShowInterface(wxCommandEvent & event)846 void wxMediaPlayerFrame::OnShowInterface(wxCommandEvent& event)
847 {
848     wxMediaPlayerNotebookPage* currentpage =
849         ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage());
850 
851     if( !currentpage->m_mediactrl->ShowPlayerControls(event.IsChecked() ?
852             wxMEDIACTRLPLAYERCONTROLS_DEFAULT :
853              wxMEDIACTRLPLAYERCONTROLS_NONE)    )
854     {
855         //error - uncheck and warn user
856         wxMenuItem* pSIItem = GetMenuBar()->FindItem(wxID_SHOWINTERFACE);
857         wxASSERT(pSIItem);
858         pSIItem->Check(!event.IsChecked());
859 
860         if(event.IsChecked())
861             wxMessageBox(wxT("Could not show player controls"));
862         else
863             wxMessageBox(wxT("Could not hide player controls"));
864     }
865 }
866 
867 // ----------------------------------------------------------------------------
868 // wxMediaPlayerFrame::OnOpenFileSamePage
869 //
870 // Called from file->openfile.
871 // Opens and plays a media file in the current notebook page
872 // ----------------------------------------------------------------------------
OnOpenFileSamePage(wxCommandEvent & WXUNUSED (event))873 void wxMediaPlayerFrame::OnOpenFileSamePage(wxCommandEvent& WXUNUSED(event))
874 {
875     OpenFile(false);
876 }
877 
878 // ----------------------------------------------------------------------------
879 // wxMediaPlayerFrame::OnOpenFileNewPage
880 //
881 // Called from file->openfileinnewpage.
882 // Opens and plays a media file in a new notebook page
883 // ----------------------------------------------------------------------------
OnOpenFileNewPage(wxCommandEvent & WXUNUSED (event))884 void wxMediaPlayerFrame::OnOpenFileNewPage(wxCommandEvent& WXUNUSED(event))
885 {
886     OpenFile(true);
887 }
888 
889 // ----------------------------------------------------------------------------
890 // wxMediaPlayerFrame::OpenFile
891 //
892 // Opens a file dialog asking the user for a filename, then
893 // calls DoOpenFile which will add the file to the playlist and play it
894 // ----------------------------------------------------------------------------
OpenFile(bool bNewPage)895 void wxMediaPlayerFrame::OpenFile(bool bNewPage)
896 {
897     wxFileDialog fd(this);
898 
899     if(fd.ShowModal() == wxID_OK)
900     {
901         DoOpenFile(fd.GetPath(), bNewPage);
902     }
903 }
904 
905 // ----------------------------------------------------------------------------
906 // wxMediaPlayerFrame::DoOpenFile
907 //
908 // Adds the file to our playlist, selects it in the playlist,
909 // and then calls DoPlayFile to play it
910 // ----------------------------------------------------------------------------
DoOpenFile(const wxString & path,bool bNewPage)911 void wxMediaPlayerFrame::DoOpenFile(const wxString& path, bool bNewPage)
912 {
913     if(bNewPage)
914     {
915         m_notebook->AddPage(
916             new wxMediaPlayerNotebookPage(this, m_notebook),
917             path,
918             true);
919     }
920 
921     wxMediaPlayerNotebookPage* currentpage =
922         (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
923 
924     if(currentpage->m_nLastFileId != -1)
925         currentpage->m_playlist->SetItemState(currentpage->m_nLastFileId,
926                                               0, wxLIST_STATE_SELECTED);
927 
928     wxListItem newlistitem;
929     newlistitem.SetAlign(wxLIST_FORMAT_LEFT);
930 
931     int nID;
932 
933     newlistitem.SetId(nID = currentpage->m_playlist->GetItemCount());
934     newlistitem.SetMask(wxLIST_MASK_DATA | wxLIST_MASK_STATE);
935     newlistitem.SetState(wxLIST_STATE_SELECTED);
936     newlistitem.SetData(new wxString(path));
937 
938     currentpage->m_playlist->InsertItem(newlistitem);
939     currentpage->m_playlist->SetItem(nID, 0, wxT("*"));
940     currentpage->m_playlist->SetItem(nID, 1, wxFileName(path).GetName());
941 
942     if (nID % 2)
943     {
944         newlistitem.SetBackgroundColour(wxColour(192,192,192));
945         currentpage->m_playlist->SetItem(newlistitem);
946     }
947 
948     DoPlayFile(path);
949 }
950 
951 // ----------------------------------------------------------------------------
952 // wxMediaPlayerFrame::DoPlayFile
953 //
954 // Pauses the file if its the currently playing file,
955 // otherwise it plays the file
956 // ----------------------------------------------------------------------------
DoPlayFile(const wxString & path)957 void wxMediaPlayerFrame::DoPlayFile(const wxString& path)
958 {
959     wxMediaPlayerNotebookPage* currentpage =
960         (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
961 
962     wxListItem listitem;
963     currentpage->m_playlist->GetSelectedItem(listitem);
964 
965     if( (  listitem.GetData() &&
966            currentpage->m_nLastFileId == listitem.GetId() &&
967            currentpage->m_szFile.compare(path) == 0 ) ||
968         (  !listitem.GetData() &&
969             currentpage->m_nLastFileId != -1 &&
970             currentpage->m_szFile.compare(path) == 0)
971       )
972     {
973         if(currentpage->m_mediactrl->GetState() == wxMEDIASTATE_PLAYING)
974     {
975             if( !currentpage->m_mediactrl->Pause() )
976                 wxMessageBox(wxT("Couldn't pause movie!"));
977         }
978         else
979         {
980             if( !currentpage->m_mediactrl->Play() )
981                 wxMessageBox(wxT("Couldn't play movie!"));
982         }
983     }
984     else
985     {
986         int nNewId = listitem.GetData() ? listitem.GetId() :
987                             currentpage->m_playlist->GetItemCount()-1;
988         m_notebook->SetPageText(m_notebook->GetSelection(),
989                                 wxFileName(path).GetName());
990 
991         if(currentpage->m_nLastFileId != -1)
992            currentpage->m_playlist->SetItem(
993                     currentpage->m_nLastFileId, 0, wxT("*"));
994 
995         wxURI uripath(path);
996         if( uripath.IsReference() )
997         {
998             if( !currentpage->m_mediactrl->Load(path) )
999             {
1000                 wxMessageBox(wxT("Couldn't load file!"));
1001                 currentpage->m_playlist->SetItem(nNewId, 0, wxT("E"));
1002             }
1003             else
1004             {
1005                 currentpage->m_playlist->SetItem(nNewId, 0, wxT("O"));
1006             }
1007         }
1008         else
1009         {
1010             if( !currentpage->m_mediactrl->Load(uripath) )
1011             {
1012                 wxMessageBox(wxT("Couldn't load URL!"));
1013                 currentpage->m_playlist->SetItem(nNewId, 0, wxT("E"));
1014             }
1015             else
1016             {
1017                 currentpage->m_playlist->SetItem(nNewId, 0, wxT("O"));
1018             }
1019         }
1020 
1021         currentpage->m_nLastFileId = nNewId;
1022         currentpage->m_szFile = path;
1023         currentpage->m_playlist->SetItem(currentpage->m_nLastFileId,
1024                                          1, wxFileName(path).GetName());
1025         currentpage->m_playlist->SetItem(currentpage->m_nLastFileId,
1026                                          2, wxT(""));
1027     }
1028 }
1029 
1030 // ----------------------------------------------------------------------------
1031 // wxMediaPlayerFrame::OnMediaLoaded
1032 //
1033 // Called when the media is ready to be played - and does
1034 // so, also gets the length of media and shows that in the list control
1035 // ----------------------------------------------------------------------------
OnMediaLoaded(wxMediaEvent & WXUNUSED (evt))1036 void wxMediaPlayerFrame::OnMediaLoaded(wxMediaEvent& WXUNUSED(evt))
1037 {
1038     wxMediaPlayerNotebookPage* currentpage =
1039         (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
1040 
1041     if( !currentpage->m_mediactrl->Play() )
1042     {
1043             wxMessageBox(wxT("Couldn't play movie!"));
1044         currentpage->m_playlist->SetItem(currentpage->m_nLastFileId, 0, wxT("E"));
1045     }
1046     else
1047     {
1048         currentpage->m_playlist->SetItem(currentpage->m_nLastFileId, 0, wxT(">"));
1049     }
1050 
1051 }
1052 
1053 
1054 // ----------------------------------------------------------------------------
1055 // wxMediaPlayerFrame::OnSelectBackend
1056 //
1057 // Little debugging routine - enter the class name of a backend and it
1058 // will use that instead of letting wxMediaCtrl search the wxMediaBackend
1059 // RTTI class list.
1060 // ----------------------------------------------------------------------------
OnSelectBackend(wxCommandEvent & WXUNUSED (evt))1061 void wxMediaPlayerFrame::OnSelectBackend(wxCommandEvent& WXUNUSED(evt))
1062 {
1063     wxString sBackend = wxGetTextFromUser(wxT("Enter backend to use"));
1064 
1065     if(sBackend.empty() == false)  //could have been cancelled by the user
1066     {
1067         int sel = m_notebook->GetSelection();
1068 
1069         if (sel != wxNOT_FOUND)
1070         {
1071             m_notebook->DeletePage(sel);
1072         }
1073 
1074         m_notebook->AddPage(new wxMediaPlayerNotebookPage(this, m_notebook,
1075                                                         sBackend
1076                                                         ), wxT(""), true);
1077 
1078         DoOpenFile(
1079             ((wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage())->m_szFile,
1080             false);
1081     }
1082 }
1083 
1084 // ----------------------------------------------------------------------------
1085 // wxMediaPlayerFrame::OnOpenURLSamePage
1086 //
1087 // Called from file->openurl.
1088 // Opens and plays a media file from a URL in the current notebook page
1089 // ----------------------------------------------------------------------------
OnOpenURLSamePage(wxCommandEvent & WXUNUSED (event))1090 void wxMediaPlayerFrame::OnOpenURLSamePage(wxCommandEvent& WXUNUSED(event))
1091 {
1092     OpenURL(false);
1093 }
1094 
1095 // ----------------------------------------------------------------------------
1096 // wxMediaPlayerFrame::OnOpenURLNewPage
1097 //
1098 // Called from file->openurlinnewpage.
1099 // Opens and plays a media file from a URL in a new notebook page
1100 // ----------------------------------------------------------------------------
OnOpenURLNewPage(wxCommandEvent & WXUNUSED (event))1101 void wxMediaPlayerFrame::OnOpenURLNewPage(wxCommandEvent& WXUNUSED(event))
1102 {
1103     OpenURL(true);
1104 }
1105 
1106 // ----------------------------------------------------------------------------
1107 // wxMediaPlayerFrame::OpenURL
1108 //
1109 // Just calls DoOpenFile with the url path - which calls DoPlayFile
1110 // which handles the real dirty work
1111 // ----------------------------------------------------------------------------
OpenURL(bool bNewPage)1112 void wxMediaPlayerFrame::OpenURL(bool bNewPage)
1113 {
1114     wxString sUrl = wxGetTextFromUser(
1115         wxT("Enter the URL that has the movie to play")
1116                                      );
1117 
1118     if(sUrl.empty() == false) //could have been cancelled by user
1119     {
1120         DoOpenFile(sUrl, bNewPage);
1121     }
1122 }
1123 
1124 // ----------------------------------------------------------------------------
1125 // wxMediaPlayerFrame::OnCloseCurrentPage
1126 //
1127 // Called when the user wants to close the current notebook page
1128 //
1129 // 1) Get the current page number (wxControl::GetSelection)
1130 // 2) If there is no current page, break out
1131 // 3) Delete the current page
1132 // ----------------------------------------------------------------------------
OnCloseCurrentPage(wxCommandEvent & WXUNUSED (event))1133 void wxMediaPlayerFrame::OnCloseCurrentPage(wxCommandEvent& WXUNUSED(event))
1134 {
1135     if( m_notebook->GetPageCount() > 1 )
1136     {
1137     int sel = m_notebook->GetSelection();
1138 
1139     if (sel != wxNOT_FOUND)
1140     {
1141         m_notebook->DeletePage(sel);
1142     }
1143     }
1144     else
1145     {
1146         wxMessageBox(wxT("Cannot close main page"));
1147     }
1148 }
1149 
1150 // ----------------------------------------------------------------------------
1151 // wxMediaPlayerFrame::OnPlay
1152 //
1153 // Called from file->play.
1154 // Resumes the media if it is paused or stopped.
1155 // ----------------------------------------------------------------------------
OnPlay(wxCommandEvent & WXUNUSED (event))1156 void wxMediaPlayerFrame::OnPlay(wxCommandEvent& WXUNUSED(event))
1157 {
1158     wxMediaPlayerNotebookPage* currentpage =
1159         (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
1160 
1161     wxListItem listitem;
1162     currentpage->m_playlist->GetSelectedItem(listitem);
1163     if ( !listitem.GetData() )
1164     {
1165         int nLast = -1;
1166         if ((nLast = currentpage->m_playlist->GetNextItem(nLast,
1167                                          wxLIST_NEXT_ALL,
1168                                          wxLIST_STATE_DONTCARE)) == -1)
1169         {
1170             //no items in list
1171             wxMessageBox(wxT("No items in playlist!"));
1172     }
1173         else
1174         {
1175         listitem.SetId(nLast);
1176             currentpage->m_playlist->GetItem(listitem);
1177         listitem.SetMask(listitem.GetMask() | wxLIST_MASK_STATE);
1178         listitem.SetState(listitem.GetState() | wxLIST_STATE_SELECTED);
1179             currentpage->m_playlist->SetItem(listitem);
1180             wxASSERT(listitem.GetData());
1181             DoPlayFile((*((wxString*) listitem.GetData())));
1182     }
1183     }
1184     else
1185     {
1186         wxASSERT(listitem.GetData());
1187         DoPlayFile((*((wxString*) listitem.GetData())));
1188     }
1189 }
1190 
1191 // ----------------------------------------------------------------------------
1192 // wxMediaPlayerFrame::OnKeyDown
1193 //
1194 // Deletes all selected files from the playlist if the backspace key is pressed
1195 // ----------------------------------------------------------------------------
OnKeyDown(wxKeyEvent & event)1196 void wxMediaPlayerFrame::OnKeyDown(wxKeyEvent& event)
1197 {
1198    if(event.GetKeyCode() == WXK_BACK/*DELETE*/)
1199     {
1200         wxMediaPlayerNotebookPage* currentpage =
1201             (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
1202        //delete all selected items
1203        while(true)
1204        {
1205            wxInt32 nSelectedItem = currentpage->m_playlist->GetNextItem(
1206                     -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
1207            if (nSelectedItem == -1)
1208                break;
1209 
1210            wxListItem listitem;
1211            listitem.SetId(nSelectedItem);
1212            currentpage->m_playlist->GetItem(listitem);
1213            delete (wxString*) listitem.GetData();
1214 
1215            currentpage->m_playlist->DeleteItem(nSelectedItem);
1216        }
1217     }
1218 
1219    //Could be wxGetTextFromUser or something else important
1220    if(event.GetEventObject() != this)
1221        event.Skip();
1222 }
1223 
1224 // ----------------------------------------------------------------------------
1225 // wxMediaPlayerFrame::OnStop
1226 //
1227 // Called from file->stop.
1228 // Where it stops depends on whether you can seek in the
1229 // media control or not - if you can it stops and seeks to the beginning,
1230 // otherwise it will appear to be at the end - but it will start over again
1231 // when Play() is called
1232 // ----------------------------------------------------------------------------
OnStop(wxCommandEvent & WXUNUSED (evt))1233 void wxMediaPlayerFrame::OnStop(wxCommandEvent& WXUNUSED(evt))
1234 {
1235     wxMediaPlayerNotebookPage* currentpage =
1236         (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
1237 
1238     if( !currentpage->m_mediactrl->Stop() )
1239         wxMessageBox(wxT("Couldn't stop movie!"));
1240     else
1241         currentpage->m_playlist->SetItem(
1242             currentpage->m_nLastFileId, 0, wxT("[]"));
1243 }
1244 
1245 
1246 // ----------------------------------------------------------------------------
1247 // wxMediaPlayerFrame::OnChangeSong
1248 //
1249 // Routine that plays the currently selected file in the playlist.
1250 // Called when the user actives the song from the playlist,
1251 // and from other various places in the sample
1252 // ----------------------------------------------------------------------------
OnChangeSong(wxListEvent & WXUNUSED (evt))1253 void wxMediaPlayerFrame::OnChangeSong(wxListEvent& WXUNUSED(evt))
1254 {
1255     wxMediaPlayerNotebookPage* currentpage =
1256         (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
1257 
1258     wxListItem listitem;
1259     currentpage->m_playlist->GetSelectedItem(listitem);
1260     if(listitem.GetData())
1261     DoPlayFile((*((wxString*) listitem.GetData())));
1262     else
1263         wxMessageBox(wxT("No selected item!"));
1264 }
1265 
1266 // ----------------------------------------------------------------------------
1267 // wxMediaPlayerFrame::OnPrev
1268 //
1269 // Tedious wxListCtrl stuff.  Goes to prevous song in list, or if at the
1270 // beginning goes to the last in the list.
1271 // ----------------------------------------------------------------------------
OnPrev(wxCommandEvent & WXUNUSED (event))1272 void wxMediaPlayerFrame::OnPrev(wxCommandEvent& WXUNUSED(event))
1273 {
1274     wxMediaPlayerNotebookPage* currentpage =
1275         (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
1276 
1277     if (currentpage->m_playlist->GetItemCount() == 0)
1278         return;
1279 
1280     wxInt32 nLastSelectedItem = -1;
1281     while(true)
1282     {
1283         wxInt32 nSelectedItem = currentpage->m_playlist->GetNextItem(nLastSelectedItem,
1284                                                      wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
1285         if (nSelectedItem == -1)
1286             break;
1287         nLastSelectedItem = nSelectedItem;
1288         currentpage->m_playlist->SetItemState(nSelectedItem, 0, wxLIST_STATE_SELECTED);
1289     }
1290 
1291     if (nLastSelectedItem == -1)
1292     {
1293         //nothing selected, default to the file before the currently playing one
1294         if(currentpage->m_nLastFileId == 0)
1295             nLastSelectedItem = currentpage->m_playlist->GetItemCount() - 1;
1296     else
1297             nLastSelectedItem = currentpage->m_nLastFileId - 1;
1298     }
1299     else if (nLastSelectedItem == 0)
1300         nLastSelectedItem = currentpage->m_playlist->GetItemCount() - 1;
1301     else
1302         nLastSelectedItem -= 1;
1303 
1304     if(nLastSelectedItem == currentpage->m_nLastFileId)
1305         return; //already playing... nothing to do
1306 
1307     wxListItem listitem;
1308     listitem.SetId(nLastSelectedItem);
1309     listitem.SetMask(wxLIST_MASK_TEXT |  wxLIST_MASK_DATA);
1310     currentpage->m_playlist->GetItem(listitem);
1311     listitem.SetMask(listitem.GetMask() | wxLIST_MASK_STATE);
1312     listitem.SetState(listitem.GetState() | wxLIST_STATE_SELECTED);
1313     currentpage->m_playlist->SetItem(listitem);
1314 
1315     wxASSERT(listitem.GetData());
1316     DoPlayFile((*((wxString*) listitem.GetData())));
1317 }
1318 
1319 // ----------------------------------------------------------------------------
1320 // wxMediaPlayerFrame::OnNext
1321 //
1322 // Tedious wxListCtrl stuff.  Goes to next song in list, or if at the
1323 // end goes to the first in the list.
1324 // ----------------------------------------------------------------------------
OnNext(wxCommandEvent & WXUNUSED (event))1325 void wxMediaPlayerFrame::OnNext(wxCommandEvent& WXUNUSED(event))
1326 {
1327     wxMediaPlayerNotebookPage* currentpage =
1328         (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
1329 
1330     if (currentpage->m_playlist->GetItemCount() == 0)
1331         return;
1332 
1333     wxInt32 nLastSelectedItem = -1;
1334     while(true)
1335     {
1336         wxInt32 nSelectedItem = currentpage->m_playlist->GetNextItem(nLastSelectedItem,
1337                                                      wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
1338         if (nSelectedItem == -1)
1339             break;
1340         nLastSelectedItem = nSelectedItem;
1341         currentpage->m_playlist->SetItemState(nSelectedItem, 0, wxLIST_STATE_SELECTED);
1342     }
1343 
1344     if (nLastSelectedItem == -1)
1345     {
1346         if(currentpage->m_nLastFileId == currentpage->m_playlist->GetItemCount() - 1)
1347         nLastSelectedItem = 0;
1348     else
1349             nLastSelectedItem = currentpage->m_nLastFileId + 1;
1350     }
1351     else if (nLastSelectedItem == currentpage->m_playlist->GetItemCount() - 1)
1352             nLastSelectedItem = 0;
1353         else
1354             nLastSelectedItem += 1;
1355 
1356     if(nLastSelectedItem == currentpage->m_nLastFileId)
1357         return; //already playing... nothing to do
1358 
1359     wxListItem listitem;
1360     listitem.SetMask(wxLIST_MASK_TEXT |  wxLIST_MASK_DATA);
1361     listitem.SetId(nLastSelectedItem);
1362     currentpage->m_playlist->GetItem(listitem);
1363     listitem.SetMask(listitem.GetMask() | wxLIST_MASK_STATE);
1364     listitem.SetState(listitem.GetState() | wxLIST_STATE_SELECTED);
1365     currentpage->m_playlist->SetItem(listitem);
1366 
1367     wxASSERT(listitem.GetData());
1368     DoPlayFile((*((wxString*) listitem.GetData())));
1369 }
1370 
1371 
1372 // ----------------------------------------------------------------------------
1373 // wxMediaPlayerFrame::OnVolumeDown
1374 //
1375 // Lowers the volume of the media control by 5%
1376 // ----------------------------------------------------------------------------
OnVolumeDown(wxCommandEvent & WXUNUSED (event))1377 void wxMediaPlayerFrame::OnVolumeDown(wxCommandEvent& WXUNUSED(event))
1378 {
1379     wxMediaPlayerNotebookPage* currentpage =
1380         (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
1381 
1382     double dVolume = currentpage->m_mediactrl->GetVolume();
1383     currentpage->m_mediactrl->SetVolume(dVolume < 0.05 ? 0.0 : dVolume - .05);
1384 }
1385 
1386 // ----------------------------------------------------------------------------
1387 // wxMediaPlayerFrame::OnVolumeUp
1388 //
1389 // Increases the volume of the media control by 5%
1390 // ----------------------------------------------------------------------------
OnVolumeUp(wxCommandEvent & WXUNUSED (event))1391 void wxMediaPlayerFrame::OnVolumeUp(wxCommandEvent& WXUNUSED(event))
1392 {
1393     wxMediaPlayerNotebookPage* currentpage =
1394         (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
1395 
1396     double dVolume = currentpage->m_mediactrl->GetVolume();
1397     currentpage->m_mediactrl->SetVolume(dVolume > 0.95 ? 1.0 : dVolume + .05);
1398 }
1399 
1400 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1401 //
1402 // wxMediaPlayerTimer
1403 //
1404 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1405 
1406 // ----------------------------------------------------------------------------
1407 // wxMediaPlayerTimer::Notify
1408 //
1409 // 1) Updates media information on the status bar
1410 // 2) Sets the max/min length of the slider and guage
1411 //
1412 // Note that the reason we continually do this and don't cache it is because
1413 // some backends such as GStreamer are dynamic change values all the time
1414 // and often don't have things like duration or video size available
1415 // until the media is actually being played
1416 // ----------------------------------------------------------------------------
Notify()1417 void wxMediaPlayerTimer::Notify()
1418 {
1419     wxMediaPlayerNotebookPage* currentpage =
1420         (wxMediaPlayerNotebookPage*) m_frame->m_notebook->GetCurrentPage();
1421     wxMediaCtrl* currentMediaCtrl = currentpage->m_mediactrl;
1422 
1423     if(currentpage)
1424     {
1425         // Number of minutes/seconds total
1426         wxLongLong llLength = currentpage->m_mediactrl->Length();
1427         int nMinutes = (int) (llLength / 60000).GetValue();
1428         int nSeconds = (int) ((llLength % 60000)/1000).GetValue();
1429 
1430         // Duration string (i.e. MM:SS)
1431         wxString sDuration;
1432         sDuration.Printf(wxT("%2i:%02i"), nMinutes, nSeconds);
1433 
1434 
1435         // Number of minutes/seconds total
1436         wxLongLong llTell = currentpage->m_mediactrl->Tell();
1437         nMinutes = (int) (llTell / 60000).GetValue();
1438         nSeconds = (int) ((llTell % 60000)/1000).GetValue();
1439 
1440         // Position string (i.e. MM:SS)
1441         wxString sPosition;
1442         sPosition.Printf(wxT("%2i:%02i"), nMinutes, nSeconds);
1443 
1444 
1445         // Set the third item in the listctrl entry to the duration string
1446         if(currentpage->m_nLastFileId >= 0)
1447             currentpage->m_playlist->SetItem(
1448                     currentpage->m_nLastFileId, 2, sDuration);
1449 
1450         // Setup the slider and gauge min/max values
1451         currentpage->m_slider->SetRange(0, (int)(llLength / 1000).GetValue());
1452         currentpage->m_gauge->SetRange(100);
1453 
1454 
1455         // if the slider is not being dragged then update it with the song position
1456         if(currentpage->IsBeingDragged() == false)
1457             currentpage->m_slider->SetValue((long)(llTell / 1000).GetValue());
1458 
1459 
1460         // Update the gauge with the download progress
1461         wxLongLong llDownloadProgress =
1462             currentpage->m_mediactrl->GetDownloadProgress();
1463         wxLongLong llDownloadTotal =
1464             currentpage->m_mediactrl->GetDownloadTotal();
1465 
1466         if(llDownloadTotal.GetValue() != 0)
1467         {
1468             currentpage->m_gauge->SetValue(
1469                 (int) ((llDownloadProgress * 100) / llDownloadTotal).GetValue()
1470                                           );
1471         }
1472 
1473         // GetBestSize holds the original video size
1474         wxSize videoSize = currentMediaCtrl->GetBestSize();
1475 
1476         // Now the big part - set the status bar text to
1477         // hold various metadata about the media
1478 #if wxUSE_STATUSBAR
1479         m_frame->SetStatusText(wxString::Format(
1480                         wxT("Size(x,y):%i,%i ")
1481                         wxT("Position:%s/%s Speed:%1.1fx ")
1482                         wxT("State:%s Loops:%i D/T:[%i]/[%i] V:%i%%"),
1483                         videoSize.x,
1484                         videoSize.y,
1485                         sPosition.c_str(),
1486                         sDuration.c_str(),
1487                         currentMediaCtrl->GetPlaybackRate(),
1488                         wxGetMediaStateText(currentpage->m_mediactrl->GetState()),
1489                         currentpage->m_nLoops,
1490                         (int)llDownloadProgress.GetValue(),
1491                         (int)llDownloadTotal.GetValue(),
1492                         (int)(currentpage->m_mediactrl->GetVolume() * 100)));
1493 #endif // wxUSE_STATUSBAR
1494     }
1495 }
1496 
1497 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1498 //
1499 // wxMediaPlayerNotebookPage
1500 //
1501 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1502 
1503 // ----------------------------------------------------------------------------
1504 // wxMediaPlayerNotebookPage Constructor
1505 //
1506 // Creates a media control and slider and adds it to this panel,
1507 // along with some sizers for positioning
1508 // ----------------------------------------------------------------------------
wxMediaPlayerNotebookPage(wxMediaPlayerFrame * parentFrame,wxNotebook * theBook,const wxString & szBackend)1509 wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentFrame,
1510                                                      wxNotebook* theBook,
1511                                                      const wxString& szBackend)
1512                          : wxPanel(theBook, wxID_ANY),
1513                            m_nLastFileId(-1),
1514                            m_nLoops(0),
1515                            m_bLoop(false),
1516                            m_bIsBeingDragged(false),
1517                            m_parentFrame(parentFrame)
1518 {
1519     //
1520     //  Layout
1521     //
1522     //  [wxMediaCtrl]
1523     //  [playlist]
1524     //  [5 control buttons]
1525     //  [slider]
1526     //  [gauge]
1527     //
1528 
1529     //
1530     //  Create and attach the sizer
1531     //
1532     wxFlexGridSizer* sizer = new wxFlexGridSizer(2, 1, 0, 0);
1533     this->SetSizer(sizer);
1534     this->SetAutoLayout(true);
1535     sizer->AddGrowableRow(0);
1536     sizer->AddGrowableCol(0);
1537 
1538     //
1539     //  Create our media control
1540     //
1541     m_mediactrl = new wxMediaCtrl();
1542 
1543     //  Make sure creation was successful
1544     bool bOK = m_mediactrl->Create(this, wxID_MEDIACTRL, wxEmptyString,
1545                                     wxDefaultPosition, wxDefaultSize, 0,
1546 //you could specify a macrod backend here like
1547 //  wxMEDIABACKEND_WMP10);
1548 //        wxT("wxPDFMediaBackend"));
1549                                    szBackend);
1550 //you could change the cursor here like
1551 //    m_mediactrl->SetCursor(wxCURSOR_BLANK);
1552 //note that this may not effect it if SetPlayerControls
1553 //is set to something else than wxMEDIACTRLPLAYERCONTROLS_NONE
1554     wxASSERT_MSG(bOK, wxT("Could not create media control!"));
1555     wxUnusedVar(bOK);
1556 
1557     sizer->Add(m_mediactrl, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 5);
1558 
1559     //
1560     //  Create the playlist/listctrl
1561     //
1562     m_playlist = new wxMediaPlayerListCtrl();
1563     m_playlist->Create(this, wxID_LISTCTRL, wxDefaultPosition,
1564                     wxDefaultSize,
1565                     wxLC_REPORT //wxLC_LIST
1566                     | wxSUNKEN_BORDER);
1567 
1568     //  Set the background of our listctrl to white
1569     m_playlist->SetBackgroundColour(wxColour(255,255,255));
1570 
1571     //  The layout of the headers of the listctrl are like
1572     //  |   | File               |  Length
1573     //
1574     //  Where Column one is a character representing the state the file is in:
1575     //  * - not the current file
1576     //  E - Error has occured
1577     //  > - Currently Playing
1578     //  [] - Stopped
1579     //  || - Paused
1580     //  (( - Volume Down 5%
1581     //  )) - Volume Up 5%
1582     //
1583     //  Column two is the name of the file
1584     //
1585     //  Column three is the length in seconds of the file
1586     m_playlist->InsertColumn(0,_(""), wxLIST_FORMAT_CENTER, 20);
1587     m_playlist->InsertColumn(1,_("File"), wxLIST_FORMAT_LEFT, /*wxLIST_AUTOSIZE_USEHEADER*/305);
1588     m_playlist->InsertColumn(2,_("Length"), wxLIST_FORMAT_CENTER, 75);
1589 
1590 #if wxUSE_DRAG_AND_DROP
1591     m_playlist->SetDropTarget(new wxPlayListDropTarget(*m_playlist));
1592 #endif
1593 
1594     sizer->Add(m_playlist, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 5);
1595 
1596     //
1597     //  Create the control buttons
1598     //  TODO/FIXME/HACK:  This part about sizers is really a nice hack
1599     //                    and probably isn't proper
1600     //
1601     wxBoxSizer* horsizer1 = new wxBoxSizer(wxHORIZONTAL);
1602     wxBoxSizer* vertsizer = new wxBoxSizer(wxHORIZONTAL);
1603 
1604     m_prevButton = new wxButton();
1605     m_playButton = new wxButton();
1606     m_stopButton = new wxButton();
1607     m_nextButton = new wxButton();
1608     m_vdButton = new wxButton();
1609     m_vuButton = new wxButton();
1610 
1611     m_prevButton->Create(this, wxID_BUTTONPREV, wxT("|<"));
1612     m_playButton->Create(this, wxID_BUTTONPLAY, wxT(">"));
1613     m_stopButton->Create(this, wxID_BUTTONSTOP, wxT("[]"));
1614     m_nextButton->Create(this, wxID_BUTTONNEXT, wxT(">|"));
1615     m_vdButton->Create(this, wxID_BUTTONVD, wxT("(("));
1616     m_vuButton->Create(this, wxID_BUTTONVU, wxT("))"));
1617     vertsizer->Add(m_prevButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1618     vertsizer->Add(m_playButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1619     vertsizer->Add(m_stopButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1620     vertsizer->Add(m_nextButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1621     vertsizer->Add(m_vdButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1622     vertsizer->Add(m_vuButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1623     horsizer1->Add(vertsizer, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1624     sizer->Add(horsizer1, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
1625 
1626 
1627     //
1628     //  Create our slider
1629     //
1630     m_slider = new wxSlider(this, wxID_SLIDER, 0, //init
1631                             0, //start
1632                             0, //end
1633                             wxDefaultPosition, wxDefaultSize,
1634                             wxSL_HORIZONTAL );
1635     sizer->Add(m_slider, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5);
1636 
1637     //
1638     //  Create the gauge
1639     //
1640     m_gauge = new wxGauge();
1641     m_gauge->Create(this, wxID_GAUGE, 0, wxDefaultPosition, wxDefaultSize,
1642                         wxGA_HORIZONTAL | wxGA_SMOOTH);
1643     sizer->Add(m_gauge, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5);
1644 
1645     //
1646     //  Create the speed/volume sliders
1647     //
1648     wxBoxSizer* horsizer3 = new wxBoxSizer(wxHORIZONTAL);
1649 
1650     m_volSlider = new wxSlider(this, wxID_VOLSLIDER, 100, // init
1651                             0, // start
1652                             100, // end
1653                             wxDefaultPosition, wxSize(250,20),
1654                             wxSL_HORIZONTAL );
1655     horsizer3->Add(m_volSlider, 1, wxALL, 5);
1656 
1657     m_pbSlider = new wxSlider(this, wxID_PBSLIDER, 4, // init
1658                             1, // start
1659                             16, // end
1660                             wxDefaultPosition, wxSize(250,20),
1661                             wxSL_HORIZONTAL );
1662     horsizer3->Add(m_pbSlider, 1, wxALL, 5);
1663     sizer->Add(horsizer3, 1, wxCENTRE | wxALL, 5);
1664 
1665     //
1666     // ListCtrl events
1667     //
1668     this->Connect( wxID_LISTCTRL, wxEVT_COMMAND_LIST_ITEM_ACTIVATED,
1669         wxListEventHandler(wxMediaPlayerFrame::OnChangeSong),
1670         (wxObject*)0, parentFrame);
1671 
1672     //
1673     // Slider events
1674     //
1675     this->Connect(wxID_SLIDER, wxEVT_SCROLL_THUMBTRACK,
1676                   wxScrollEventHandler(wxMediaPlayerNotebookPage::OnBeginSeek));
1677     this->Connect(wxID_SLIDER, wxEVT_SCROLL_THUMBRELEASE,
1678                   wxScrollEventHandler(wxMediaPlayerNotebookPage::OnEndSeek));
1679     this->Connect(wxID_PBSLIDER, wxEVT_SCROLL_THUMBRELEASE,
1680                     wxScrollEventHandler(wxMediaPlayerNotebookPage::OnPBChange));
1681     this->Connect(wxID_VOLSLIDER, wxEVT_SCROLL_THUMBRELEASE,
1682                     wxScrollEventHandler(wxMediaPlayerNotebookPage::OnVolChange));
1683 
1684     //
1685     // Media Control events
1686     //
1687     this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_PLAY,
1688                   wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaPlay));
1689     this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_PAUSE,
1690                   wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaPause));
1691     this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_STOP,
1692                   wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaStop));
1693     this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_FINISHED,
1694                   wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaFinished));
1695     this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_LOADED,
1696                   wxMediaEventHandler(wxMediaPlayerFrame::OnMediaLoaded),
1697                   (wxObject*)0, parentFrame);
1698 
1699     //
1700     // Button events
1701     //
1702     this->Connect( wxID_BUTTONPREV, wxEVT_COMMAND_BUTTON_CLICKED,
1703         wxCommandEventHandler(wxMediaPlayerFrame::OnPrev),
1704         (wxObject*)0, parentFrame);
1705     this->Connect( wxID_BUTTONPLAY, wxEVT_COMMAND_BUTTON_CLICKED,
1706         wxCommandEventHandler(wxMediaPlayerFrame::OnPlay),
1707         (wxObject*)0, parentFrame);
1708     this->Connect( wxID_BUTTONSTOP, wxEVT_COMMAND_BUTTON_CLICKED,
1709         wxCommandEventHandler(wxMediaPlayerFrame::OnStop),
1710         (wxObject*)0, parentFrame);
1711     this->Connect( wxID_BUTTONNEXT, wxEVT_COMMAND_BUTTON_CLICKED,
1712         wxCommandEventHandler(wxMediaPlayerFrame::OnNext),
1713         (wxObject*)0, parentFrame);
1714     this->Connect( wxID_BUTTONVD, wxEVT_COMMAND_BUTTON_CLICKED,
1715         wxCommandEventHandler(wxMediaPlayerFrame::OnVolumeDown),
1716         (wxObject*)0, parentFrame);
1717     this->Connect( wxID_BUTTONVU, wxEVT_COMMAND_BUTTON_CLICKED,
1718         wxCommandEventHandler(wxMediaPlayerFrame::OnVolumeUp),
1719         (wxObject*)0, parentFrame);
1720 }
1721 
1722 // ----------------------------------------------------------------------------
1723 // MyNotebook::OnBeginSeek
1724 //
1725 // Sets m_bIsBeingDragged to true to stop the timer from changing the position
1726 // of our slider
1727 // ----------------------------------------------------------------------------
OnBeginSeek(wxScrollEvent & WXUNUSED (event))1728 void wxMediaPlayerNotebookPage::OnBeginSeek(wxScrollEvent& WXUNUSED(event))
1729 {
1730     m_bIsBeingDragged = true;
1731 }
1732 
1733 // ----------------------------------------------------------------------------
1734 // MyNotebook::OnEndSeek
1735 //
1736 // Called from file->seek.
1737 // Called when the user moves the slider -
1738 // seeks to a position within the media
1739 // then sets m_bIsBeingDragged to false to ok the timer to change the position
1740 // ----------------------------------------------------------------------------
OnEndSeek(wxScrollEvent & WXUNUSED (event))1741 void wxMediaPlayerNotebookPage::OnEndSeek(wxScrollEvent& WXUNUSED(event))
1742 {
1743     if( m_mediactrl->Seek(
1744             m_slider->GetValue() * 1000
1745                                    ) == wxInvalidOffset )
1746         wxMessageBox(wxT("Couldn't seek in movie!"));
1747 
1748     m_bIsBeingDragged = false;
1749 }
1750 
1751 // ----------------------------------------------------------------------------
1752 // wxMediaPlayerNotebookPage::IsBeingDragged
1753 //
1754 // Returns true if the user is dragging the slider
1755 // ----------------------------------------------------------------------------
IsBeingDragged()1756 bool wxMediaPlayerNotebookPage::IsBeingDragged()
1757 {
1758     return m_bIsBeingDragged;
1759 }
1760 
1761 // ----------------------------------------------------------------------------
1762 // wxMediaPlayerNotebookPage::OnVolChange
1763 //
1764 // Called when the user is done dragging the volume-changing slider
1765 // ----------------------------------------------------------------------------
OnVolChange(wxScrollEvent & WXUNUSED (event))1766 void wxMediaPlayerNotebookPage::OnVolChange(wxScrollEvent& WXUNUSED(event))
1767 {
1768     if( m_mediactrl->SetVolume(
1769             m_volSlider->GetValue() / 100.0
1770                                    ) == false )
1771         wxMessageBox(wxT("Couldn't set volume!"));
1772 
1773 }
1774 
1775 // ----------------------------------------------------------------------------
1776 // wxMediaPlayerNotebookPage::OnPBChange
1777 //
1778 // Called when the user is done dragging the speed-changing slider
1779 // ----------------------------------------------------------------------------
OnPBChange(wxScrollEvent & WXUNUSED (event))1780 void wxMediaPlayerNotebookPage::OnPBChange(wxScrollEvent& WXUNUSED(event))
1781 {
1782     if( m_mediactrl->SetPlaybackRate(
1783             m_pbSlider->GetValue() * .25
1784                                    ) == false )
1785         wxMessageBox(wxT("Couldn't set playbackrate!"));
1786 
1787 }
1788 
1789 // ----------------------------------------------------------------------------
1790 // wxMediaPlayerNotebookPage::OnMediaPlay
1791 //
1792 // Called when the media plays.
1793 // ----------------------------------------------------------------------------
OnMediaPlay(wxMediaEvent & WXUNUSED (event))1794 void wxMediaPlayerNotebookPage::OnMediaPlay(wxMediaEvent& WXUNUSED(event))
1795 {
1796     m_playlist->SetItem(m_nLastFileId, 0, wxT(">"));
1797 }
1798 
1799 // ----------------------------------------------------------------------------
1800 // wxMediaPlayerNotebookPage::OnMediaPause
1801 //
1802 // Called when the media is paused.
1803 // ----------------------------------------------------------------------------
OnMediaPause(wxMediaEvent & WXUNUSED (event))1804 void wxMediaPlayerNotebookPage::OnMediaPause(wxMediaEvent& WXUNUSED(event))
1805 {
1806     m_playlist->SetItem(m_nLastFileId, 0, wxT("||"));
1807 }
1808 
1809 // ----------------------------------------------------------------------------
1810 // wxMediaPlayerNotebookPage::OnMediaStop
1811 //
1812 // Called when the media stops.
1813 // ----------------------------------------------------------------------------
OnMediaStop(wxMediaEvent & WXUNUSED (event))1814 void wxMediaPlayerNotebookPage::OnMediaStop(wxMediaEvent& WXUNUSED(event))
1815 {
1816     m_playlist->SetItem(m_nLastFileId, 0, wxT("[]"));
1817 }
1818 
1819 // ----------------------------------------------------------------------------
1820 // wxMediaPlayerNotebookPage::OnMediaFinished
1821 //
1822 // Called when the media finishes playing.
1823 // Here we loop it if the user wants to (has been selected from file menu)
1824 // ----------------------------------------------------------------------------
OnMediaFinished(wxMediaEvent & WXUNUSED (event))1825 void wxMediaPlayerNotebookPage::OnMediaFinished(wxMediaEvent& WXUNUSED(event))
1826 {
1827     if(m_bLoop)
1828     {
1829         if ( !m_mediactrl->Play() )
1830         {
1831             wxMessageBox(wxT("Couldn't loop movie!"));
1832             m_playlist->SetItem(m_nLastFileId, 0, wxT("E"));
1833         }
1834         else
1835             ++m_nLoops;
1836     }
1837     else
1838     {
1839         m_playlist->SetItem(m_nLastFileId, 0, wxT("[]"));
1840     }
1841 }
1842 
1843 //
1844 // End of MediaPlayer sample
1845 //
1846