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