Ryan's cumulative wxActiveX and media control patch (1427775)
[wxWidgets.git] / samples / mediaplayer / mediaplayer.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: mediaplayer.cpp
3 // Purpose: wxMediaCtrl sample
4 // Author: Ryan Norton
5 // Modified by:
6 // Created: 11/10/04
7 // RCS-ID: $Id$
8 // Copyright: (c) Ryan Norton
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 // MediaPlayer
14 //
15 // This is a 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
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:
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
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:
336 wxPlayListDropTarget(wxMediaPlayerListCtrl& list) : m_list(list) {}
337 ~wxPlayListDropTarget(){}
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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
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
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
768 void wxMediaPlayerFrame::OnClose(wxCloseEvent& event)
769 {
770 event.Skip(); //really close the frame
771 }
772
773 // ----------------------------------------------------------------------------
774 // wxMediaPlayerFrame::AddToPlayList
775 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
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 //