1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: mediaplayer.cpp
3 // Purpose: wxMediaCtrl sample
8 // Copyright: (c) Ryan Norton
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15 // This is a somewhat comprehensive example of how to use all the funtionality
16 // of the wxMediaCtrl class in wxWidgets.
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.
22 // You can select one of the menu options, or move the slider around
23 // to manipulate what is playing.
24 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
26 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
27 // Known bugs with wxMediaCtrl:
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 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 // ============================================================================
37 // ============================================================================
39 // ----------------------------------------------------------------------------
40 // Pre-compiled header stuff
41 // ----------------------------------------------------------------------------
43 #include "wx/wxprec.h"
53 // ----------------------------------------------------------------------------
55 // ----------------------------------------------------------------------------
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"
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)
77 wxFORCE_LINK_MODULE(wxmediabackend_am
)
78 wxFORCE_LINK_MODULE(wxmediabackend_qt
)
79 wxFORCE_LINK_MODULE(wxmediabackend_wmp10
)
80 #endif // static wxMSW build
82 #ifndef wxHAS_IMAGES_IN_RESOURCES
83 #include "../sample.xpm"
86 // ----------------------------------------------------------------------------
87 // Bail out if the user doesn't want one of the
89 // ----------------------------------------------------------------------------
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!"
96 // ============================================================================
98 // ============================================================================
100 // ----------------------------------------------------------------------------
102 // ----------------------------------------------------------------------------
104 // IDs for the controls and the menu commands
109 wxID_OPENFILESAMEPAGE
,
110 wxID_OPENFILENEWPAGE
,
111 wxID_OPENURLSAMEPAGE
,
113 wxID_CLOSECURRENTPAGE
,
120 // wxID_STOP, [built-in to wxWidgets]
121 // wxID_ABOUT, [built-in to wxWidgets]
122 // wxID_EXIT, [built-in to wxWidgets]
139 // ----------------------------------------------------------------------------
141 // ----------------------------------------------------------------------------
143 class wxMediaPlayerApp
: public wxApp
147 virtual void MacOpenFiles(const wxArrayString
& fileNames
);
150 #if wxUSE_CMDLINE_PARSER
151 virtual void OnInitCmdLine(wxCmdLineParser
& parser
);
152 virtual bool OnCmdLineParsed(wxCmdLineParser
& parser
);
154 // Files specified on the command line, if any.
155 wxVector
<wxString
> m_params
;
156 #endif // wxUSE_CMDLINE_PARSER
158 virtual bool OnInit();
161 class wxMediaPlayerFrame
* m_frame
;
164 // ----------------------------------------------------------------------------
165 // wxMediaPlayerFrame
166 // ----------------------------------------------------------------------------
168 class wxMediaPlayerFrame
: public wxFrame
172 wxMediaPlayerFrame(const wxString
& title
);
173 ~wxMediaPlayerFrame();
175 // Menu event handlers
176 void OnQuit(wxCommandEvent
& event
);
177 void OnAbout(wxCommandEvent
& event
);
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
);
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
);
193 void OnLoop(wxCommandEvent
& event
);
194 void OnShowInterface(wxCommandEvent
& event
);
196 void OnSelectBackend(wxCommandEvent
& event
);
198 // Key event handlers
199 void OnKeyDown(wxKeyEvent
& event
);
201 // Quickie for playing from command line
202 void AddToPlayList(const wxString
& szString
);
204 // ListCtrl event handlers
205 void OnChangeSong(wxListEvent
& event
);
207 // Media event handlers
208 void OnMediaLoaded(wxMediaEvent
& event
);
210 // Close event handlers
211 void OnClose(wxCloseEvent
& event
);
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
);
220 class wxMediaPlayerTimer
* m_timer
; // Timer to write info to status bar
221 wxNotebook
* m_notebook
; // Notebook containing our pages
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
;
232 // ----------------------------------------------------------------------------
233 // wxMediaPlayerNotebookPage
234 // ----------------------------------------------------------------------------
236 class wxMediaPlayerNotebookPage
: public wxPanel
238 wxMediaPlayerNotebookPage(wxMediaPlayerFrame
* parentFrame
,
239 wxNotebook
* book
, const wxString
& be
= wxEmptyString
);
241 // Slider event handlers
242 void OnBeginSeek(wxScrollEvent
& event
);
243 void OnEndSeek(wxScrollEvent
& event
);
244 void OnPBChange(wxScrollEvent
& event
);
245 void OnVolChange(wxScrollEvent
& event
);
247 // Media event handlers
248 void OnMediaPlay(wxMediaEvent
& event
);
249 void OnMediaPause(wxMediaEvent
& event
);
250 void OnMediaStop(wxMediaEvent
& event
);
251 void OnMediaFinished(wxMediaEvent
& event
);
254 bool IsBeingDragged(); // accessor for m_bIsBeingDragged
256 // make wxMediaPlayerFrame able to access the private members
257 friend class wxMediaPlayerFrame
;
259 int m_nLastFileId
; // List ID of played file in listctrl
260 wxString m_szFile
; // Name of currently playing file/location
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
280 // ----------------------------------------------------------------------------
281 // wxMediaPlayerTimer
282 // ----------------------------------------------------------------------------
284 class wxMediaPlayerTimer
: public wxTimer
288 wxMediaPlayerTimer(wxMediaPlayerFrame
* frame
) {m_frame
= frame
;}
290 // Called each time the timer's timeout expires
293 wxMediaPlayerFrame
* m_frame
; // The wxMediaPlayerFrame
296 // ----------------------------------------------------------------------------
297 // wxMediaPlayerListCtrl
298 // ----------------------------------------------------------------------------
299 class wxMediaPlayerListCtrl
: public wxListCtrl
302 void AddToPlayList(const wxString
& szString
)
305 kNewItem
.SetAlign(wxLIST_FORMAT_LEFT
);
307 int nID
= this->GetItemCount();
309 kNewItem
.SetMask(wxLIST_MASK_DATA
);
310 kNewItem
.SetData(new wxString(szString
));
312 this->InsertItem(kNewItem
);
313 this->SetItem(nID
, 0, wxT("*"));
314 this->SetItem(nID
, 1, wxFileName(szString
).GetName());
318 kNewItem
.SetBackgroundColour(wxColour(192,192,192));
319 this->SetItem(kNewItem
);
323 void GetSelectedItem(wxListItem
& listitem
)
325 listitem
.SetMask(wxLIST_MASK_TEXT
| wxLIST_MASK_DATA
);
326 int nLast
= -1, nLastSelected
= -1;
327 while ((nLast
= this->GetNextItem(nLast
,
329 wxLIST_STATE_SELECTED
)) != -1)
331 listitem
.SetId(nLast
);
332 this->GetItem(listitem
);
333 if ((listitem
.GetState() & wxLIST_STATE_FOCUSED
) )
335 nLastSelected
= nLast
;
337 if (nLast
== -1 && nLastSelected
== -1)
339 listitem
.SetId(nLastSelected
== -1 ? nLast
: nLastSelected
);
340 this->GetItem(listitem
);
344 // ----------------------------------------------------------------------------
345 // wxPlayListDropTarget
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
354 wxPlayListDropTarget(wxMediaPlayerListCtrl
& list
) : m_list(list
) {}
355 ~wxPlayListDropTarget(){}
356 virtual bool OnDropFiles(wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
),
357 const wxArrayString
& files
)
359 for (size_t i
= 0; i
< files
.GetCount(); ++i
)
361 m_list
.AddToPlayList(files
[i
]);
365 wxMediaPlayerListCtrl
& m_list
;
369 // ============================================================================
373 // ============================================================================
375 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
379 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
381 // ----------------------------------------------------------------------------
382 // wxGetMediaStateText
384 // Converts a wxMediaCtrl state into something useful that we can display
386 // ----------------------------------------------------------------------------
387 const wxChar
* wxGetMediaStateText(int nState
)
391 case wxMEDIASTATE_PLAYING
:
392 return wxT("Playing");
393 case wxMEDIASTATE_STOPPED
:
394 return wxT("Stopped");
395 ///case wxMEDIASTATE_PAUSED:
397 return wxT("Paused");
401 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
405 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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.
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
)
420 // ----------------------------------------------------------------------------
421 // wxMediaPlayerApp command line parsing
422 // ----------------------------------------------------------------------------
424 #if wxUSE_CMDLINE_PARSER
426 void wxMediaPlayerApp::OnInitCmdLine(wxCmdLineParser
& parser
)
428 wxApp::OnInitCmdLine(parser
);
430 parser
.AddParam("input files",
431 wxCMD_LINE_VAL_STRING
,
432 wxCMD_LINE_PARAM_OPTIONAL
| wxCMD_LINE_PARAM_MULTIPLE
);
435 bool wxMediaPlayerApp::OnCmdLineParsed(wxCmdLineParser
& parser
)
437 if ( !wxApp::OnCmdLineParsed(parser
) )
440 for (size_t paramNr
=0; paramNr
< parser
.GetParamCount(); ++paramNr
)
441 m_params
.push_back(parser
.GetParam(paramNr
));
446 #endif // wxUSE_CMDLINE_PARSER
448 // ----------------------------------------------------------------------------
449 // wxMediaPlayerApp::OnInit
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()
458 if ( !wxApp::OnInit() )
461 // SetAppName() lets wxConfig and others know where to write
462 SetAppName(wxT("wxMediaPlayer"));
464 wxMediaPlayerFrame
*frame
=
465 new wxMediaPlayerFrame(wxT("MediaPlayer wxWidgets Sample"));
468 #if wxUSE_CMDLINE_PARSER
469 if ( !m_params
.empty() )
471 for ( size_t n
= 0; n
< m_params
.size(); n
++ )
472 frame
->AddToPlayList(m_params
[n
]);
474 wxCommandEvent
theEvent(wxEVT_MENU
, wxID_NEXT
);
475 frame
->AddPendingEvent(theEvent
);
477 #endif // wxUSE_CMDLINE_PARSER
484 void wxMediaPlayerApp::MacOpenFiles(const wxArrayString
& fileNames
)
486 // Called when a user drags files over our app
487 m_frame
->DoOpenFile(fileNames
[0], true /* new page */);
492 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
494 // wxMediaPlayerFrame
496 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
498 // ----------------------------------------------------------------------------
499 // wxMediaPlayerFrame Constructor
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 // ----------------------------------------------------------------------------
508 wxMediaPlayerFrame::wxMediaPlayerFrame(const wxString
& title
)
509 : wxFrame(NULL
, wxID_ANY
, title
, wxDefaultPosition
, wxSize(600,600))
511 SetIcon(wxICON(sample
));
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
;
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
,
536 wxT("Quit this program"));
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"));
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"));
551 debugMenu
->Append(wxID_SELECTBACKEND
,
552 wxT("&Select Backend...\tCtrl-D"),
553 wxT("Select a backend manually"));
555 helpMenu
->Append(wxID_ABOUT
,
557 wxT("Show about dialog"));
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"));
569 // Create our notebook - using wxNotebook is luckily pretty
570 // simple and self-explanatory in most cases
572 m_notebook
= new wxNotebook(this, wxID_NOTEBOOK
);
575 // Create our status bar
578 // create a status bar just for fun (by default with 1 pane only)
580 #endif // wxUSE_STATUSBAR
585 // There are two ways in wxWidgets to use events -
586 // Message Maps and Connections.
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.
592 // Then after your class declaration you put
593 // BEGIN_EVENT_TABLE(wxMediaPlayerFrame, wxFrame)
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.
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).
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.
612 // There are five parameters to wxEvtHandler::Connect -
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())
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).
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
630 // Or, you can use the new (2.5.5+) event handler
631 // conversion macros - for instance the above could
633 // wxCommandEventHandler(wxMediaPlayerFrame::MyHandler)
634 // pretty simple, eh?
636 // The fourth is an optional userdata param -
637 // this is of historical relevance only and is
638 // there only for backwards compatibility.
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.
654 this->Connect(wxID_EXIT
, wxEVT_MENU
,
655 wxCommandEventHandler(wxMediaPlayerFrame::OnQuit
));
657 this->Connect(wxID_ABOUT
, wxEVT_MENU
,
658 wxCommandEventHandler(wxMediaPlayerFrame::OnAbout
));
660 this->Connect(wxID_LOOP
, wxEVT_MENU
,
661 wxCommandEventHandler(wxMediaPlayerFrame::OnLoop
));
663 this->Connect(wxID_SHOWINTERFACE
, wxEVT_MENU
,
664 wxCommandEventHandler(wxMediaPlayerFrame::OnShowInterface
));
666 this->Connect(wxID_OPENFILENEWPAGE
, wxEVT_MENU
,
667 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileNewPage
));
669 this->Connect(wxID_OPENFILESAMEPAGE
, wxEVT_MENU
,
670 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileSamePage
));
672 this->Connect(wxID_OPENURLNEWPAGE
, wxEVT_MENU
,
673 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLNewPage
));
675 this->Connect(wxID_OPENURLSAMEPAGE
, wxEVT_MENU
,
676 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLSamePage
));
678 this->Connect(wxID_CLOSECURRENTPAGE
, wxEVT_MENU
,
679 wxCommandEventHandler(wxMediaPlayerFrame::OnCloseCurrentPage
));
681 this->Connect(wxID_PLAY
, wxEVT_MENU
,
682 wxCommandEventHandler(wxMediaPlayerFrame::OnPlay
));
684 this->Connect(wxID_STOP
, wxEVT_MENU
,
685 wxCommandEventHandler(wxMediaPlayerFrame::OnStop
));
687 this->Connect(wxID_NEXT
, wxEVT_MENU
,
688 wxCommandEventHandler(wxMediaPlayerFrame::OnNext
));
690 this->Connect(wxID_PREV
, wxEVT_MENU
,
691 wxCommandEventHandler(wxMediaPlayerFrame::OnPrev
));
693 this->Connect(wxID_SELECTBACKEND
, wxEVT_MENU
,
694 wxCommandEventHandler(wxMediaPlayerFrame::OnSelectBackend
));
699 wxTheApp
->Connect(wxID_ANY
, wxEVT_KEY_DOWN
,
700 wxKeyEventHandler(wxMediaPlayerFrame::OnKeyDown
),
706 this->Connect(wxID_ANY
, wxEVT_CLOSE_WINDOW
,
707 wxCloseEventHandler(wxMediaPlayerFrame::OnClose
));
714 // Create an initial notebook page so the user has something
715 // to work with without having to go file->open every time :).
717 wxMediaPlayerNotebookPage
* page
=
718 new wxMediaPlayerNotebookPage(this, m_notebook
);
719 m_notebook
->AddPage(page
,
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
728 #if wxUSE_CMDLINE_PARSER
729 if ( wxGetApp().m_params
.empty() )
730 #endif // wxUSE_CMDLINE_PARSER
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
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.
742 wxString key
, outstring
;
743 for(int i
= 0; ; ++i
)
747 if(!conf
.Read(key
, &outstring
))
749 page
->m_playlist
->AddToPlayList(outstring
);
754 // Create a timer to update our status bar
756 m_timer
= new wxMediaPlayerTimer(this);
760 // ----------------------------------------------------------------------------
761 // wxMediaPlayerFrame Destructor
763 // 1) Deletes child objects implicitly
764 // 2) Delete our timer explicitly
765 // ----------------------------------------------------------------------------
766 wxMediaPlayerFrame::~wxMediaPlayerFrame()
768 // Shut down our timer
772 // Here we save our info to the registry or whatever
773 // mechanism the OS uses.
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.
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.
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
788 // As an exercise to the reader, try modifying this so
789 // that it saves the data for each notebook page
791 wxMediaPlayerListCtrl
* playlist
=
792 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetPage(0))->m_playlist
;
797 for(int i
= 0; i
< playlist
->GetItemCount(); ++i
)
799 wxString
* pData
= (wxString
*) playlist
->GetItemData(i
);
802 conf
.Write(s
, *(pData
));
807 // ----------------------------------------------------------------------------
808 // wxMediaPlayerFrame::OnClose
809 // ----------------------------------------------------------------------------
810 void wxMediaPlayerFrame::OnClose(wxCloseEvent
& event
)
812 event
.Skip(); // really close the frame
815 // ----------------------------------------------------------------------------
816 // wxMediaPlayerFrame::AddToPlayList
817 // ----------------------------------------------------------------------------
818 void wxMediaPlayerFrame::AddToPlayList(const wxString
& szString
)
820 wxMediaPlayerNotebookPage
* currentpage
=
821 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
823 currentpage
->m_playlist
->AddToPlayList(szString
);
826 // ----------------------------------------------------------------------------
827 // wxMediaPlayerFrame::OnQuit
829 // Called from file->quit.
830 // Closes this application.
831 // ----------------------------------------------------------------------------
832 void wxMediaPlayerFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
834 // true is to force the frame to close
838 // ----------------------------------------------------------------------------
839 // wxMediaPlayerFrame::OnAbout
841 // Called from help->about.
842 // Gets some info about this application.
843 // ----------------------------------------------------------------------------
844 void wxMediaPlayerFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
847 msg
.Printf( wxT("This is a test of wxMediaCtrl.\n\n")
849 wxT("Instructions:\n")
851 wxT("The top slider shows the current the current position, ")
852 wxT("which you can change by dragging and releasing it.\n")
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")
858 wxT("The lower-left slider controls the volume and the lower-")
859 wxT("right slider controls the playback rate/speed of the ")
862 wxT("Currently using: %s"), wxVERSION_STRING
);
864 wxMessageBox(msg
, wxT("About wxMediaCtrl test"),
865 wxOK
| wxICON_INFORMATION
, this);
868 // ----------------------------------------------------------------------------
869 // wxMediaPlayerFrame::OnLoop
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
))
876 wxMediaPlayerNotebookPage
* currentpage
=
877 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
879 currentpage
->m_bLoop
= !currentpage
->m_bLoop
;
882 // ----------------------------------------------------------------------------
883 // wxMediaPlayerFrame::OnLoop
885 // Called from file->loop.
886 // Changes the state of whether we want to loop or not.
887 // ----------------------------------------------------------------------------
888 void wxMediaPlayerFrame::OnShowInterface(wxCommandEvent
& event
)
890 wxMediaPlayerNotebookPage
* currentpage
=
891 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
893 if( !currentpage
->m_mediactrl
->ShowPlayerControls(event
.IsChecked() ?
894 wxMEDIACTRLPLAYERCONTROLS_DEFAULT
:
895 wxMEDIACTRLPLAYERCONTROLS_NONE
) )
897 // error - uncheck and warn user
898 wxMenuItem
* pSIItem
= GetMenuBar()->FindItem(wxID_SHOWINTERFACE
);
900 pSIItem
->Check(!event
.IsChecked());
902 if(event
.IsChecked())
903 wxMessageBox(wxT("Could not show player controls"));
905 wxMessageBox(wxT("Could not hide player controls"));
909 // ----------------------------------------------------------------------------
910 // wxMediaPlayerFrame::OnOpenFileSamePage
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
))
920 // ----------------------------------------------------------------------------
921 // wxMediaPlayerFrame::OnOpenFileNewPage
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
))
931 // ----------------------------------------------------------------------------
932 // wxMediaPlayerFrame::OpenFile
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
)
939 wxFileDialog
fd(this);
941 if(fd
.ShowModal() == wxID_OK
)
943 DoOpenFile(fd
.GetPath(), bNewPage
);
947 // ----------------------------------------------------------------------------
948 // wxMediaPlayerFrame::DoOpenFile
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
)
958 new wxMediaPlayerNotebookPage(this, m_notebook
),
963 wxMediaPlayerNotebookPage
* currentpage
=
964 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
966 if(currentpage
->m_nLastFileId
!= -1)
967 currentpage
->m_playlist
->SetItemState(currentpage
->m_nLastFileId
,
968 0, wxLIST_STATE_SELECTED
);
970 wxListItem newlistitem
;
971 newlistitem
.SetAlign(wxLIST_FORMAT_LEFT
);
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
));
980 currentpage
->m_playlist
->InsertItem(newlistitem
);
981 currentpage
->m_playlist
->SetItem(nID
, 0, wxT("*"));
982 currentpage
->m_playlist
->SetItem(nID
, 1, wxFileName(path
).GetName());
986 newlistitem
.SetBackgroundColour(wxColour(192,192,192));
987 currentpage
->m_playlist
->SetItem(newlistitem
);
993 // ----------------------------------------------------------------------------
994 // wxMediaPlayerFrame::DoPlayFile
996 // Pauses the file if its the currently playing file,
997 // otherwise it plays the file
998 // ----------------------------------------------------------------------------
999 void wxMediaPlayerFrame::DoPlayFile(const wxString
& path
)
1001 wxMediaPlayerNotebookPage
* currentpage
=
1002 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1004 wxListItem listitem
;
1005 currentpage
->m_playlist
->GetSelectedItem(listitem
);
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)
1015 if(currentpage
->m_mediactrl
->GetState() == wxMEDIASTATE_PLAYING
)
1017 if( !currentpage
->m_mediactrl
->Pause() )
1018 wxMessageBox(wxT("Couldn't pause movie!"));
1022 if( !currentpage
->m_mediactrl
->Play() )
1023 wxMessageBox(wxT("Couldn't play movie!"));
1028 int nNewId
= listitem
.GetData() ? listitem
.GetId() :
1029 currentpage
->m_playlist
->GetItemCount()-1;
1030 m_notebook
->SetPageText(m_notebook
->GetSelection(),
1031 wxFileName(path
).GetName());
1033 if(currentpage
->m_nLastFileId
!= -1)
1034 currentpage
->m_playlist
->SetItem(
1035 currentpage
->m_nLastFileId
, 0, wxT("*"));
1037 wxURI
uripath(path
);
1038 if( uripath
.IsReference() )
1040 if( !currentpage
->m_mediactrl
->Load(path
) )
1042 wxMessageBox(wxT("Couldn't load file!"));
1043 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("E"));
1047 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("O"));
1052 if( !currentpage
->m_mediactrl
->Load(uripath
) )
1054 wxMessageBox(wxT("Couldn't load URL!"));
1055 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("E"));
1059 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("O"));
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
,
1072 // ----------------------------------------------------------------------------
1073 // wxMediaPlayerFrame::OnMediaLoaded
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
))
1080 wxMediaPlayerNotebookPage
* currentpage
=
1081 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1083 if( !currentpage
->m_mediactrl
->Play() )
1085 wxMessageBox(wxT("Couldn't play movie!"));
1086 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
, 0, wxT("E"));
1090 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
, 0, wxT(">"));
1096 // ----------------------------------------------------------------------------
1097 // wxMediaPlayerFrame::OnSelectBackend
1099 // Little debugging routine - enter the class name of a backend and it
1100 // will use that instead of letting wxMediaCtrl search the wxMediaBackend
1102 // ----------------------------------------------------------------------------
1103 void wxMediaPlayerFrame::OnSelectBackend(wxCommandEvent
& WXUNUSED(evt
))
1105 wxString sBackend
= wxGetTextFromUser(wxT("Enter backend to use"));
1107 if(sBackend
.empty() == false) // could have been cancelled by the user
1109 int sel
= m_notebook
->GetSelection();
1111 if (sel
!= wxNOT_FOUND
)
1113 m_notebook
->DeletePage(sel
);
1116 m_notebook
->AddPage(new wxMediaPlayerNotebookPage(this, m_notebook
,
1121 ((wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage())->m_szFile
,
1126 // ----------------------------------------------------------------------------
1127 // wxMediaPlayerFrame::OnOpenURLSamePage
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
))
1137 // ----------------------------------------------------------------------------
1138 // wxMediaPlayerFrame::OnOpenURLNewPage
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
))
1148 // ----------------------------------------------------------------------------
1149 // wxMediaPlayerFrame::OpenURL
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
)
1156 wxString sUrl
= wxGetTextFromUser(
1157 wxT("Enter the URL that has the movie to play")
1160 if(sUrl
.empty() == false) // could have been cancelled by user
1162 DoOpenFile(sUrl
, bNewPage
);
1166 // ----------------------------------------------------------------------------
1167 // wxMediaPlayerFrame::OnCloseCurrentPage
1169 // Called when the user wants to close the current notebook page
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
))
1177 if( m_notebook
->GetPageCount() > 1 )
1179 int sel
= m_notebook
->GetSelection();
1181 if (sel
!= wxNOT_FOUND
)
1183 m_notebook
->DeletePage(sel
);
1188 wxMessageBox(wxT("Cannot close main page"));
1192 // ----------------------------------------------------------------------------
1193 // wxMediaPlayerFrame::OnPlay
1195 // Called from file->play.
1196 // Resumes the media if it is paused or stopped.
1197 // ----------------------------------------------------------------------------
1198 void wxMediaPlayerFrame::OnPlay(wxCommandEvent
& WXUNUSED(event
))
1200 wxMediaPlayerNotebookPage
* currentpage
=
1201 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1203 wxListItem listitem
;
1204 currentpage
->m_playlist
->GetSelectedItem(listitem
);
1205 if ( !listitem
.GetData() )
1208 if ((nLast
= currentpage
->m_playlist
->GetNextItem(nLast
,
1210 wxLIST_STATE_DONTCARE
)) == -1)
1213 wxMessageBox(wxT("No items in playlist!"));
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())));
1228 wxASSERT(listitem
.GetData());
1229 DoPlayFile((*((wxString
*) listitem
.GetData())));
1233 // ----------------------------------------------------------------------------
1234 // wxMediaPlayerFrame::OnKeyDown
1236 // Deletes all selected files from the playlist if the backspace key is pressed
1237 // ----------------------------------------------------------------------------
1238 void wxMediaPlayerFrame::OnKeyDown(wxKeyEvent
& event
)
1240 if(event
.GetKeyCode() == WXK_BACK
/*DELETE*/)
1242 wxMediaPlayerNotebookPage
* currentpage
=
1243 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1244 // delete all selected items
1247 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(
1248 -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1249 if (nSelectedItem
== -1)
1252 wxListItem listitem
;
1253 listitem
.SetId(nSelectedItem
);
1254 currentpage
->m_playlist
->GetItem(listitem
);
1255 delete (wxString
*) listitem
.GetData();
1257 currentpage
->m_playlist
->DeleteItem(nSelectedItem
);
1261 // Could be wxGetTextFromUser or something else important
1262 if(event
.GetEventObject() != this)
1266 // ----------------------------------------------------------------------------
1267 // wxMediaPlayerFrame::OnStop
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
))
1277 wxMediaPlayerNotebookPage
* currentpage
=
1278 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1280 if( !currentpage
->m_mediactrl
->Stop() )
1281 wxMessageBox(wxT("Couldn't stop movie!"));
1283 currentpage
->m_playlist
->SetItem(
1284 currentpage
->m_nLastFileId
, 0, wxT("[]"));
1288 // ----------------------------------------------------------------------------
1289 // wxMediaPlayerFrame::OnChangeSong
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
))
1297 wxMediaPlayerNotebookPage
* currentpage
=
1298 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1300 wxListItem listitem
;
1301 currentpage
->m_playlist
->GetSelectedItem(listitem
);
1302 if(listitem
.GetData())
1303 DoPlayFile((*((wxString
*) listitem
.GetData())));
1305 wxMessageBox(wxT("No selected item!"));
1308 // ----------------------------------------------------------------------------
1309 // wxMediaPlayerFrame::OnPrev
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
))
1316 wxMediaPlayerNotebookPage
* currentpage
=
1317 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1319 if (currentpage
->m_playlist
->GetItemCount() == 0)
1322 wxInt32 nLastSelectedItem
= -1;
1325 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(nLastSelectedItem
,
1326 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1327 if (nSelectedItem
== -1)
1329 nLastSelectedItem
= nSelectedItem
;
1330 currentpage
->m_playlist
->SetItemState(nSelectedItem
, 0, wxLIST_STATE_SELECTED
);
1333 if (nLastSelectedItem
== -1)
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;
1339 nLastSelectedItem
= currentpage
->m_nLastFileId
- 1;
1341 else if (nLastSelectedItem
== 0)
1342 nLastSelectedItem
= currentpage
->m_playlist
->GetItemCount() - 1;
1344 nLastSelectedItem
-= 1;
1346 if(nLastSelectedItem
== currentpage
->m_nLastFileId
)
1347 return; // already playing... nothing to do
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
);
1357 wxASSERT(listitem
.GetData());
1358 DoPlayFile((*((wxString
*) listitem
.GetData())));
1361 // ----------------------------------------------------------------------------
1362 // wxMediaPlayerFrame::OnNext
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
))
1369 wxMediaPlayerNotebookPage
* currentpage
=
1370 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1372 if (currentpage
->m_playlist
->GetItemCount() == 0)
1375 wxInt32 nLastSelectedItem
= -1;
1378 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(nLastSelectedItem
,
1379 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1380 if (nSelectedItem
== -1)
1382 nLastSelectedItem
= nSelectedItem
;
1383 currentpage
->m_playlist
->SetItemState(nSelectedItem
, 0, wxLIST_STATE_SELECTED
);
1386 if (nLastSelectedItem
== -1)
1388 if(currentpage
->m_nLastFileId
== currentpage
->m_playlist
->GetItemCount() - 1)
1389 nLastSelectedItem
= 0;
1391 nLastSelectedItem
= currentpage
->m_nLastFileId
+ 1;
1393 else if (nLastSelectedItem
== currentpage
->m_playlist
->GetItemCount() - 1)
1394 nLastSelectedItem
= 0;
1396 nLastSelectedItem
+= 1;
1398 if(nLastSelectedItem
== currentpage
->m_nLastFileId
)
1399 return; // already playing... nothing to do
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
);
1409 wxASSERT(listitem
.GetData());
1410 DoPlayFile((*((wxString
*) listitem
.GetData())));
1414 // ----------------------------------------------------------------------------
1415 // wxMediaPlayerFrame::OnVolumeDown
1417 // Lowers the volume of the media control by 5%
1418 // ----------------------------------------------------------------------------
1419 void wxMediaPlayerFrame::OnVolumeDown(wxCommandEvent
& WXUNUSED(event
))
1421 wxMediaPlayerNotebookPage
* currentpage
=
1422 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1424 double dVolume
= currentpage
->m_mediactrl
->GetVolume();
1425 currentpage
->m_mediactrl
->SetVolume(dVolume
< 0.05 ? 0.0 : dVolume
- .05);
1428 // ----------------------------------------------------------------------------
1429 // wxMediaPlayerFrame::OnVolumeUp
1431 // Increases the volume of the media control by 5%
1432 // ----------------------------------------------------------------------------
1433 void wxMediaPlayerFrame::OnVolumeUp(wxCommandEvent
& WXUNUSED(event
))
1435 wxMediaPlayerNotebookPage
* currentpage
=
1436 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1438 double dVolume
= currentpage
->m_mediactrl
->GetVolume();
1439 currentpage
->m_mediactrl
->SetVolume(dVolume
> 0.95 ? 1.0 : dVolume
+ .05);
1442 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1444 // wxMediaPlayerTimer
1446 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1448 // ----------------------------------------------------------------------------
1449 // wxMediaPlayerTimer::Notify
1451 // 1) Updates media information on the status bar
1452 // 2) Sets the max/min length of the slider and guage
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()
1461 wxMediaPlayerNotebookPage
* currentpage
=
1462 (wxMediaPlayerNotebookPage
*) m_frame
->m_notebook
->GetCurrentPage();
1463 wxMediaCtrl
* currentMediaCtrl
= currentpage
->m_mediactrl
;
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();
1470 // Duration string (i.e. MM:SS)
1472 sDuration
.Printf(wxT("%2i:%02i"), nMinutes
, nSeconds
);
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();
1480 // Position string (i.e. MM:SS)
1482 sPosition
.Printf(wxT("%2i:%02i"), nMinutes
, nSeconds
);
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
);
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);
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());
1500 // Update the gauge with the download progress
1501 wxLongLong llDownloadProgress
=
1502 currentpage
->m_mediactrl
->GetDownloadProgress();
1503 wxLongLong llDownloadTotal
=
1504 currentpage
->m_mediactrl
->GetDownloadTotal();
1506 if(llDownloadTotal
.GetValue() != 0)
1508 currentpage
->m_gauge
->SetValue(
1509 (int) ((llDownloadProgress
* 100) / llDownloadTotal
).GetValue()
1513 // GetBestSize holds the original video size
1514 wxSize videoSize
= currentMediaCtrl
->GetBestSize();
1516 // Now the big part - set the status bar text to
1517 // hold various metadata about the media
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%%"),
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
1536 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1538 // wxMediaPlayerNotebookPage
1540 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1542 // ----------------------------------------------------------------------------
1543 // wxMediaPlayerNotebookPage Constructor
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
),
1555 m_bIsBeingDragged(false),
1556 m_parentFrame(parentFrame
)
1563 // [5 control buttons]
1569 // Create and attach a 2-column grid sizer
1571 wxFlexGridSizer
* sizer
= new wxFlexGridSizer(2);
1572 sizer
->AddGrowableCol(0);
1573 this->SetSizer(sizer
);
1576 // Create our media control
1578 m_mediactrl
= new wxMediaCtrl();
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"));
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!"));
1594 sizer
->Add(m_mediactrl
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1597 // Create the playlist/listctrl
1599 m_playlist
= new wxMediaPlayerListCtrl();
1600 m_playlist
->Create(this, wxID_LISTCTRL
, wxDefaultPosition
,
1602 wxLC_REPORT
// wxLC_LIST
1605 // Set the background of our listctrl to white
1606 m_playlist
->SetBackgroundColour(*wxWHITE
);
1608 // The layout of the headers of the listctrl are like
1609 // | | File | Length
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
1617 // (( - Volume Down 5%
1618 // )) - Volume Up 5%
1620 // Column two is the name of the file
1622 // Column three is the length in seconds of the file
1623 m_playlist
->InsertColumn(0,_(""), wxLIST_FORMAT_CENTER
, 20);
1624 m_playlist
->InsertColumn(1,_("File"), wxLIST_FORMAT_LEFT
, /*wxLIST_AUTOSIZE_USEHEADER*/305);
1625 m_playlist
->InsertColumn(2,_("Length"), wxLIST_FORMAT_CENTER
, 75);
1627 #if wxUSE_DRAG_AND_DROP
1628 m_playlist
->SetDropTarget(new wxPlayListDropTarget(*m_playlist
));
1631 sizer
->Add(m_playlist
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1634 // Create the control buttons
1635 // TODO/FIXME/HACK: This part about sizers is really a nice hack
1636 // and probably isn't proper
1638 wxBoxSizer
* horsizer1
= new wxBoxSizer(wxHORIZONTAL
);
1639 wxBoxSizer
* vertsizer
= new wxBoxSizer(wxHORIZONTAL
);
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();
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");
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);
1672 // Create our slider
1674 m_slider
= new wxSlider(this, wxID_SLIDER
, 0, // init
1676 1, // end, dummy but must be greater than start
1677 wxDefaultPosition
, wxDefaultSize
,
1679 sizer
->Add(m_slider
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
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);
1691 // Create the speed/volume sliders
1693 wxBoxSizer
* horsizer3
= new wxBoxSizer(wxHORIZONTAL
);
1695 m_volSlider
= new wxSlider(this, wxID_VOLSLIDER
, 100, // init
1698 wxDefaultPosition
, wxSize(250,20),
1700 horsizer3
->Add(m_volSlider
, 1, wxALL
, 5);
1702 m_pbSlider
= new wxSlider(this, wxID_PBSLIDER
, 4, // init
1705 wxDefaultPosition
, wxSize(250,20),
1707 horsizer3
->Add(m_pbSlider
, 1, wxALL
, 5);
1708 sizer
->Add(horsizer3
, 1, wxCENTRE
| wxALL
, 5);
1710 // Now that we have all our rows make some of them growable
1711 sizer
->AddGrowableRow(0);
1716 this->Connect( wxID_LISTCTRL
, wxEVT_LIST_ITEM_ACTIVATED
,
1717 wxListEventHandler(wxMediaPlayerFrame::OnChangeSong
),
1718 (wxObject
*)0, parentFrame
);
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
));
1733 // Media Control events
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
);
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
);
1770 // ----------------------------------------------------------------------------
1771 // MyNotebook::OnBeginSeek
1773 // Sets m_bIsBeingDragged to true to stop the timer from changing the position
1775 // ----------------------------------------------------------------------------
1776 void wxMediaPlayerNotebookPage::OnBeginSeek(wxScrollEvent
& WXUNUSED(event
))
1778 m_bIsBeingDragged
= true;
1781 // ----------------------------------------------------------------------------
1782 // MyNotebook::OnEndSeek
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
))
1791 if( m_mediactrl
->Seek(
1792 m_slider
->GetValue() * 1000
1793 ) == wxInvalidOffset
)
1794 wxMessageBox(wxT("Couldn't seek in movie!"));
1796 m_bIsBeingDragged
= false;
1799 // ----------------------------------------------------------------------------
1800 // wxMediaPlayerNotebookPage::IsBeingDragged
1802 // Returns true if the user is dragging the slider
1803 // ----------------------------------------------------------------------------
1804 bool wxMediaPlayerNotebookPage::IsBeingDragged()
1806 return m_bIsBeingDragged
;
1809 // ----------------------------------------------------------------------------
1810 // wxMediaPlayerNotebookPage::OnVolChange
1812 // Called when the user is done dragging the volume-changing slider
1813 // ----------------------------------------------------------------------------
1814 void wxMediaPlayerNotebookPage::OnVolChange(wxScrollEvent
& WXUNUSED(event
))
1816 if( m_mediactrl
->SetVolume(
1817 m_volSlider
->GetValue() / 100.0
1819 wxMessageBox(wxT("Couldn't set volume!"));
1823 // ----------------------------------------------------------------------------
1824 // wxMediaPlayerNotebookPage::OnPBChange
1826 // Called when the user is done dragging the speed-changing slider
1827 // ----------------------------------------------------------------------------
1828 void wxMediaPlayerNotebookPage::OnPBChange(wxScrollEvent
& WXUNUSED(event
))
1830 if( m_mediactrl
->SetPlaybackRate(
1831 m_pbSlider
->GetValue() * .25
1833 wxMessageBox(wxT("Couldn't set playbackrate!"));
1837 // ----------------------------------------------------------------------------
1838 // wxMediaPlayerNotebookPage::OnMediaPlay
1840 // Called when the media plays.
1841 // ----------------------------------------------------------------------------
1842 void wxMediaPlayerNotebookPage::OnMediaPlay(wxMediaEvent
& WXUNUSED(event
))
1844 m_playlist
->SetItem(m_nLastFileId
, 0, wxT(">"));
1847 // ----------------------------------------------------------------------------
1848 // wxMediaPlayerNotebookPage::OnMediaPause
1850 // Called when the media is paused.
1851 // ----------------------------------------------------------------------------
1852 void wxMediaPlayerNotebookPage::OnMediaPause(wxMediaEvent
& WXUNUSED(event
))
1854 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("||"));
1857 // ----------------------------------------------------------------------------
1858 // wxMediaPlayerNotebookPage::OnMediaStop
1860 // Called when the media stops.
1861 // ----------------------------------------------------------------------------
1862 void wxMediaPlayerNotebookPage::OnMediaStop(wxMediaEvent
& WXUNUSED(event
))
1864 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("[]"));
1867 // ----------------------------------------------------------------------------
1868 // wxMediaPlayerNotebookPage::OnMediaFinished
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
))
1877 if ( !m_mediactrl
->Play() )
1879 wxMessageBox(wxT("Couldn't loop movie!"));
1880 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("E"));
1887 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("[]"));
1892 // End of MediaPlayer sample