1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: mediaplayer.cpp
3 // Purpose: wxMediaCtrl sample
7 // Copyright: (c) Ryan Norton
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14 // This is a somewhat comprehensive example of how to use all the funtionality
15 // of the wxMediaCtrl class in wxWidgets.
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.
21 // You can select one of the menu options, or move the slider around
22 // to manipulate what is playing.
23 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
25 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
26 // Known bugs with wxMediaCtrl:
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 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34 // ============================================================================
36 // ============================================================================
38 // ----------------------------------------------------------------------------
39 // Pre-compiled header stuff
40 // ----------------------------------------------------------------------------
42 #include "wx/wxprec.h"
52 // ----------------------------------------------------------------------------
54 // ----------------------------------------------------------------------------
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"
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)
76 wxFORCE_LINK_MODULE(wxmediabackend_am
)
77 wxFORCE_LINK_MODULE(wxmediabackend_qt
)
78 wxFORCE_LINK_MODULE(wxmediabackend_wmp10
)
79 #endif // static wxMSW build
81 #ifndef wxHAS_IMAGES_IN_RESOURCES
82 #include "../sample.xpm"
85 // ----------------------------------------------------------------------------
86 // Bail out if the user doesn't want one of the
88 // ----------------------------------------------------------------------------
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!"
95 // ============================================================================
97 // ============================================================================
99 // ----------------------------------------------------------------------------
101 // ----------------------------------------------------------------------------
103 // IDs for the controls and the menu commands
108 wxID_OPENFILESAMEPAGE
,
109 wxID_OPENFILENEWPAGE
,
110 wxID_OPENURLSAMEPAGE
,
112 wxID_CLOSECURRENTPAGE
,
119 // wxID_STOP, [built-in to wxWidgets]
120 // wxID_ABOUT, [built-in to wxWidgets]
121 // wxID_EXIT, [built-in to wxWidgets]
138 // ----------------------------------------------------------------------------
140 // ----------------------------------------------------------------------------
142 class wxMediaPlayerApp
: public wxApp
146 virtual void MacOpenFiles(const wxArrayString
& fileNames
);
149 #if wxUSE_CMDLINE_PARSER
150 virtual void OnInitCmdLine(wxCmdLineParser
& parser
);
151 virtual bool OnCmdLineParsed(wxCmdLineParser
& parser
);
153 // Files specified on the command line, if any.
154 wxVector
<wxString
> m_params
;
155 #endif // wxUSE_CMDLINE_PARSER
157 virtual bool OnInit();
160 class wxMediaPlayerFrame
* m_frame
;
163 // ----------------------------------------------------------------------------
164 // wxMediaPlayerFrame
165 // ----------------------------------------------------------------------------
167 class wxMediaPlayerFrame
: public wxFrame
171 wxMediaPlayerFrame(const wxString
& title
);
172 ~wxMediaPlayerFrame();
174 // Menu event handlers
175 void OnQuit(wxCommandEvent
& event
);
176 void OnAbout(wxCommandEvent
& event
);
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
);
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
);
192 void OnLoop(wxCommandEvent
& event
);
193 void OnShowInterface(wxCommandEvent
& event
);
195 void OnSelectBackend(wxCommandEvent
& event
);
197 // Key event handlers
198 void OnKeyDown(wxKeyEvent
& event
);
200 // Quickie for playing from command line
201 void AddToPlayList(const wxString
& szString
);
203 // ListCtrl event handlers
204 void OnChangeSong(wxListEvent
& event
);
206 // Media event handlers
207 void OnMediaLoaded(wxMediaEvent
& event
);
209 // Close event handlers
210 void OnClose(wxCloseEvent
& event
);
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
);
219 class wxMediaPlayerTimer
* m_timer
; // Timer to write info to status bar
220 wxNotebook
* m_notebook
; // Notebook containing our pages
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
;
231 // ----------------------------------------------------------------------------
232 // wxMediaPlayerNotebookPage
233 // ----------------------------------------------------------------------------
235 class wxMediaPlayerNotebookPage
: public wxPanel
237 wxMediaPlayerNotebookPage(wxMediaPlayerFrame
* parentFrame
,
238 wxNotebook
* book
, const wxString
& be
= wxEmptyString
);
240 // Slider event handlers
241 void OnBeginSeek(wxScrollEvent
& event
);
242 void OnEndSeek(wxScrollEvent
& event
);
243 void OnPBChange(wxScrollEvent
& event
);
244 void OnVolChange(wxScrollEvent
& event
);
246 // Media event handlers
247 void OnMediaPlay(wxMediaEvent
& event
);
248 void OnMediaPause(wxMediaEvent
& event
);
249 void OnMediaStop(wxMediaEvent
& event
);
250 void OnMediaFinished(wxMediaEvent
& event
);
253 bool IsBeingDragged(); // accessor for m_bIsBeingDragged
255 // make wxMediaPlayerFrame able to access the private members
256 friend class wxMediaPlayerFrame
;
258 int m_nLastFileId
; // List ID of played file in listctrl
259 wxString m_szFile
; // Name of currently playing file/location
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
279 // ----------------------------------------------------------------------------
280 // wxMediaPlayerTimer
281 // ----------------------------------------------------------------------------
283 class wxMediaPlayerTimer
: public wxTimer
287 wxMediaPlayerTimer(wxMediaPlayerFrame
* frame
) {m_frame
= frame
;}
289 // Called each time the timer's timeout expires
292 wxMediaPlayerFrame
* m_frame
; // The wxMediaPlayerFrame
295 // ----------------------------------------------------------------------------
296 // wxMediaPlayerListCtrl
297 // ----------------------------------------------------------------------------
298 class wxMediaPlayerListCtrl
: public wxListCtrl
301 void AddToPlayList(const wxString
& szString
)
304 kNewItem
.SetAlign(wxLIST_FORMAT_LEFT
);
306 int nID
= this->GetItemCount();
308 kNewItem
.SetMask(wxLIST_MASK_DATA
);
309 kNewItem
.SetData(new wxString(szString
));
311 this->InsertItem(kNewItem
);
312 this->SetItem(nID
, 0, wxT("*"));
313 this->SetItem(nID
, 1, wxFileName(szString
).GetName());
317 kNewItem
.SetBackgroundColour(wxColour(192,192,192));
318 this->SetItem(kNewItem
);
322 void GetSelectedItem(wxListItem
& listitem
)
324 listitem
.SetMask(wxLIST_MASK_TEXT
| wxLIST_MASK_DATA
);
325 int nLast
= -1, nLastSelected
= -1;
326 while ((nLast
= this->GetNextItem(nLast
,
328 wxLIST_STATE_SELECTED
)) != -1)
330 listitem
.SetId(nLast
);
331 this->GetItem(listitem
);
332 if ((listitem
.GetState() & wxLIST_STATE_FOCUSED
) )
334 nLastSelected
= nLast
;
336 if (nLast
== -1 && nLastSelected
== -1)
338 listitem
.SetId(nLastSelected
== -1 ? nLast
: nLastSelected
);
339 this->GetItem(listitem
);
343 // ----------------------------------------------------------------------------
344 // wxPlayListDropTarget
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
353 wxPlayListDropTarget(wxMediaPlayerListCtrl
& list
) : m_list(list
) {}
354 ~wxPlayListDropTarget(){}
355 virtual bool OnDropFiles(wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
),
356 const wxArrayString
& files
)
358 for (size_t i
= 0; i
< files
.GetCount(); ++i
)
360 m_list
.AddToPlayList(files
[i
]);
364 wxMediaPlayerListCtrl
& m_list
;
368 // ============================================================================
372 // ============================================================================
374 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
378 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
380 // ----------------------------------------------------------------------------
381 // wxGetMediaStateText
383 // Converts a wxMediaCtrl state into something useful that we can display
385 // ----------------------------------------------------------------------------
386 const wxChar
* wxGetMediaStateText(int nState
)
390 case wxMEDIASTATE_PLAYING
:
391 return wxT("Playing");
392 case wxMEDIASTATE_STOPPED
:
393 return wxT("Stopped");
394 ///case wxMEDIASTATE_PAUSED:
396 return wxT("Paused");
400 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
404 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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.
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
)
419 // ----------------------------------------------------------------------------
420 // wxMediaPlayerApp command line parsing
421 // ----------------------------------------------------------------------------
423 #if wxUSE_CMDLINE_PARSER
425 void wxMediaPlayerApp::OnInitCmdLine(wxCmdLineParser
& parser
)
427 wxApp::OnInitCmdLine(parser
);
429 parser
.AddParam("input files",
430 wxCMD_LINE_VAL_STRING
,
431 wxCMD_LINE_PARAM_OPTIONAL
| wxCMD_LINE_PARAM_MULTIPLE
);
434 bool wxMediaPlayerApp::OnCmdLineParsed(wxCmdLineParser
& parser
)
436 if ( !wxApp::OnCmdLineParsed(parser
) )
439 for (size_t paramNr
=0; paramNr
< parser
.GetParamCount(); ++paramNr
)
440 m_params
.push_back(parser
.GetParam(paramNr
));
445 #endif // wxUSE_CMDLINE_PARSER
447 // ----------------------------------------------------------------------------
448 // wxMediaPlayerApp::OnInit
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()
457 if ( !wxApp::OnInit() )
460 // SetAppName() lets wxConfig and others know where to write
461 SetAppName(wxT("wxMediaPlayer"));
463 wxMediaPlayerFrame
*frame
=
464 new wxMediaPlayerFrame(wxT("MediaPlayer wxWidgets Sample"));
467 #if wxUSE_CMDLINE_PARSER
468 if ( !m_params
.empty() )
470 for ( size_t n
= 0; n
< m_params
.size(); n
++ )
471 frame
->AddToPlayList(m_params
[n
]);
473 wxCommandEvent
theEvent(wxEVT_MENU
, wxID_NEXT
);
474 frame
->AddPendingEvent(theEvent
);
476 #endif // wxUSE_CMDLINE_PARSER
483 void wxMediaPlayerApp::MacOpenFiles(const wxArrayString
& fileNames
)
485 // Called when a user drags files over our app
486 m_frame
->DoOpenFile(fileNames
[0], true /* new page */);
491 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
493 // wxMediaPlayerFrame
495 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
497 // ----------------------------------------------------------------------------
498 // wxMediaPlayerFrame Constructor
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 // ----------------------------------------------------------------------------
507 wxMediaPlayerFrame::wxMediaPlayerFrame(const wxString
& title
)
508 : wxFrame(NULL
, wxID_ANY
, title
, wxDefaultPosition
, wxSize(600,600))
510 SetIcon(wxICON(sample
));
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
;
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
,
535 wxT("Quit this program"));
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"));
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"));
550 debugMenu
->Append(wxID_SELECTBACKEND
,
551 wxT("&Select Backend...\tCtrl-D"),
552 wxT("Select a backend manually"));
554 helpMenu
->Append(wxID_ABOUT
,
556 wxT("Show about dialog"));
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"));
568 // Create our notebook - using wxNotebook is luckily pretty
569 // simple and self-explanatory in most cases
571 m_notebook
= new wxNotebook(this, wxID_NOTEBOOK
);
574 // Create our status bar
577 // create a status bar just for fun (by default with 1 pane only)
579 #endif // wxUSE_STATUSBAR
584 // There are two ways in wxWidgets to use events -
585 // Message Maps and Connections.
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.
591 // Then after your class declaration you put
592 // BEGIN_EVENT_TABLE(wxMediaPlayerFrame, wxFrame)
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.
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).
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.
611 // There are five parameters to wxEvtHandler::Connect -
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())
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).
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
629 // Or, you can use the new (2.5.5+) event handler
630 // conversion macros - for instance the above could
632 // wxCommandEventHandler(wxMediaPlayerFrame::MyHandler)
633 // pretty simple, eh?
635 // The fourth is an optional userdata param -
636 // this is of historical relevance only and is
637 // there only for backwards compatibility.
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.
653 this->Connect(wxID_EXIT
, wxEVT_MENU
,
654 wxCommandEventHandler(wxMediaPlayerFrame::OnQuit
));
656 this->Connect(wxID_ABOUT
, wxEVT_MENU
,
657 wxCommandEventHandler(wxMediaPlayerFrame::OnAbout
));
659 this->Connect(wxID_LOOP
, wxEVT_MENU
,
660 wxCommandEventHandler(wxMediaPlayerFrame::OnLoop
));
662 this->Connect(wxID_SHOWINTERFACE
, wxEVT_MENU
,
663 wxCommandEventHandler(wxMediaPlayerFrame::OnShowInterface
));
665 this->Connect(wxID_OPENFILENEWPAGE
, wxEVT_MENU
,
666 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileNewPage
));
668 this->Connect(wxID_OPENFILESAMEPAGE
, wxEVT_MENU
,
669 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileSamePage
));
671 this->Connect(wxID_OPENURLNEWPAGE
, wxEVT_MENU
,
672 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLNewPage
));
674 this->Connect(wxID_OPENURLSAMEPAGE
, wxEVT_MENU
,
675 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLSamePage
));
677 this->Connect(wxID_CLOSECURRENTPAGE
, wxEVT_MENU
,
678 wxCommandEventHandler(wxMediaPlayerFrame::OnCloseCurrentPage
));
680 this->Connect(wxID_PLAY
, wxEVT_MENU
,
681 wxCommandEventHandler(wxMediaPlayerFrame::OnPlay
));
683 this->Connect(wxID_STOP
, wxEVT_MENU
,
684 wxCommandEventHandler(wxMediaPlayerFrame::OnStop
));
686 this->Connect(wxID_NEXT
, wxEVT_MENU
,
687 wxCommandEventHandler(wxMediaPlayerFrame::OnNext
));
689 this->Connect(wxID_PREV
, wxEVT_MENU
,
690 wxCommandEventHandler(wxMediaPlayerFrame::OnPrev
));
692 this->Connect(wxID_SELECTBACKEND
, wxEVT_MENU
,
693 wxCommandEventHandler(wxMediaPlayerFrame::OnSelectBackend
));
698 wxTheApp
->Connect(wxID_ANY
, wxEVT_KEY_DOWN
,
699 wxKeyEventHandler(wxMediaPlayerFrame::OnKeyDown
),
705 this->Connect(wxID_ANY
, wxEVT_CLOSE_WINDOW
,
706 wxCloseEventHandler(wxMediaPlayerFrame::OnClose
));
713 // Create an initial notebook page so the user has something
714 // to work with without having to go file->open every time :).
716 wxMediaPlayerNotebookPage
* page
=
717 new wxMediaPlayerNotebookPage(this, m_notebook
);
718 m_notebook
->AddPage(page
,
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
727 #if wxUSE_CMDLINE_PARSER
728 if ( wxGetApp().m_params
.empty() )
729 #endif // wxUSE_CMDLINE_PARSER
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
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.
741 wxString key
, outstring
;
742 for(int i
= 0; ; ++i
)
746 if(!conf
.Read(key
, &outstring
))
748 page
->m_playlist
->AddToPlayList(outstring
);
753 // Create a timer to update our status bar
755 m_timer
= new wxMediaPlayerTimer(this);
759 // ----------------------------------------------------------------------------
760 // wxMediaPlayerFrame Destructor
762 // 1) Deletes child objects implicitly
763 // 2) Delete our timer explicitly
764 // ----------------------------------------------------------------------------
765 wxMediaPlayerFrame::~wxMediaPlayerFrame()
767 // Shut down our timer
771 // Here we save our info to the registry or whatever
772 // mechanism the OS uses.
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.
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.
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
787 // As an exercise to the reader, try modifying this so
788 // that it saves the data for each notebook page
790 wxMediaPlayerListCtrl
* playlist
=
791 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetPage(0))->m_playlist
;
796 for(int i
= 0; i
< playlist
->GetItemCount(); ++i
)
798 wxString
* pData
= (wxString
*) playlist
->GetItemData(i
);
801 conf
.Write(s
, *(pData
));
806 // ----------------------------------------------------------------------------
807 // wxMediaPlayerFrame::OnClose
808 // ----------------------------------------------------------------------------
809 void wxMediaPlayerFrame::OnClose(wxCloseEvent
& event
)
811 event
.Skip(); // really close the frame
814 // ----------------------------------------------------------------------------
815 // wxMediaPlayerFrame::AddToPlayList
816 // ----------------------------------------------------------------------------
817 void wxMediaPlayerFrame::AddToPlayList(const wxString
& szString
)
819 wxMediaPlayerNotebookPage
* currentpage
=
820 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
822 currentpage
->m_playlist
->AddToPlayList(szString
);
825 // ----------------------------------------------------------------------------
826 // wxMediaPlayerFrame::OnQuit
828 // Called from file->quit.
829 // Closes this application.
830 // ----------------------------------------------------------------------------
831 void wxMediaPlayerFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
833 // true is to force the frame to close
837 // ----------------------------------------------------------------------------
838 // wxMediaPlayerFrame::OnAbout
840 // Called from help->about.
841 // Gets some info about this application.
842 // ----------------------------------------------------------------------------
843 void wxMediaPlayerFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
846 msg
.Printf( wxT("This is a test of wxMediaCtrl.\n\n")
848 wxT("Instructions:\n")
850 wxT("The top slider shows the current the current position, ")
851 wxT("which you can change by dragging and releasing it.\n")
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")
857 wxT("The lower-left slider controls the volume and the lower-")
858 wxT("right slider controls the playback rate/speed of the ")
861 wxT("Currently using: %s"), wxVERSION_STRING
);
863 wxMessageBox(msg
, wxT("About wxMediaCtrl test"),
864 wxOK
| wxICON_INFORMATION
, this);
867 // ----------------------------------------------------------------------------
868 // wxMediaPlayerFrame::OnLoop
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
))
875 wxMediaPlayerNotebookPage
* currentpage
=
876 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
878 currentpage
->m_bLoop
= !currentpage
->m_bLoop
;
881 // ----------------------------------------------------------------------------
882 // wxMediaPlayerFrame::OnLoop
884 // Called from file->loop.
885 // Changes the state of whether we want to loop or not.
886 // ----------------------------------------------------------------------------
887 void wxMediaPlayerFrame::OnShowInterface(wxCommandEvent
& event
)
889 wxMediaPlayerNotebookPage
* currentpage
=
890 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
892 if( !currentpage
->m_mediactrl
->ShowPlayerControls(event
.IsChecked() ?
893 wxMEDIACTRLPLAYERCONTROLS_DEFAULT
:
894 wxMEDIACTRLPLAYERCONTROLS_NONE
) )
896 // error - uncheck and warn user
897 wxMenuItem
* pSIItem
= GetMenuBar()->FindItem(wxID_SHOWINTERFACE
);
899 pSIItem
->Check(!event
.IsChecked());
901 if(event
.IsChecked())
902 wxMessageBox(wxT("Could not show player controls"));
904 wxMessageBox(wxT("Could not hide player controls"));
908 // ----------------------------------------------------------------------------
909 // wxMediaPlayerFrame::OnOpenFileSamePage
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
))
919 // ----------------------------------------------------------------------------
920 // wxMediaPlayerFrame::OnOpenFileNewPage
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
))
930 // ----------------------------------------------------------------------------
931 // wxMediaPlayerFrame::OpenFile
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
)
938 wxFileDialog
fd(this);
940 if(fd
.ShowModal() == wxID_OK
)
942 DoOpenFile(fd
.GetPath(), bNewPage
);
946 // ----------------------------------------------------------------------------
947 // wxMediaPlayerFrame::DoOpenFile
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
)
957 new wxMediaPlayerNotebookPage(this, m_notebook
),
962 wxMediaPlayerNotebookPage
* currentpage
=
963 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
965 if(currentpage
->m_nLastFileId
!= -1)
966 currentpage
->m_playlist
->SetItemState(currentpage
->m_nLastFileId
,
967 0, wxLIST_STATE_SELECTED
);
969 wxListItem newlistitem
;
970 newlistitem
.SetAlign(wxLIST_FORMAT_LEFT
);
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
));
979 currentpage
->m_playlist
->InsertItem(newlistitem
);
980 currentpage
->m_playlist
->SetItem(nID
, 0, wxT("*"));
981 currentpage
->m_playlist
->SetItem(nID
, 1, wxFileName(path
).GetName());
985 newlistitem
.SetBackgroundColour(wxColour(192,192,192));
986 currentpage
->m_playlist
->SetItem(newlistitem
);
992 // ----------------------------------------------------------------------------
993 // wxMediaPlayerFrame::DoPlayFile
995 // Pauses the file if its the currently playing file,
996 // otherwise it plays the file
997 // ----------------------------------------------------------------------------
998 void wxMediaPlayerFrame::DoPlayFile(const wxString
& path
)
1000 wxMediaPlayerNotebookPage
* currentpage
=
1001 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1003 wxListItem listitem
;
1004 currentpage
->m_playlist
->GetSelectedItem(listitem
);
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)
1014 if(currentpage
->m_mediactrl
->GetState() == wxMEDIASTATE_PLAYING
)
1016 if( !currentpage
->m_mediactrl
->Pause() )
1017 wxMessageBox(wxT("Couldn't pause movie!"));
1021 if( !currentpage
->m_mediactrl
->Play() )
1022 wxMessageBox(wxT("Couldn't play movie!"));
1027 int nNewId
= listitem
.GetData() ? listitem
.GetId() :
1028 currentpage
->m_playlist
->GetItemCount()-1;
1029 m_notebook
->SetPageText(m_notebook
->GetSelection(),
1030 wxFileName(path
).GetName());
1032 if(currentpage
->m_nLastFileId
!= -1)
1033 currentpage
->m_playlist
->SetItem(
1034 currentpage
->m_nLastFileId
, 0, wxT("*"));
1036 wxURI
uripath(path
);
1037 if( uripath
.IsReference() )
1039 if( !currentpage
->m_mediactrl
->Load(path
) )
1041 wxMessageBox(wxT("Couldn't load file!"));
1042 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("E"));
1046 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("O"));
1051 if( !currentpage
->m_mediactrl
->Load(uripath
) )
1053 wxMessageBox(wxT("Couldn't load URL!"));
1054 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("E"));
1058 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("O"));
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
,
1071 // ----------------------------------------------------------------------------
1072 // wxMediaPlayerFrame::OnMediaLoaded
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
))
1079 wxMediaPlayerNotebookPage
* currentpage
=
1080 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1082 if( !currentpage
->m_mediactrl
->Play() )
1084 wxMessageBox(wxT("Couldn't play movie!"));
1085 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
, 0, wxT("E"));
1089 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
, 0, wxT(">"));
1095 // ----------------------------------------------------------------------------
1096 // wxMediaPlayerFrame::OnSelectBackend
1098 // Little debugging routine - enter the class name of a backend and it
1099 // will use that instead of letting wxMediaCtrl search the wxMediaBackend
1101 // ----------------------------------------------------------------------------
1102 void wxMediaPlayerFrame::OnSelectBackend(wxCommandEvent
& WXUNUSED(evt
))
1104 wxString sBackend
= wxGetTextFromUser(wxT("Enter backend to use"));
1106 if(sBackend
.empty() == false) // could have been cancelled by the user
1108 int sel
= m_notebook
->GetSelection();
1110 if (sel
!= wxNOT_FOUND
)
1112 m_notebook
->DeletePage(sel
);
1115 m_notebook
->AddPage(new wxMediaPlayerNotebookPage(this, m_notebook
,
1120 ((wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage())->m_szFile
,
1125 // ----------------------------------------------------------------------------
1126 // wxMediaPlayerFrame::OnOpenURLSamePage
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
))
1136 // ----------------------------------------------------------------------------
1137 // wxMediaPlayerFrame::OnOpenURLNewPage
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
))
1147 // ----------------------------------------------------------------------------
1148 // wxMediaPlayerFrame::OpenURL
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
)
1155 wxString sUrl
= wxGetTextFromUser(
1156 wxT("Enter the URL that has the movie to play")
1159 if(sUrl
.empty() == false) // could have been cancelled by user
1161 DoOpenFile(sUrl
, bNewPage
);
1165 // ----------------------------------------------------------------------------
1166 // wxMediaPlayerFrame::OnCloseCurrentPage
1168 // Called when the user wants to close the current notebook page
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
))
1176 if( m_notebook
->GetPageCount() > 1 )
1178 int sel
= m_notebook
->GetSelection();
1180 if (sel
!= wxNOT_FOUND
)
1182 m_notebook
->DeletePage(sel
);
1187 wxMessageBox(wxT("Cannot close main page"));
1191 // ----------------------------------------------------------------------------
1192 // wxMediaPlayerFrame::OnPlay
1194 // Called from file->play.
1195 // Resumes the media if it is paused or stopped.
1196 // ----------------------------------------------------------------------------
1197 void wxMediaPlayerFrame::OnPlay(wxCommandEvent
& WXUNUSED(event
))
1199 wxMediaPlayerNotebookPage
* currentpage
=
1200 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1202 wxListItem listitem
;
1203 currentpage
->m_playlist
->GetSelectedItem(listitem
);
1204 if ( !listitem
.GetData() )
1207 if ((nLast
= currentpage
->m_playlist
->GetNextItem(nLast
,
1209 wxLIST_STATE_DONTCARE
)) == -1)
1212 wxMessageBox(wxT("No items in playlist!"));
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())));
1227 wxASSERT(listitem
.GetData());
1228 DoPlayFile((*((wxString
*) listitem
.GetData())));
1232 // ----------------------------------------------------------------------------
1233 // wxMediaPlayerFrame::OnKeyDown
1235 // Deletes all selected files from the playlist if the backspace key is pressed
1236 // ----------------------------------------------------------------------------
1237 void wxMediaPlayerFrame::OnKeyDown(wxKeyEvent
& event
)
1239 if(event
.GetKeyCode() == WXK_BACK
/*DELETE*/)
1241 wxMediaPlayerNotebookPage
* currentpage
=
1242 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1243 // delete all selected items
1246 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(
1247 -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1248 if (nSelectedItem
== -1)
1251 wxListItem listitem
;
1252 listitem
.SetId(nSelectedItem
);
1253 currentpage
->m_playlist
->GetItem(listitem
);
1254 delete (wxString
*) listitem
.GetData();
1256 currentpage
->m_playlist
->DeleteItem(nSelectedItem
);
1260 // Could be wxGetTextFromUser or something else important
1261 if(event
.GetEventObject() != this)
1265 // ----------------------------------------------------------------------------
1266 // wxMediaPlayerFrame::OnStop
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
))
1276 wxMediaPlayerNotebookPage
* currentpage
=
1277 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1279 if( !currentpage
->m_mediactrl
->Stop() )
1280 wxMessageBox(wxT("Couldn't stop movie!"));
1282 currentpage
->m_playlist
->SetItem(
1283 currentpage
->m_nLastFileId
, 0, wxT("[]"));
1287 // ----------------------------------------------------------------------------
1288 // wxMediaPlayerFrame::OnChangeSong
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
))
1296 wxMediaPlayerNotebookPage
* currentpage
=
1297 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1299 wxListItem listitem
;
1300 currentpage
->m_playlist
->GetSelectedItem(listitem
);
1301 if(listitem
.GetData())
1302 DoPlayFile((*((wxString
*) listitem
.GetData())));
1304 wxMessageBox(wxT("No selected item!"));
1307 // ----------------------------------------------------------------------------
1308 // wxMediaPlayerFrame::OnPrev
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
))
1315 wxMediaPlayerNotebookPage
* currentpage
=
1316 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1318 if (currentpage
->m_playlist
->GetItemCount() == 0)
1321 wxInt32 nLastSelectedItem
= -1;
1324 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(nLastSelectedItem
,
1325 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1326 if (nSelectedItem
== -1)
1328 nLastSelectedItem
= nSelectedItem
;
1329 currentpage
->m_playlist
->SetItemState(nSelectedItem
, 0, wxLIST_STATE_SELECTED
);
1332 if (nLastSelectedItem
== -1)
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;
1338 nLastSelectedItem
= currentpage
->m_nLastFileId
- 1;
1340 else if (nLastSelectedItem
== 0)
1341 nLastSelectedItem
= currentpage
->m_playlist
->GetItemCount() - 1;
1343 nLastSelectedItem
-= 1;
1345 if(nLastSelectedItem
== currentpage
->m_nLastFileId
)
1346 return; // already playing... nothing to do
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
);
1356 wxASSERT(listitem
.GetData());
1357 DoPlayFile((*((wxString
*) listitem
.GetData())));
1360 // ----------------------------------------------------------------------------
1361 // wxMediaPlayerFrame::OnNext
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
))
1368 wxMediaPlayerNotebookPage
* currentpage
=
1369 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1371 if (currentpage
->m_playlist
->GetItemCount() == 0)
1374 wxInt32 nLastSelectedItem
= -1;
1377 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(nLastSelectedItem
,
1378 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1379 if (nSelectedItem
== -1)
1381 nLastSelectedItem
= nSelectedItem
;
1382 currentpage
->m_playlist
->SetItemState(nSelectedItem
, 0, wxLIST_STATE_SELECTED
);
1385 if (nLastSelectedItem
== -1)
1387 if(currentpage
->m_nLastFileId
== currentpage
->m_playlist
->GetItemCount() - 1)
1388 nLastSelectedItem
= 0;
1390 nLastSelectedItem
= currentpage
->m_nLastFileId
+ 1;
1392 else if (nLastSelectedItem
== currentpage
->m_playlist
->GetItemCount() - 1)
1393 nLastSelectedItem
= 0;
1395 nLastSelectedItem
+= 1;
1397 if(nLastSelectedItem
== currentpage
->m_nLastFileId
)
1398 return; // already playing... nothing to do
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
);
1408 wxASSERT(listitem
.GetData());
1409 DoPlayFile((*((wxString
*) listitem
.GetData())));
1413 // ----------------------------------------------------------------------------
1414 // wxMediaPlayerFrame::OnVolumeDown
1416 // Lowers the volume of the media control by 5%
1417 // ----------------------------------------------------------------------------
1418 void wxMediaPlayerFrame::OnVolumeDown(wxCommandEvent
& WXUNUSED(event
))
1420 wxMediaPlayerNotebookPage
* currentpage
=
1421 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1423 double dVolume
= currentpage
->m_mediactrl
->GetVolume();
1424 currentpage
->m_mediactrl
->SetVolume(dVolume
< 0.05 ? 0.0 : dVolume
- .05);
1427 // ----------------------------------------------------------------------------
1428 // wxMediaPlayerFrame::OnVolumeUp
1430 // Increases the volume of the media control by 5%
1431 // ----------------------------------------------------------------------------
1432 void wxMediaPlayerFrame::OnVolumeUp(wxCommandEvent
& WXUNUSED(event
))
1434 wxMediaPlayerNotebookPage
* currentpage
=
1435 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1437 double dVolume
= currentpage
->m_mediactrl
->GetVolume();
1438 currentpage
->m_mediactrl
->SetVolume(dVolume
> 0.95 ? 1.0 : dVolume
+ .05);
1441 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1443 // wxMediaPlayerTimer
1445 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1447 // ----------------------------------------------------------------------------
1448 // wxMediaPlayerTimer::Notify
1450 // 1) Updates media information on the status bar
1451 // 2) Sets the max/min length of the slider and guage
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()
1460 wxMediaPlayerNotebookPage
* currentpage
=
1461 (wxMediaPlayerNotebookPage
*) m_frame
->m_notebook
->GetCurrentPage();
1462 wxMediaCtrl
* currentMediaCtrl
= currentpage
->m_mediactrl
;
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();
1469 // Duration string (i.e. MM:SS)
1471 sDuration
.Printf(wxT("%2i:%02i"), nMinutes
, nSeconds
);
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();
1479 // Position string (i.e. MM:SS)
1481 sPosition
.Printf(wxT("%2i:%02i"), nMinutes
, nSeconds
);
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
);
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);
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());
1499 // Update the gauge with the download progress
1500 wxLongLong llDownloadProgress
=
1501 currentpage
->m_mediactrl
->GetDownloadProgress();
1502 wxLongLong llDownloadTotal
=
1503 currentpage
->m_mediactrl
->GetDownloadTotal();
1505 if(llDownloadTotal
.GetValue() != 0)
1507 currentpage
->m_gauge
->SetValue(
1508 (int) ((llDownloadProgress
* 100) / llDownloadTotal
).GetValue()
1512 // GetBestSize holds the original video size
1513 wxSize videoSize
= currentMediaCtrl
->GetBestSize();
1515 // Now the big part - set the status bar text to
1516 // hold various metadata about the media
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%%"),
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
1535 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1537 // wxMediaPlayerNotebookPage
1539 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1541 // ----------------------------------------------------------------------------
1542 // wxMediaPlayerNotebookPage Constructor
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
),
1554 m_bIsBeingDragged(false),
1555 m_parentFrame(parentFrame
)
1562 // [5 control buttons]
1568 // Create and attach a 2-column grid sizer
1570 wxFlexGridSizer
* sizer
= new wxFlexGridSizer(2);
1571 sizer
->AddGrowableCol(0);
1572 this->SetSizer(sizer
);
1575 // Create our media control
1577 m_mediactrl
= new wxMediaCtrl();
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"));
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!"));
1593 sizer
->Add(m_mediactrl
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1596 // Create the playlist/listctrl
1598 m_playlist
= new wxMediaPlayerListCtrl();
1599 m_playlist
->Create(this, wxID_LISTCTRL
, wxDefaultPosition
,
1601 wxLC_REPORT
// wxLC_LIST
1604 // Set the background of our listctrl to white
1605 m_playlist
->SetBackgroundColour(*wxWHITE
);
1607 // The layout of the headers of the listctrl are like
1608 // | | File | Length
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
1616 // (( - Volume Down 5%
1617 // )) - Volume Up 5%
1619 // Column two is the name of the file
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);
1626 #if wxUSE_DRAG_AND_DROP
1627 m_playlist
->SetDropTarget(new wxPlayListDropTarget(*m_playlist
));
1630 sizer
->Add(m_playlist
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1633 // Create the control buttons
1634 // TODO/FIXME/HACK: This part about sizers is really a nice hack
1635 // and probably isn't proper
1637 wxBoxSizer
* horsizer1
= new wxBoxSizer(wxHORIZONTAL
);
1638 wxBoxSizer
* vertsizer
= new wxBoxSizer(wxHORIZONTAL
);
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();
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");
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);
1671 // Create our slider
1673 m_slider
= new wxSlider(this, wxID_SLIDER
, 0, // init
1675 1, // end, dummy but must be greater than start
1676 wxDefaultPosition
, wxDefaultSize
,
1678 sizer
->Add(m_slider
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
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);
1690 // Create the speed/volume sliders
1692 wxBoxSizer
* horsizer3
= new wxBoxSizer(wxHORIZONTAL
);
1694 m_volSlider
= new wxSlider(this, wxID_VOLSLIDER
, 100, // init
1697 wxDefaultPosition
, wxSize(250,20),
1699 horsizer3
->Add(m_volSlider
, 1, wxALL
, 5);
1701 m_pbSlider
= new wxSlider(this, wxID_PBSLIDER
, 4, // init
1704 wxDefaultPosition
, wxSize(250,20),
1706 horsizer3
->Add(m_pbSlider
, 1, wxALL
, 5);
1707 sizer
->Add(horsizer3
, 1, wxCENTRE
| wxALL
, 5);
1709 // Now that we have all our rows make some of them growable
1710 sizer
->AddGrowableRow(0);
1715 this->Connect( wxID_LISTCTRL
, wxEVT_LIST_ITEM_ACTIVATED
,
1716 wxListEventHandler(wxMediaPlayerFrame::OnChangeSong
),
1717 (wxObject
*)0, parentFrame
);
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
));
1732 // Media Control events
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
);
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
);
1769 // ----------------------------------------------------------------------------
1770 // MyNotebook::OnBeginSeek
1772 // Sets m_bIsBeingDragged to true to stop the timer from changing the position
1774 // ----------------------------------------------------------------------------
1775 void wxMediaPlayerNotebookPage::OnBeginSeek(wxScrollEvent
& WXUNUSED(event
))
1777 m_bIsBeingDragged
= true;
1780 // ----------------------------------------------------------------------------
1781 // MyNotebook::OnEndSeek
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
))
1790 if( m_mediactrl
->Seek(
1791 m_slider
->GetValue() * 1000
1792 ) == wxInvalidOffset
)
1793 wxMessageBox(wxT("Couldn't seek in movie!"));
1795 m_bIsBeingDragged
= false;
1798 // ----------------------------------------------------------------------------
1799 // wxMediaPlayerNotebookPage::IsBeingDragged
1801 // Returns true if the user is dragging the slider
1802 // ----------------------------------------------------------------------------
1803 bool wxMediaPlayerNotebookPage::IsBeingDragged()
1805 return m_bIsBeingDragged
;
1808 // ----------------------------------------------------------------------------
1809 // wxMediaPlayerNotebookPage::OnVolChange
1811 // Called when the user is done dragging the volume-changing slider
1812 // ----------------------------------------------------------------------------
1813 void wxMediaPlayerNotebookPage::OnVolChange(wxScrollEvent
& WXUNUSED(event
))
1815 if( m_mediactrl
->SetVolume(
1816 m_volSlider
->GetValue() / 100.0
1818 wxMessageBox(wxT("Couldn't set volume!"));
1822 // ----------------------------------------------------------------------------
1823 // wxMediaPlayerNotebookPage::OnPBChange
1825 // Called when the user is done dragging the speed-changing slider
1826 // ----------------------------------------------------------------------------
1827 void wxMediaPlayerNotebookPage::OnPBChange(wxScrollEvent
& WXUNUSED(event
))
1829 if( m_mediactrl
->SetPlaybackRate(
1830 m_pbSlider
->GetValue() * .25
1832 wxMessageBox(wxT("Couldn't set playbackrate!"));
1836 // ----------------------------------------------------------------------------
1837 // wxMediaPlayerNotebookPage::OnMediaPlay
1839 // Called when the media plays.
1840 // ----------------------------------------------------------------------------
1841 void wxMediaPlayerNotebookPage::OnMediaPlay(wxMediaEvent
& WXUNUSED(event
))
1843 m_playlist
->SetItem(m_nLastFileId
, 0, wxT(">"));
1846 // ----------------------------------------------------------------------------
1847 // wxMediaPlayerNotebookPage::OnMediaPause
1849 // Called when the media is paused.
1850 // ----------------------------------------------------------------------------
1851 void wxMediaPlayerNotebookPage::OnMediaPause(wxMediaEvent
& WXUNUSED(event
))
1853 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("||"));
1856 // ----------------------------------------------------------------------------
1857 // wxMediaPlayerNotebookPage::OnMediaStop
1859 // Called when the media stops.
1860 // ----------------------------------------------------------------------------
1861 void wxMediaPlayerNotebookPage::OnMediaStop(wxMediaEvent
& WXUNUSED(event
))
1863 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("[]"));
1866 // ----------------------------------------------------------------------------
1867 // wxMediaPlayerNotebookPage::OnMediaFinished
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
))
1876 if ( !m_mediactrl
->Play() )
1878 wxMessageBox(wxT("Couldn't loop movie!"));
1879 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("E"));
1886 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("[]"));
1891 // End of MediaPlayer sample