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