fixes as per http://thread.gmane.org/gmane.comp.lib.wxwidgets.devel/92325
[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 if ( !wxApp::OnInit() )
413 return false;
414
415 // SetAppName() lets wxConfig and others know where to write
416 SetAppName(wxT("wxMediaPlayer"));
417
418 wxMediaPlayerFrame *frame =
419 new wxMediaPlayerFrame(wxT("MediaPlayer wxWidgets Sample"));
420 frame->Show(true);
421
422 #if wxUSE_CMDLINE_PARSER
423 //
424 // What this does is get all the command line arguments
425 // and treat each one as a file to put to the initial playlist
426 //
427 wxCmdLineEntryDesc cmdLineDesc[2];
428 cmdLineDesc[0].kind = wxCMD_LINE_PARAM;
429 cmdLineDesc[0].shortName = NULL;
430 cmdLineDesc[0].longName = NULL;
431 cmdLineDesc[0].description = "input files";
432 cmdLineDesc[0].type = wxCMD_LINE_VAL_STRING;
433 cmdLineDesc[0].flags = wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE;
434
435 cmdLineDesc[1].kind = wxCMD_LINE_NONE;
436
437 //gets the passed media files from cmd line
438 wxCmdLineParser parser (cmdLineDesc, argc, argv);
439
440 // get filenames from the commandline
441 if (parser.Parse() == 0)
442 {
443 for (size_t paramNr=0; paramNr < parser.GetParamCount(); ++paramNr)
444 {
445 frame->AddToPlayList((parser.GetParam (paramNr)));
446 }
447 wxCommandEvent theEvent(wxEVT_COMMAND_MENU_SELECTED, wxID_NEXT);
448 frame->AddPendingEvent(theEvent);
449 }
450 #endif
451
452 return true;
453 }
454
455 #ifdef __WXMAC__
456
457 void wxMediaPlayerApp::MacOpenFile(const wxString & fileName )
458 {
459 //Called when a user drags a file over our app
460 m_frame->DoOpenFile(fileName, true /* new page */);
461 }
462
463 #endif // __WXMAC__
464
465 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
466 //
467 // wxMediaPlayerFrame
468 //
469 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
470
471 // ----------------------------------------------------------------------------
472 // wxMediaPlayerFrame Constructor
473 //
474 // 1) Create our menus
475 // 2) Create our notebook control and add it to the frame
476 // 3) Create our status bar
477 // 4) Connect our events
478 // 5) Start our timer
479 // ----------------------------------------------------------------------------
480
481 wxMediaPlayerFrame::wxMediaPlayerFrame(const wxString& title)
482 : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(600,600))
483 {
484 //
485 // Create Menus
486 //
487 wxMenu *fileMenu = new wxMenu;
488 wxMenu *controlsMenu = new wxMenu;
489 wxMenu *optionsMenu = new wxMenu;
490 wxMenu *helpMenu = new wxMenu;
491 wxMenu *debugMenu = new wxMenu;
492
493 fileMenu->Append(wxID_OPENFILESAMEPAGE, wxT("&Open File\tCtrl-Shift-O"),
494 wxT("Open a File in the current notebook page"));
495 fileMenu->Append(wxID_OPENFILENEWPAGE, wxT("&Open File in a new page"),
496 wxT("Open a File in a new notebook page"));
497 fileMenu->Append(wxID_OPENURLSAMEPAGE, wxT("&Open URL"),
498 wxT("Open a URL in the current notebook page"));
499 fileMenu->Append(wxID_OPENURLNEWPAGE, wxT("&Open URL in a new page"),
500 wxT("Open a URL in a new notebook page"));
501 fileMenu->AppendSeparator();
502 fileMenu->Append(wxID_CLOSECURRENTPAGE, wxT("&Close Current Page\tCtrl-C"),
503 wxT("Close current notebook page"));
504 fileMenu->AppendSeparator();
505 fileMenu->Append(wxID_EXIT,
506 wxT("E&xit\tAlt-X"),
507 wxT("Quit this program"));
508
509 controlsMenu->Append(wxID_PLAY, wxT("&Play/Pause\tCtrl-P"), wxT("Resume/Pause playback"));
510 controlsMenu->Append(wxID_STOP, wxT("&Stop\tCtrl-S"), wxT("Stop playback"));
511 controlsMenu->AppendSeparator();
512 controlsMenu->Append(wxID_PREV, wxT("&Previous\tCtrl-B"), wxT("Go to previous track"));
513 controlsMenu->Append(wxID_NEXT, wxT("&Next\tCtrl-N"), wxT("Skip to next track"));
514
515 optionsMenu->AppendCheckItem(wxID_LOOP,
516 wxT("&Loop\tCtrl-L"),
517 wxT("Loop Selected Media"));
518 optionsMenu->AppendCheckItem(wxID_SHOWINTERFACE,
519 wxT("&Show Interface\tCtrl-I"),
520 wxT("Show wxMediaCtrl native controls"));
521
522 debugMenu->Append(wxID_SELECTBACKEND,
523 wxT("&Select Backend...\tCtrl-D"),
524 wxT("Select a backend manually"));
525
526 helpMenu->Append(wxID_ABOUT,
527 wxT("&About...\tF1"),
528 wxT("Show about dialog"));
529
530
531 wxMenuBar *menuBar = new wxMenuBar();
532 menuBar->Append(fileMenu, wxT("&File"));
533 menuBar->Append(controlsMenu, wxT("&Controls"));
534 menuBar->Append(optionsMenu, wxT("&Options"));
535 menuBar->Append(debugMenu, wxT("&Debug"));
536 menuBar->Append(helpMenu, wxT("&Help"));
537 SetMenuBar(menuBar);
538
539 //
540 // Create our notebook - using wxNotebook is luckily pretty
541 // simple and self-explanatory in most cases
542 //
543 m_notebook = new wxNotebook(this, wxID_NOTEBOOK);
544
545 //
546 // Create our status bar
547 //
548 #if wxUSE_STATUSBAR
549 // create a status bar just for fun (by default with 1 pane only)
550 CreateStatusBar(1);
551 #endif // wxUSE_STATUSBAR
552
553 //
554 // Connect events.
555 //
556 // There are two ways in wxWidgets to use events -
557 // Message Maps and Connections.
558 //
559 // Message Maps are implemented by putting
560 // DECLARE_MESSAGE_MAP in your wxEvtHandler-derived
561 // class you want to use for events, such as wxMediaPlayerFrame.
562 //
563 // Then after your class declaration you put
564 // BEGIN_EVENT_TABLE(wxMediaPlayerFrame, wxFrame)
565 // EVT_XXX(XXX)...
566 // END_EVENT_TABLE()
567 //
568 // Where wxMediaPlayerFrame is the class with the DECLARE_MESSAGE_MAP
569 // in it. EVT_XXX(XXX) are each of your handlers, such
570 // as EVT_MENU for menu events and the XXX inside
571 // is the parameters to the event macro - in the case
572 // of EVT_MENU the menu id and then the function to call.
573 //
574 // However, with wxEvtHandler::Connect you can avoid a
575 // global message map for your class and those annoying
576 // macros. You can also change the context in which
577 // the call the handler (more later).
578 //
579 // The downside is that due to the limitation that
580 // wxWidgets doesn't use templates in certain areas,
581 // You have to triple-cast the event function.
582 //
583 // There are five parameters to wxEvtHandler::Connect -
584 //
585 // The first is the id of the instance whose events
586 // you want to handle - i.e. a menu id for menus,
587 // a control id for controls (wxControl::GetId())
588 // and so on.
589 //
590 // The second is the event id. This is the same
591 // as the message maps (EVT_MENU) except prefixed
592 // with "wx" (wxEVT_MENU).
593 //
594 // The third is the function handler for the event -
595 // You need to cast it to the specific event handler
596 // type, then to a wxEventFunction, then to a
597 // wxObjectEventFunction - I.E.
598 // (wxObjectEventFunction)(wxEventFunction)
599 // (wxCommandEventFunction) &wxMediaPlayerFrame::MyHandler
600 //
601 // Or, you can use the new (2.5.5+) event handler
602 // conversion macros - for instance the above could
603 // be done as
604 // wxCommandEventHandler(wxMediaPlayerFrame::MyHandler)
605 // pretty simple, eh?
606 //
607 // The fourth is an optional userdata param -
608 // this is of historical relevance only and is
609 // there only for backwards compatibility.
610 //
611 // The fifth is the context in which to call the
612 // handler - by default (this param is optional)
613 // this. For example in your event handler
614 // if you were to call "this->MyFunc()"
615 // it would literally do this->MyFunc. However,
616 // if you were to pass myHandler as the fifth
617 // parameter, for instance, you would _really_
618 // be calling myHandler->MyFunc, even though
619 // the compiler doesn't really know it.
620 //
621
622 //
623 // Menu events
624 //
625 this->Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED,
626 wxCommandEventHandler(wxMediaPlayerFrame::OnQuit));
627
628 this->Connect(wxID_ABOUT, wxEVT_COMMAND_MENU_SELECTED,
629 wxCommandEventHandler(wxMediaPlayerFrame::OnAbout));
630
631 this->Connect(wxID_LOOP, wxEVT_COMMAND_MENU_SELECTED,
632 wxCommandEventHandler(wxMediaPlayerFrame::OnLoop));
633
634 this->Connect(wxID_SHOWINTERFACE, wxEVT_COMMAND_MENU_SELECTED,
635 wxCommandEventHandler(wxMediaPlayerFrame::OnShowInterface));
636
637 this->Connect(wxID_OPENFILENEWPAGE, wxEVT_COMMAND_MENU_SELECTED,
638 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileNewPage));
639
640 this->Connect(wxID_OPENFILESAMEPAGE, wxEVT_COMMAND_MENU_SELECTED,
641 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileSamePage));
642
643 this->Connect(wxID_OPENURLNEWPAGE, wxEVT_COMMAND_MENU_SELECTED,
644 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLNewPage));
645
646 this->Connect(wxID_OPENURLSAMEPAGE, wxEVT_COMMAND_MENU_SELECTED,
647 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLSamePage));
648
649 this->Connect(wxID_CLOSECURRENTPAGE, wxEVT_COMMAND_MENU_SELECTED,
650 wxCommandEventHandler(wxMediaPlayerFrame::OnCloseCurrentPage));
651
652 this->Connect(wxID_PLAY, wxEVT_COMMAND_MENU_SELECTED,
653 wxCommandEventHandler(wxMediaPlayerFrame::OnPlay));
654
655 this->Connect(wxID_STOP, wxEVT_COMMAND_MENU_SELECTED,
656 wxCommandEventHandler(wxMediaPlayerFrame::OnStop));
657
658 this->Connect(wxID_NEXT, wxEVT_COMMAND_MENU_SELECTED,
659 wxCommandEventHandler(wxMediaPlayerFrame::OnNext));
660
661 this->Connect(wxID_PREV, wxEVT_COMMAND_MENU_SELECTED,
662 wxCommandEventHandler(wxMediaPlayerFrame::OnPrev));
663
664 this->Connect(wxID_SELECTBACKEND, wxEVT_COMMAND_MENU_SELECTED,
665 wxCommandEventHandler(wxMediaPlayerFrame::OnSelectBackend));
666
667 //
668 // Key events
669 //
670 wxTheApp->Connect(wxID_ANY, wxEVT_KEY_DOWN,
671 wxKeyEventHandler(wxMediaPlayerFrame::OnKeyDown),
672 (wxObject*)0, this);
673
674 //
675 // Close events
676 //
677 this->Connect(wxID_ANY, wxEVT_CLOSE_WINDOW,
678 wxCloseEventHandler(wxMediaPlayerFrame::OnClose));
679
680 //
681 // End of Events
682 //
683
684 //
685 // Create an initial notebook page so the user has something
686 // to work with without having to go file->open every time :).
687 //
688 wxMediaPlayerNotebookPage* page =
689 new wxMediaPlayerNotebookPage(this, m_notebook);
690 m_notebook->AddPage(page,
691 wxT(""),
692 true);
693
694 //
695 // Here we load the our configuration -
696 // in our case we load all the files that were left in
697 // the playlist the last time the user closed our application
698 //
699 // As an exercise to the reader try modifying it so that
700 // it properly loads the playlist for each page without
701 // conflicting (loading the same data) with the other ones.
702 //
703 wxConfig conf;
704 wxString key, outstring;
705 for(int i = 0; ; ++i)
706 {
707 key.clear();
708 key << i;
709 if(!conf.Read(key, &outstring))
710 break;
711 page->m_playlist->AddToPlayList(outstring);
712 }
713
714 //
715 // Create a timer to update our status bar
716 //
717 m_timer = new wxMediaPlayerTimer(this);
718 m_timer->Start(500);
719 }
720
721 // ----------------------------------------------------------------------------
722 // wxMediaPlayerFrame Destructor
723 //
724 // 1) Deletes child objects implicitly
725 // 2) Delete our timer explicitly
726 // ----------------------------------------------------------------------------
727 wxMediaPlayerFrame::~wxMediaPlayerFrame()
728 {
729 // Shut down our timer
730 delete m_timer;
731
732 //
733 // Here we save our info to the registry or whatever
734 // mechanism the OS uses.
735 //
736 // This makes it so that when mediaplayer loads up again
737 // it restores the same files that were in the playlist
738 // this time, rather than the user manually re-adding them.
739 //
740 // We need to do conf->DeleteAll() here because by default
741 // the config still contains the same files as last time
742 // so we need to clear it before writing our new ones.
743 //
744 // TODO: Maybe you could add a menu option to the
745 // options menu to delete the configuration on exit -
746 // all you'd need to do is just remove everything after
747 // conf->DeleteAll() here
748 //
749 // As an exercise to the reader, try modifying this so
750 // that it saves the data for each notebook page
751 //
752 wxMediaPlayerListCtrl* playlist =
753 ((wxMediaPlayerNotebookPage*)m_notebook->GetPage(0))->m_playlist;
754
755 wxConfig conf;
756 conf.DeleteAll();
757
758 for(int i = 0; i < playlist->GetItemCount(); ++i)
759 {
760 wxString* pData = (wxString*) playlist->GetItemData(i);
761 wxString s;
762 s << i;
763 conf.Write(s, *(pData));
764 delete pData;
765 }
766 }
767
768 // ----------------------------------------------------------------------------
769 // wxMediaPlayerFrame::OnClose
770 // ----------------------------------------------------------------------------
771 void wxMediaPlayerFrame::OnClose(wxCloseEvent& event)
772 {
773 event.Skip(); //really close the frame
774 }
775
776 // ----------------------------------------------------------------------------
777 // wxMediaPlayerFrame::AddToPlayList
778 // ----------------------------------------------------------------------------
779 void wxMediaPlayerFrame::AddToPlayList(const wxString& szString)
780 {
781 wxMediaPlayerNotebookPage* currentpage =
782 ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage());
783
784 currentpage->m_playlist->AddToPlayList(szString);
785 }
786
787 // ----------------------------------------------------------------------------
788 // wxMediaPlayerFrame::OnQuit
789 //
790 // Called from file->quit.
791 // Closes this application.
792 // ----------------------------------------------------------------------------
793 void wxMediaPlayerFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
794 {
795 // true is to force the frame to close
796 Close(true);
797 }
798
799 // ----------------------------------------------------------------------------
800 // wxMediaPlayerFrame::OnAbout
801 //
802 // Called from help->about.
803 // Gets some info about this application.
804 // ----------------------------------------------------------------------------
805 void wxMediaPlayerFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
806 {
807 wxString msg;
808 msg.Printf( wxT("This is a test of wxMediaCtrl.\n\n")
809
810 wxT("Intructions:\n")
811
812 wxT("The top slider shows the current the current position, ")
813 wxT("which you can change by dragging and releasing it.\n")
814
815 wxT("The gauge (progress bar) shows the progress in ")
816 wxT("downloading data of the current file - it may always be ")
817 wxT("Empty due to lack of support from the current backend.\n")
818
819 wxT("The lower-left slider controls the volume and the lower-")
820 wxT("right slider controls the playback rate/speed of the ")
821 wxT("media\n\n")
822
823 wxT("Currently using: %s"), wxVERSION_STRING);
824
825 wxMessageBox(msg, wxT("About wxMediaCtrl test"),
826 wxOK | wxICON_INFORMATION, this);
827 }
828
829 // ----------------------------------------------------------------------------
830 // wxMediaPlayerFrame::OnLoop
831 //
832 // Called from file->loop.
833 // Changes the state of whether we want to loop or not.
834 // ----------------------------------------------------------------------------
835 void wxMediaPlayerFrame::OnLoop(wxCommandEvent& WXUNUSED(event))
836 {
837 wxMediaPlayerNotebookPage* currentpage =
838 ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage());
839
840 currentpage->m_bLoop = !currentpage->m_bLoop;
841 }
842
843 // ----------------------------------------------------------------------------
844 // wxMediaPlayerFrame::OnLoop
845 //
846 // Called from file->loop.
847 // Changes the state of whether we want to loop or not.
848 // ----------------------------------------------------------------------------
849 void wxMediaPlayerFrame::OnShowInterface(wxCommandEvent& event)
850 {
851 wxMediaPlayerNotebookPage* currentpage =
852 ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage());
853
854 if( !currentpage->m_mediactrl->ShowPlayerControls(event.IsChecked() ?
855 wxMEDIACTRLPLAYERCONTROLS_DEFAULT :
856 wxMEDIACTRLPLAYERCONTROLS_NONE) )
857 {
858 //error - uncheck and warn user
859 wxMenuItem* pSIItem = GetMenuBar()->FindItem(wxID_SHOWINTERFACE);
860 wxASSERT(pSIItem);
861 pSIItem->Check(!event.IsChecked());
862
863 if(event.IsChecked())
864 wxMessageBox(wxT("Could not show player controls"));
865 else
866 wxMessageBox(wxT("Could not hide player controls"));
867 }
868 }
869
870 // ----------------------------------------------------------------------------
871 // wxMediaPlayerFrame::OnOpenFileSamePage
872 //
873 // Called from file->openfile.
874 // Opens and plays a media file in the current notebook page
875 // ----------------------------------------------------------------------------
876 void wxMediaPlayerFrame::OnOpenFileSamePage(wxCommandEvent& WXUNUSED(event))
877 {
878 OpenFile(false);
879 }
880
881 // ----------------------------------------------------------------------------
882 // wxMediaPlayerFrame::OnOpenFileNewPage
883 //
884 // Called from file->openfileinnewpage.
885 // Opens and plays a media file in a new notebook page
886 // ----------------------------------------------------------------------------
887 void wxMediaPlayerFrame::OnOpenFileNewPage(wxCommandEvent& WXUNUSED(event))
888 {
889 OpenFile(true);
890 }
891
892 // ----------------------------------------------------------------------------
893 // wxMediaPlayerFrame::OpenFile
894 //
895 // Opens a file dialog asking the user for a filename, then
896 // calls DoOpenFile which will add the file to the playlist and play it
897 // ----------------------------------------------------------------------------
898 void wxMediaPlayerFrame::OpenFile(bool bNewPage)
899 {
900 wxFileDialog fd(this);
901
902 if(fd.ShowModal() == wxID_OK)
903 {
904 DoOpenFile(fd.GetPath(), bNewPage);
905 }
906 }
907
908 // ----------------------------------------------------------------------------
909 // wxMediaPlayerFrame::DoOpenFile
910 //
911 // Adds the file to our playlist, selects it in the playlist,
912 // and then calls DoPlayFile to play it
913 // ----------------------------------------------------------------------------
914 void wxMediaPlayerFrame::DoOpenFile(const wxString& path, bool bNewPage)
915 {
916 if(bNewPage)
917 {
918 m_notebook->AddPage(
919 new wxMediaPlayerNotebookPage(this, m_notebook),
920 path,
921 true);
922 }
923
924 wxMediaPlayerNotebookPage* currentpage =
925 (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
926
927 if(currentpage->m_nLastFileId != -1)
928 currentpage->m_playlist->SetItemState(currentpage->m_nLastFileId,
929 0, wxLIST_STATE_SELECTED);
930
931 wxListItem newlistitem;
932 newlistitem.SetAlign(wxLIST_FORMAT_LEFT);
933
934 int nID;
935
936 newlistitem.SetId(nID = currentpage->m_playlist->GetItemCount());
937 newlistitem.SetMask(wxLIST_MASK_DATA | wxLIST_MASK_STATE);
938 newlistitem.SetState(wxLIST_STATE_SELECTED);
939 newlistitem.SetData(new wxString(path));
940
941 currentpage->m_playlist->InsertItem(newlistitem);
942 currentpage->m_playlist->SetItem(nID, 0, wxT("*"));
943 currentpage->m_playlist->SetItem(nID, 1, wxFileName(path).GetName());
944
945 if (nID % 2)
946 {
947 newlistitem.SetBackgroundColour(wxColour(192,192,192));
948 currentpage->m_playlist->SetItem(newlistitem);
949 }
950
951 DoPlayFile(path);
952 }
953
954 // ----------------------------------------------------------------------------
955 // wxMediaPlayerFrame::DoPlayFile
956 //
957 // Pauses the file if its the currently playing file,
958 // otherwise it plays the file
959 // ----------------------------------------------------------------------------
960 void wxMediaPlayerFrame::DoPlayFile(const wxString& path)
961 {
962 wxMediaPlayerNotebookPage* currentpage =
963 (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
964
965 wxListItem listitem;
966 currentpage->m_playlist->GetSelectedItem(listitem);
967
968 if( ( listitem.GetData() &&
969 currentpage->m_nLastFileId == listitem.GetId() &&
970 currentpage->m_szFile.compare(path) == 0 ) ||
971 ( !listitem.GetData() &&
972 currentpage->m_nLastFileId != -1 &&
973 currentpage->m_szFile.compare(path) == 0)
974 )
975 {
976 if(currentpage->m_mediactrl->GetState() == wxMEDIASTATE_PLAYING)
977 {
978 if( !currentpage->m_mediactrl->Pause() )
979 wxMessageBox(wxT("Couldn't pause movie!"));
980 }
981 else
982 {
983 if( !currentpage->m_mediactrl->Play() )
984 wxMessageBox(wxT("Couldn't play movie!"));
985 }
986 }
987 else
988 {
989 int nNewId = listitem.GetData() ? listitem.GetId() :
990 currentpage->m_playlist->GetItemCount()-1;
991 m_notebook->SetPageText(m_notebook->GetSelection(),
992 wxFileName(path).GetName());
993
994 if(currentpage->m_nLastFileId != -1)
995 currentpage->m_playlist->SetItem(
996 currentpage->m_nLastFileId, 0, wxT("*"));
997
998 wxURI uripath(path);
999 if( uripath.IsReference() )
1000 {
1001 if( !currentpage->m_mediactrl->Load(path) )
1002 {
1003 wxMessageBox(wxT("Couldn't load file!"));
1004 currentpage->m_playlist->SetItem(nNewId, 0, wxT("E"));
1005 }
1006 else
1007 {
1008 currentpage->m_playlist->SetItem(nNewId, 0, wxT("O"));
1009 }
1010 }
1011 else
1012 {
1013 if( !currentpage->m_mediactrl->Load(uripath) )
1014 {
1015 wxMessageBox(wxT("Couldn't load URL!"));
1016 currentpage->m_playlist->SetItem(nNewId, 0, wxT("E"));
1017 }
1018 else
1019 {
1020 currentpage->m_playlist->SetItem(nNewId, 0, wxT("O"));
1021 }
1022 }
1023
1024 currentpage->m_nLastFileId = nNewId;
1025 currentpage->m_szFile = path;
1026 currentpage->m_playlist->SetItem(currentpage->m_nLastFileId,
1027 1, wxFileName(path).GetName());
1028 currentpage->m_playlist->SetItem(currentpage->m_nLastFileId,
1029 2, wxT(""));
1030 }
1031 }
1032
1033 // ----------------------------------------------------------------------------
1034 // wxMediaPlayerFrame::OnMediaLoaded
1035 //
1036 // Called when the media is ready to be played - and does
1037 // so, also gets the length of media and shows that in the list control
1038 // ----------------------------------------------------------------------------
1039 void wxMediaPlayerFrame::OnMediaLoaded(wxMediaEvent& WXUNUSED(evt))
1040 {
1041 wxMediaPlayerNotebookPage* currentpage =
1042 (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
1043
1044 if( !currentpage->m_mediactrl->Play() )
1045 {
1046 wxMessageBox(wxT("Couldn't play movie!"));
1047 currentpage->m_playlist->SetItem(currentpage->m_nLastFileId, 0, wxT("E"));
1048 }
1049 else
1050 {
1051 currentpage->m_playlist->SetItem(currentpage->m_nLastFileId, 0, wxT(">"));
1052 }
1053
1054 }
1055
1056
1057 // ----------------------------------------------------------------------------
1058 // wxMediaPlayerFrame::OnSelectBackend
1059 //
1060 // Little debugging routine - enter the class name of a backend and it
1061 // will use that instead of letting wxMediaCtrl search the wxMediaBackend
1062 // RTTI class list.
1063 // ----------------------------------------------------------------------------
1064 void wxMediaPlayerFrame::OnSelectBackend(wxCommandEvent& WXUNUSED(evt))
1065 {
1066 wxString sBackend = wxGetTextFromUser(wxT("Enter backend to use"));
1067
1068 if(sBackend.empty() == false) //could have been cancelled by the user
1069 {
1070 int sel = m_notebook->GetSelection();
1071
1072 if (sel != wxNOT_FOUND)
1073 {
1074 m_notebook->DeletePage(sel);
1075 }
1076
1077 m_notebook->AddPage(new wxMediaPlayerNotebookPage(this, m_notebook,
1078 sBackend
1079 ), wxT(""), true);
1080
1081 DoOpenFile(
1082 ((wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage())->m_szFile,
1083 false);
1084 }
1085 }
1086
1087 // ----------------------------------------------------------------------------
1088 // wxMediaPlayerFrame::OnOpenURLSamePage
1089 //
1090 // Called from file->openurl.
1091 // Opens and plays a media file from a URL in the current notebook page
1092 // ----------------------------------------------------------------------------
1093 void wxMediaPlayerFrame::OnOpenURLSamePage(wxCommandEvent& WXUNUSED(event))
1094 {
1095 OpenURL(false);
1096 }
1097
1098 // ----------------------------------------------------------------------------
1099 // wxMediaPlayerFrame::OnOpenURLNewPage
1100 //
1101 // Called from file->openurlinnewpage.
1102 // Opens and plays a media file from a URL in a new notebook page
1103 // ----------------------------------------------------------------------------
1104 void wxMediaPlayerFrame::OnOpenURLNewPage(wxCommandEvent& WXUNUSED(event))
1105 {
1106 OpenURL(true);
1107 }
1108
1109 // ----------------------------------------------------------------------------
1110 // wxMediaPlayerFrame::OpenURL
1111 //
1112 // Just calls DoOpenFile with the url path - which calls DoPlayFile
1113 // which handles the real dirty work
1114 // ----------------------------------------------------------------------------
1115 void wxMediaPlayerFrame::OpenURL(bool bNewPage)
1116 {
1117 wxString sUrl = wxGetTextFromUser(
1118 wxT("Enter the URL that has the movie to play")
1119 );
1120
1121 if(sUrl.empty() == false) //could have been cancelled by user
1122 {
1123 DoOpenFile(sUrl, bNewPage);
1124 }
1125 }
1126
1127 // ----------------------------------------------------------------------------
1128 // wxMediaPlayerFrame::OnCloseCurrentPage
1129 //
1130 // Called when the user wants to close the current notebook page
1131 //
1132 // 1) Get the current page number (wxControl::GetSelection)
1133 // 2) If there is no current page, break out
1134 // 3) Delete the current page
1135 // ----------------------------------------------------------------------------
1136 void wxMediaPlayerFrame::OnCloseCurrentPage(wxCommandEvent& WXUNUSED(event))
1137 {
1138 if( m_notebook->GetPageCount() > 1 )
1139 {
1140 int sel = m_notebook->GetSelection();
1141
1142 if (sel != wxNOT_FOUND)
1143 {
1144 m_notebook->DeletePage(sel);
1145 }
1146 }
1147 else
1148 {
1149 wxMessageBox(wxT("Cannot close main page"));
1150 }
1151 }
1152
1153 // ----------------------------------------------------------------------------
1154 // wxMediaPlayerFrame::OnPlay
1155 //
1156 // Called from file->play.
1157 // Resumes the media if it is paused or stopped.
1158 // ----------------------------------------------------------------------------
1159 void wxMediaPlayerFrame::OnPlay(wxCommandEvent& WXUNUSED(event))
1160 {
1161 wxMediaPlayerNotebookPage* currentpage =
1162 (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
1163
1164 wxListItem listitem;
1165 currentpage->m_playlist->GetSelectedItem(listitem);
1166 if ( !listitem.GetData() )
1167 {
1168 int nLast = -1;
1169 if ((nLast = currentpage->m_playlist->GetNextItem(nLast,
1170 wxLIST_NEXT_ALL,
1171 wxLIST_STATE_DONTCARE)) == -1)
1172 {
1173 //no items in list
1174 wxMessageBox(wxT("No items in playlist!"));
1175 }
1176 else
1177 {
1178 listitem.SetId(nLast);
1179 currentpage->m_playlist->GetItem(listitem);
1180 listitem.SetMask(listitem.GetMask() | wxLIST_MASK_STATE);
1181 listitem.SetState(listitem.GetState() | wxLIST_STATE_SELECTED);
1182 currentpage->m_playlist->SetItem(listitem);
1183 wxASSERT(listitem.GetData());
1184 DoPlayFile((*((wxString*) listitem.GetData())));
1185 }
1186 }
1187 else
1188 {
1189 wxASSERT(listitem.GetData());
1190 DoPlayFile((*((wxString*) listitem.GetData())));
1191 }
1192 }
1193
1194 // ----------------------------------------------------------------------------
1195 // wxMediaPlayerFrame::OnKeyDown
1196 //
1197 // Deletes all selected files from the playlist if the backspace key is pressed
1198 // ----------------------------------------------------------------------------
1199 void wxMediaPlayerFrame::OnKeyDown(wxKeyEvent& event)
1200 {
1201 if(event.GetKeyCode() == WXK_BACK/*DELETE*/)
1202 {
1203 wxMediaPlayerNotebookPage* currentpage =
1204 (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
1205 //delete all selected items
1206 while(true)
1207 {
1208 wxInt32 nSelectedItem = currentpage->m_playlist->GetNextItem(
1209 -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
1210 if (nSelectedItem == -1)
1211 break;
1212
1213 wxListItem listitem;
1214 listitem.SetId(nSelectedItem);
1215 currentpage->m_playlist->GetItem(listitem);
1216 delete (wxString*) listitem.GetData();
1217
1218 currentpage->m_playlist->DeleteItem(nSelectedItem);
1219 }
1220 }
1221
1222 //Could be wxGetTextFromUser or something else important
1223 if(event.GetEventObject() != this)
1224 event.Skip();
1225 }
1226
1227 // ----------------------------------------------------------------------------
1228 // wxMediaPlayerFrame::OnStop
1229 //
1230 // Called from file->stop.
1231 // Where it stops depends on whether you can seek in the
1232 // media control or not - if you can it stops and seeks to the beginning,
1233 // otherwise it will appear to be at the end - but it will start over again
1234 // when Play() is called
1235 // ----------------------------------------------------------------------------
1236 void wxMediaPlayerFrame::OnStop(wxCommandEvent& WXUNUSED(evt))
1237 {
1238 wxMediaPlayerNotebookPage* currentpage =
1239 (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
1240
1241 if( !currentpage->m_mediactrl->Stop() )
1242 wxMessageBox(wxT("Couldn't stop movie!"));
1243 else
1244 currentpage->m_playlist->SetItem(
1245 currentpage->m_nLastFileId, 0, wxT("[]"));
1246 }
1247
1248
1249 // ----------------------------------------------------------------------------
1250 // wxMediaPlayerFrame::OnChangeSong
1251 //
1252 // Routine that plays the currently selected file in the playlist.
1253 // Called when the user actives the song from the playlist,
1254 // and from other various places in the sample
1255 // ----------------------------------------------------------------------------
1256 void wxMediaPlayerFrame::OnChangeSong(wxListEvent& WXUNUSED(evt))
1257 {
1258 wxMediaPlayerNotebookPage* currentpage =
1259 (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
1260
1261 wxListItem listitem;
1262 currentpage->m_playlist->GetSelectedItem(listitem);
1263 if(listitem.GetData())
1264 DoPlayFile((*((wxString*) listitem.GetData())));
1265 else
1266 wxMessageBox(wxT("No selected item!"));
1267 }
1268
1269 // ----------------------------------------------------------------------------
1270 // wxMediaPlayerFrame::OnPrev
1271 //
1272 // Tedious wxListCtrl stuff. Goes to prevous song in list, or if at the
1273 // beginning goes to the last in the list.
1274 // ----------------------------------------------------------------------------
1275 void wxMediaPlayerFrame::OnPrev(wxCommandEvent& WXUNUSED(event))
1276 {
1277 wxMediaPlayerNotebookPage* currentpage =
1278 (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
1279
1280 if (currentpage->m_playlist->GetItemCount() == 0)
1281 return;
1282
1283 wxInt32 nLastSelectedItem = -1;
1284 while(true)
1285 {
1286 wxInt32 nSelectedItem = currentpage->m_playlist->GetNextItem(nLastSelectedItem,
1287 wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
1288 if (nSelectedItem == -1)
1289 break;
1290 nLastSelectedItem = nSelectedItem;
1291 currentpage->m_playlist->SetItemState(nSelectedItem, 0, wxLIST_STATE_SELECTED);
1292 }
1293
1294 if (nLastSelectedItem == -1)
1295 {
1296 //nothing selected, default to the file before the currently playing one
1297 if(currentpage->m_nLastFileId == 0)
1298 nLastSelectedItem = currentpage->m_playlist->GetItemCount() - 1;
1299 else
1300 nLastSelectedItem = currentpage->m_nLastFileId - 1;
1301 }
1302 else if (nLastSelectedItem == 0)
1303 nLastSelectedItem = currentpage->m_playlist->GetItemCount() - 1;
1304 else
1305 nLastSelectedItem -= 1;
1306
1307 if(nLastSelectedItem == currentpage->m_nLastFileId)
1308 return; //already playing... nothing to do
1309
1310 wxListItem listitem;
1311 listitem.SetId(nLastSelectedItem);
1312 listitem.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_DATA);
1313 currentpage->m_playlist->GetItem(listitem);
1314 listitem.SetMask(listitem.GetMask() | wxLIST_MASK_STATE);
1315 listitem.SetState(listitem.GetState() | wxLIST_STATE_SELECTED);
1316 currentpage->m_playlist->SetItem(listitem);
1317
1318 wxASSERT(listitem.GetData());
1319 DoPlayFile((*((wxString*) listitem.GetData())));
1320 }
1321
1322 // ----------------------------------------------------------------------------
1323 // wxMediaPlayerFrame::OnNext
1324 //
1325 // Tedious wxListCtrl stuff. Goes to next song in list, or if at the
1326 // end goes to the first in the list.
1327 // ----------------------------------------------------------------------------
1328 void wxMediaPlayerFrame::OnNext(wxCommandEvent& WXUNUSED(event))
1329 {
1330 wxMediaPlayerNotebookPage* currentpage =
1331 (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
1332
1333 if (currentpage->m_playlist->GetItemCount() == 0)
1334 return;
1335
1336 wxInt32 nLastSelectedItem = -1;
1337 while(true)
1338 {
1339 wxInt32 nSelectedItem = currentpage->m_playlist->GetNextItem(nLastSelectedItem,
1340 wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
1341 if (nSelectedItem == -1)
1342 break;
1343 nLastSelectedItem = nSelectedItem;
1344 currentpage->m_playlist->SetItemState(nSelectedItem, 0, wxLIST_STATE_SELECTED);
1345 }
1346
1347 if (nLastSelectedItem == -1)
1348 {
1349 if(currentpage->m_nLastFileId == currentpage->m_playlist->GetItemCount() - 1)
1350 nLastSelectedItem = 0;
1351 else
1352 nLastSelectedItem = currentpage->m_nLastFileId + 1;
1353 }
1354 else if (nLastSelectedItem == currentpage->m_playlist->GetItemCount() - 1)
1355 nLastSelectedItem = 0;
1356 else
1357 nLastSelectedItem += 1;
1358
1359 if(nLastSelectedItem == currentpage->m_nLastFileId)
1360 return; //already playing... nothing to do
1361
1362 wxListItem listitem;
1363 listitem.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_DATA);
1364 listitem.SetId(nLastSelectedItem);
1365 currentpage->m_playlist->GetItem(listitem);
1366 listitem.SetMask(listitem.GetMask() | wxLIST_MASK_STATE);
1367 listitem.SetState(listitem.GetState() | wxLIST_STATE_SELECTED);
1368 currentpage->m_playlist->SetItem(listitem);
1369
1370 wxASSERT(listitem.GetData());
1371 DoPlayFile((*((wxString*) listitem.GetData())));
1372 }
1373
1374
1375 // ----------------------------------------------------------------------------
1376 // wxMediaPlayerFrame::OnVolumeDown
1377 //
1378 // Lowers the volume of the media control by 5%
1379 // ----------------------------------------------------------------------------
1380 void wxMediaPlayerFrame::OnVolumeDown(wxCommandEvent& WXUNUSED(event))
1381 {
1382 wxMediaPlayerNotebookPage* currentpage =
1383 (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
1384
1385 double dVolume = currentpage->m_mediactrl->GetVolume();
1386 currentpage->m_mediactrl->SetVolume(dVolume < 0.05 ? 0.0 : dVolume - .05);
1387 }
1388
1389 // ----------------------------------------------------------------------------
1390 // wxMediaPlayerFrame::OnVolumeUp
1391 //
1392 // Increases the volume of the media control by 5%
1393 // ----------------------------------------------------------------------------
1394 void wxMediaPlayerFrame::OnVolumeUp(wxCommandEvent& WXUNUSED(event))
1395 {
1396 wxMediaPlayerNotebookPage* currentpage =
1397 (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
1398
1399 double dVolume = currentpage->m_mediactrl->GetVolume();
1400 currentpage->m_mediactrl->SetVolume(dVolume > 0.95 ? 1.0 : dVolume + .05);
1401 }
1402
1403 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1404 //
1405 // wxMediaPlayerTimer
1406 //
1407 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1408
1409 // ----------------------------------------------------------------------------
1410 // wxMediaPlayerTimer::Notify
1411 //
1412 // 1) Updates media information on the status bar
1413 // 2) Sets the max/min length of the slider and guage
1414 //
1415 // Note that the reason we continually do this and don't cache it is because
1416 // some backends such as GStreamer are dynamic change values all the time
1417 // and often don't have things like duration or video size available
1418 // until the media is actually being played
1419 // ----------------------------------------------------------------------------
1420 void wxMediaPlayerTimer::Notify()
1421 {
1422 wxMediaPlayerNotebookPage* currentpage =
1423 (wxMediaPlayerNotebookPage*) m_frame->m_notebook->GetCurrentPage();
1424 wxMediaCtrl* currentMediaCtrl = currentpage->m_mediactrl;
1425
1426 if(currentpage)
1427 {
1428 // Number of minutes/seconds total
1429 wxLongLong llLength = currentpage->m_mediactrl->Length();
1430 int nMinutes = (int) (llLength / 60000).GetValue();
1431 int nSeconds = (int) ((llLength % 60000)/1000).GetValue();
1432
1433 // Duration string (i.e. MM:SS)
1434 wxString sDuration;
1435 sDuration.Printf(wxT("%2i:%02i"), nMinutes, nSeconds);
1436
1437
1438 // Number of minutes/seconds total
1439 wxLongLong llTell = currentpage->m_mediactrl->Tell();
1440 nMinutes = (int) (llTell / 60000).GetValue();
1441 nSeconds = (int) ((llTell % 60000)/1000).GetValue();
1442
1443 // Position string (i.e. MM:SS)
1444 wxString sPosition;
1445 sPosition.Printf(wxT("%2i:%02i"), nMinutes, nSeconds);
1446
1447
1448 // Set the third item in the listctrl entry to the duration string
1449 if(currentpage->m_nLastFileId >= 0)
1450 currentpage->m_playlist->SetItem(
1451 currentpage->m_nLastFileId, 2, sDuration);
1452
1453 // Setup the slider and gauge min/max values
1454 currentpage->m_slider->SetRange(0, (int)(llLength / 1000).GetValue());
1455 currentpage->m_gauge->SetRange(100);
1456
1457
1458 // if the slider is not being dragged then update it with the song position
1459 if(currentpage->IsBeingDragged() == false)
1460 currentpage->m_slider->SetValue((long)(llTell / 1000).GetValue());
1461
1462
1463 // Update the gauge with the download progress
1464 wxLongLong llDownloadProgress =
1465 currentpage->m_mediactrl->GetDownloadProgress();
1466 wxLongLong llDownloadTotal =
1467 currentpage->m_mediactrl->GetDownloadTotal();
1468
1469 if(llDownloadTotal.GetValue() != 0)
1470 {
1471 currentpage->m_gauge->SetValue(
1472 (int) ((llDownloadProgress * 100) / llDownloadTotal).GetValue()
1473 );
1474 }
1475
1476 // GetBestSize holds the original video size
1477 wxSize videoSize = currentMediaCtrl->GetBestSize();
1478
1479 // Now the big part - set the status bar text to
1480 // hold various metadata about the media
1481 #if wxUSE_STATUSBAR
1482 m_frame->SetStatusText(wxString::Format(
1483 wxT("Size(x,y):%i,%i ")
1484 wxT("Position:%s/%s Speed:%1.1fx ")
1485 wxT("State:%s Loops:%i D/T:[%i]/[%i] V:%i%%"),
1486 videoSize.x,
1487 videoSize.y,
1488 sPosition.c_str(),
1489 sDuration.c_str(),
1490 currentMediaCtrl->GetPlaybackRate(),
1491 wxGetMediaStateText(currentpage->m_mediactrl->GetState()),
1492 currentpage->m_nLoops,
1493 (int)llDownloadProgress.GetValue(),
1494 (int)llDownloadTotal.GetValue(),
1495 (int)(currentpage->m_mediactrl->GetVolume() * 100)));
1496 #endif // wxUSE_STATUSBAR
1497 }
1498 }
1499
1500 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1501 //
1502 // wxMediaPlayerNotebookPage
1503 //
1504 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1505
1506 // ----------------------------------------------------------------------------
1507 // wxMediaPlayerNotebookPage Constructor
1508 //
1509 // Creates a media control and slider and adds it to this panel,
1510 // along with some sizers for positioning
1511 // ----------------------------------------------------------------------------
1512 wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentFrame,
1513 wxNotebook* theBook,
1514 const wxString& szBackend)
1515 : wxPanel(theBook, wxID_ANY),
1516 m_nLastFileId(-1),
1517 m_nLoops(0),
1518 m_bLoop(false),
1519 m_bIsBeingDragged(false),
1520 m_parentFrame(parentFrame)
1521 {
1522 //
1523 // Layout
1524 //
1525 // [wxMediaCtrl]
1526 // [playlist]
1527 // [5 control buttons]
1528 // [slider]
1529 // [gauge]
1530 //
1531
1532 //
1533 // Create and attach the sizer
1534 //
1535 wxFlexGridSizer* sizer = new wxFlexGridSizer(2, 1, 0, 0);
1536 this->SetSizer(sizer);
1537 this->SetAutoLayout(true);
1538 sizer->AddGrowableRow(0);
1539 sizer->AddGrowableCol(0);
1540
1541 //
1542 // Create our media control
1543 //
1544 m_mediactrl = new wxMediaCtrl();
1545
1546 // Make sure creation was successful
1547 bool bOK = m_mediactrl->Create(this, wxID_MEDIACTRL, wxEmptyString,
1548 wxDefaultPosition, wxDefaultSize, 0,
1549 //you could specify a macrod backend here like
1550 // wxMEDIABACKEND_WMP10);
1551 // wxT("wxPDFMediaBackend"));
1552 szBackend);
1553 //you could change the cursor here like
1554 // m_mediactrl->SetCursor(wxCURSOR_BLANK);
1555 //note that this may not effect it if SetPlayerControls
1556 //is set to something else than wxMEDIACTRLPLAYERCONTROLS_NONE
1557 wxASSERT_MSG(bOK, wxT("Could not create media control!"));
1558 wxUnusedVar(bOK);
1559
1560 sizer->Add(m_mediactrl, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 5);
1561
1562 //
1563 // Create the playlist/listctrl
1564 //
1565 m_playlist = new wxMediaPlayerListCtrl();
1566 m_playlist->Create(this, wxID_LISTCTRL, wxDefaultPosition,
1567 wxDefaultSize,
1568 wxLC_REPORT //wxLC_LIST
1569 | wxSUNKEN_BORDER);
1570
1571 // Set the background of our listctrl to white
1572 m_playlist->SetBackgroundColour(wxColour(255,255,255));
1573
1574 // The layout of the headers of the listctrl are like
1575 // | | File | Length
1576 //
1577 // Where Column one is a character representing the state the file is in:
1578 // * - not the current file
1579 // E - Error has occured
1580 // > - Currently Playing
1581 // [] - Stopped
1582 // || - Paused
1583 // (( - Volume Down 5%
1584 // )) - Volume Up 5%
1585 //
1586 // Column two is the name of the file
1587 //
1588 // Column three is the length in seconds of the file
1589 m_playlist->InsertColumn(0,_(""), wxLIST_FORMAT_CENTER, 20);
1590 m_playlist->InsertColumn(1,_("File"), wxLIST_FORMAT_LEFT, /*wxLIST_AUTOSIZE_USEHEADER*/305);
1591 m_playlist->InsertColumn(2,_("Length"), wxLIST_FORMAT_CENTER, 75);
1592
1593 #if wxUSE_DRAG_AND_DROP
1594 m_playlist->SetDropTarget(new wxPlayListDropTarget(*m_playlist));
1595 #endif
1596
1597 sizer->Add(m_playlist, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 5);
1598
1599 //
1600 // Create the control buttons
1601 // TODO/FIXME/HACK: This part about sizers is really a nice hack
1602 // and probably isn't proper
1603 //
1604 wxBoxSizer* horsizer1 = new wxBoxSizer(wxHORIZONTAL);
1605 wxBoxSizer* vertsizer = new wxBoxSizer(wxHORIZONTAL);
1606
1607 m_prevButton = new wxButton();
1608 m_playButton = new wxButton();
1609 m_stopButton = new wxButton();
1610 m_nextButton = new wxButton();
1611 m_vdButton = new wxButton();
1612 m_vuButton = new wxButton();
1613
1614 m_prevButton->Create(this, wxID_BUTTONPREV, wxT("|<"));
1615 m_playButton->Create(this, wxID_BUTTONPLAY, wxT(">"));
1616 m_stopButton->Create(this, wxID_BUTTONSTOP, wxT("[]"));
1617 m_nextButton->Create(this, wxID_BUTTONNEXT, wxT(">|"));
1618 m_vdButton->Create(this, wxID_BUTTONVD, wxT("(("));
1619 m_vuButton->Create(this, wxID_BUTTONVU, wxT("))"));
1620 vertsizer->Add(m_prevButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1621 vertsizer->Add(m_playButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1622 vertsizer->Add(m_stopButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1623 vertsizer->Add(m_nextButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1624 vertsizer->Add(m_vdButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1625 vertsizer->Add(m_vuButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1626 horsizer1->Add(vertsizer, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1627 sizer->Add(horsizer1, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
1628
1629
1630 //
1631 // Create our slider
1632 //
1633 m_slider = new wxSlider(this, wxID_SLIDER, 0, //init
1634 0, //start
1635 0, //end
1636 wxDefaultPosition, wxDefaultSize,
1637 wxSL_HORIZONTAL );
1638 sizer->Add(m_slider, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5);
1639
1640 //
1641 // Create the gauge
1642 //
1643 m_gauge = new wxGauge();
1644 m_gauge->Create(this, wxID_GAUGE, 0, wxDefaultPosition, wxDefaultSize,
1645 wxGA_HORIZONTAL | wxGA_SMOOTH);
1646 sizer->Add(m_gauge, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5);
1647
1648 //
1649 // Create the speed/volume sliders
1650 //
1651 wxBoxSizer* horsizer3 = new wxBoxSizer(wxHORIZONTAL);
1652
1653 m_volSlider = new wxSlider(this, wxID_VOLSLIDER, 100, // init
1654 0, // start
1655 100, // end
1656 wxDefaultPosition, wxSize(250,20),
1657 wxSL_HORIZONTAL );
1658 horsizer3->Add(m_volSlider, 1, wxALL, 5);
1659
1660 m_pbSlider = new wxSlider(this, wxID_PBSLIDER, 4, // init
1661 1, // start
1662 16, // end
1663 wxDefaultPosition, wxSize(250,20),
1664 wxSL_HORIZONTAL );
1665 horsizer3->Add(m_pbSlider, 1, wxALL, 5);
1666 sizer->Add(horsizer3, 1, wxCENTRE | wxALL, 5);
1667
1668 //
1669 // ListCtrl events
1670 //
1671 this->Connect( wxID_LISTCTRL, wxEVT_COMMAND_LIST_ITEM_ACTIVATED,
1672 wxListEventHandler(wxMediaPlayerFrame::OnChangeSong),
1673 (wxObject*)0, parentFrame);
1674
1675 //
1676 // Slider events
1677 //
1678 this->Connect(wxID_SLIDER, wxEVT_SCROLL_THUMBTRACK,
1679 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnBeginSeek));
1680 this->Connect(wxID_SLIDER, wxEVT_SCROLL_THUMBRELEASE,
1681 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnEndSeek));
1682 this->Connect(wxID_PBSLIDER, wxEVT_SCROLL_THUMBRELEASE,
1683 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnPBChange));
1684 this->Connect(wxID_VOLSLIDER, wxEVT_SCROLL_THUMBRELEASE,
1685 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnVolChange));
1686
1687 //
1688 // Media Control events
1689 //
1690 this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_PLAY,
1691 wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaPlay));
1692 this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_PAUSE,
1693 wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaPause));
1694 this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_STOP,
1695 wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaStop));
1696 this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_FINISHED,
1697 wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaFinished));
1698 this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_LOADED,
1699 wxMediaEventHandler(wxMediaPlayerFrame::OnMediaLoaded),
1700 (wxObject*)0, parentFrame);
1701
1702 //
1703 // Button events
1704 //
1705 this->Connect( wxID_BUTTONPREV, wxEVT_COMMAND_BUTTON_CLICKED,
1706 wxCommandEventHandler(wxMediaPlayerFrame::OnPrev),
1707 (wxObject*)0, parentFrame);
1708 this->Connect( wxID_BUTTONPLAY, wxEVT_COMMAND_BUTTON_CLICKED,
1709 wxCommandEventHandler(wxMediaPlayerFrame::OnPlay),
1710 (wxObject*)0, parentFrame);
1711 this->Connect( wxID_BUTTONSTOP, wxEVT_COMMAND_BUTTON_CLICKED,
1712 wxCommandEventHandler(wxMediaPlayerFrame::OnStop),
1713 (wxObject*)0, parentFrame);
1714 this->Connect( wxID_BUTTONNEXT, wxEVT_COMMAND_BUTTON_CLICKED,
1715 wxCommandEventHandler(wxMediaPlayerFrame::OnNext),
1716 (wxObject*)0, parentFrame);
1717 this->Connect( wxID_BUTTONVD, wxEVT_COMMAND_BUTTON_CLICKED,
1718 wxCommandEventHandler(wxMediaPlayerFrame::OnVolumeDown),
1719 (wxObject*)0, parentFrame);
1720 this->Connect( wxID_BUTTONVU, wxEVT_COMMAND_BUTTON_CLICKED,
1721 wxCommandEventHandler(wxMediaPlayerFrame::OnVolumeUp),
1722 (wxObject*)0, parentFrame);
1723 }
1724
1725 // ----------------------------------------------------------------------------
1726 // MyNotebook::OnBeginSeek
1727 //
1728 // Sets m_bIsBeingDragged to true to stop the timer from changing the position
1729 // of our slider
1730 // ----------------------------------------------------------------------------
1731 void wxMediaPlayerNotebookPage::OnBeginSeek(wxScrollEvent& WXUNUSED(event))
1732 {
1733 m_bIsBeingDragged = true;
1734 }
1735
1736 // ----------------------------------------------------------------------------
1737 // MyNotebook::OnEndSeek
1738 //
1739 // Called from file->seek.
1740 // Called when the user moves the slider -
1741 // seeks to a position within the media
1742 // then sets m_bIsBeingDragged to false to ok the timer to change the position
1743 // ----------------------------------------------------------------------------
1744 void wxMediaPlayerNotebookPage::OnEndSeek(wxScrollEvent& WXUNUSED(event))
1745 {
1746 if( m_mediactrl->Seek(
1747 m_slider->GetValue() * 1000
1748 ) == wxInvalidOffset )
1749 wxMessageBox(wxT("Couldn't seek in movie!"));
1750
1751 m_bIsBeingDragged = false;
1752 }
1753
1754 // ----------------------------------------------------------------------------
1755 // wxMediaPlayerNotebookPage::IsBeingDragged
1756 //
1757 // Returns true if the user is dragging the slider
1758 // ----------------------------------------------------------------------------
1759 bool wxMediaPlayerNotebookPage::IsBeingDragged()
1760 {
1761 return m_bIsBeingDragged;
1762 }
1763
1764 // ----------------------------------------------------------------------------
1765 // wxMediaPlayerNotebookPage::OnVolChange
1766 //
1767 // Called when the user is done dragging the volume-changing slider
1768 // ----------------------------------------------------------------------------
1769 void wxMediaPlayerNotebookPage::OnVolChange(wxScrollEvent& WXUNUSED(event))
1770 {
1771 if( m_mediactrl->SetVolume(
1772 m_volSlider->GetValue() / 100.0
1773 ) == false )
1774 wxMessageBox(wxT("Couldn't set volume!"));
1775
1776 }
1777
1778 // ----------------------------------------------------------------------------
1779 // wxMediaPlayerNotebookPage::OnPBChange
1780 //
1781 // Called when the user is done dragging the speed-changing slider
1782 // ----------------------------------------------------------------------------
1783 void wxMediaPlayerNotebookPage::OnPBChange(wxScrollEvent& WXUNUSED(event))
1784 {
1785 if( m_mediactrl->SetPlaybackRate(
1786 m_pbSlider->GetValue() * .25
1787 ) == false )
1788 wxMessageBox(wxT("Couldn't set playbackrate!"));
1789
1790 }
1791
1792 // ----------------------------------------------------------------------------
1793 // wxMediaPlayerNotebookPage::OnMediaPlay
1794 //
1795 // Called when the media plays.
1796 // ----------------------------------------------------------------------------
1797 void wxMediaPlayerNotebookPage::OnMediaPlay(wxMediaEvent& WXUNUSED(event))
1798 {
1799 m_playlist->SetItem(m_nLastFileId, 0, wxT(">"));
1800 }
1801
1802 // ----------------------------------------------------------------------------
1803 // wxMediaPlayerNotebookPage::OnMediaPause
1804 //
1805 // Called when the media is paused.
1806 // ----------------------------------------------------------------------------
1807 void wxMediaPlayerNotebookPage::OnMediaPause(wxMediaEvent& WXUNUSED(event))
1808 {
1809 m_playlist->SetItem(m_nLastFileId, 0, wxT("||"));
1810 }
1811
1812 // ----------------------------------------------------------------------------
1813 // wxMediaPlayerNotebookPage::OnMediaStop
1814 //
1815 // Called when the media stops.
1816 // ----------------------------------------------------------------------------
1817 void wxMediaPlayerNotebookPage::OnMediaStop(wxMediaEvent& WXUNUSED(event))
1818 {
1819 m_playlist->SetItem(m_nLastFileId, 0, wxT("[]"));
1820 }
1821
1822 // ----------------------------------------------------------------------------
1823 // wxMediaPlayerNotebookPage::OnMediaFinished
1824 //
1825 // Called when the media finishes playing.
1826 // Here we loop it if the user wants to (has been selected from file menu)
1827 // ----------------------------------------------------------------------------
1828 void wxMediaPlayerNotebookPage::OnMediaFinished(wxMediaEvent& WXUNUSED(event))
1829 {
1830 if(m_bLoop)
1831 {
1832 if ( !m_mediactrl->Play() )
1833 {
1834 wxMessageBox(wxT("Couldn't loop movie!"));
1835 m_playlist->SetItem(m_nLastFileId, 0, wxT("E"));
1836 }
1837 else
1838 ++m_nLoops;
1839 }
1840 else
1841 {
1842 m_playlist->SetItem(m_nLastFileId, 0, wxT("[]"));
1843 }
1844 }
1845
1846 //
1847 // End of MediaPlayer sample
1848 //