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