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
71 #include "../sample.xpm"
74 // ----------------------------------------------------------------------------
75 // Bail out if the user doesn't want one of the
77 // ----------------------------------------------------------------------------
79 #if !wxUSE_MEDIACTRL || !wxUSE_MENUS || !wxUSE_SLIDER || !wxUSE_TIMER || \
80 !wxUSE_NOTEBOOK || !wxUSE_LISTCTRL
81 #error "Not all required elements are enabled. Please modify setup.h!"
84 // ============================================================================
86 // ============================================================================
88 // ----------------------------------------------------------------------------
90 // ----------------------------------------------------------------------------
92 // IDs for the controls and the menu commands
97 wxID_OPENFILESAMEPAGE
,
101 wxID_CLOSECURRENTPAGE
,
108 // wxID_STOP, [built-in to wxWidgets]
109 // wxID_ABOUT, [built-in to wxWidgets]
110 // wxID_EXIT, [built-in to wxWidgets]
127 // ----------------------------------------------------------------------------
129 // ----------------------------------------------------------------------------
131 class wxMediaPlayerApp
: public wxApp
135 virtual void MacOpenFile(const wxString
& fileName
);
138 virtual bool OnInit();
141 class wxMediaPlayerFrame
* m_frame
;
144 // ----------------------------------------------------------------------------
145 // wxMediaPlayerFrame
146 // ----------------------------------------------------------------------------
148 class wxMediaPlayerFrame
: public wxFrame
152 wxMediaPlayerFrame(const wxString
& title
);
153 ~wxMediaPlayerFrame();
155 // Menu event handlers
156 void OnQuit(wxCommandEvent
& event
);
157 void OnAbout(wxCommandEvent
& event
);
159 void OnOpenFileSamePage(wxCommandEvent
& event
);
160 void OnOpenFileNewPage(wxCommandEvent
& event
);
161 void OnOpenURLSamePage(wxCommandEvent
& event
);
162 void OnOpenURLNewPage(wxCommandEvent
& event
);
163 void OnCloseCurrentPage(wxCommandEvent
& event
);
165 void OnPlay(wxCommandEvent
& event
);
166 void OnPause(wxCommandEvent
& event
);
167 void OnStop(wxCommandEvent
& event
);
168 void OnNext(wxCommandEvent
& event
);
169 void OnPrev(wxCommandEvent
& event
);
170 void OnVolumeDown(wxCommandEvent
& event
);
171 void OnVolumeUp(wxCommandEvent
& event
);
173 void OnLoop(wxCommandEvent
& event
);
174 void OnShowInterface(wxCommandEvent
& event
);
176 void OnSelectBackend(wxCommandEvent
& event
);
178 // Key event handlers
179 void OnKeyDown(wxKeyEvent
& event
);
181 // Quickie for playing from command line
182 void AddToPlayList(const wxString
& szString
);
184 // ListCtrl event handlers
185 void OnChangeSong(wxListEvent
& event
);
187 // Media event handlers
188 void OnMediaLoaded(wxMediaEvent
& event
);
190 // Close event handlers
191 void OnClose(wxCloseEvent
& event
);
194 // Common open file code
195 void OpenFile(bool bNewPage
);
196 void OpenURL(bool bNewPage
);
197 void DoOpenFile(const wxString
& path
, bool bNewPage
);
198 void DoPlayFile(const wxString
& path
);
200 class wxMediaPlayerTimer
* m_timer
; // Timer to write info to status bar
201 wxNotebook
* m_notebook
; // Notebook containing our pages
203 // Maybe I should use more accessors, but for simplicity
204 // I'll allow the other classes access to our members
205 friend class wxMediaPlayerApp
;
206 friend class wxMediaPlayerNotebookPage
;
207 friend class wxMediaPlayerTimer
;
212 // ----------------------------------------------------------------------------
213 // wxMediaPlayerNotebookPage
214 // ----------------------------------------------------------------------------
216 class wxMediaPlayerNotebookPage
: public wxPanel
218 wxMediaPlayerNotebookPage(wxMediaPlayerFrame
* parentFrame
,
219 wxNotebook
* book
, const wxString
& be
= wxEmptyString
);
221 // Slider event handlers
222 void OnBeginSeek(wxScrollEvent
& event
);
223 void OnEndSeek(wxScrollEvent
& event
);
224 void OnPBChange(wxScrollEvent
& event
);
225 void OnVolChange(wxScrollEvent
& event
);
227 // Media event handlers
228 void OnMediaPlay(wxMediaEvent
& event
);
229 void OnMediaPause(wxMediaEvent
& event
);
230 void OnMediaStop(wxMediaEvent
& event
);
231 void OnMediaFinished(wxMediaEvent
& event
);
234 bool IsBeingDragged(); // accessor for m_bIsBeingDragged
236 // make wxMediaPlayerFrame able to access the private members
237 friend class wxMediaPlayerFrame
;
239 int m_nLastFileId
; // List ID of played file in listctrl
240 wxString m_szFile
; // Name of currently playing file/location
242 wxMediaCtrl
* m_mediactrl
; // Our media control
243 class wxMediaPlayerListCtrl
* m_playlist
; // Our playlist
244 wxSlider
* m_slider
; // The slider below our media control
245 wxSlider
* m_pbSlider
; // Lower-left slider for adjusting speed
246 wxSlider
* m_volSlider
; // Lower-right slider for adjusting volume
247 int m_nLoops
; // Number of times media has looped
248 bool m_bLoop
; // Whether we are looping or not
249 bool m_bIsBeingDragged
; // Whether the user is dragging the scroll bar
250 wxMediaPlayerFrame
* m_parentFrame
; // Main wxFrame of our sample
251 wxButton
* m_prevButton
; // Go to previous file button
252 wxButton
* m_playButton
; // Play/pause file button
253 wxButton
* m_stopButton
; // Stop playing file button
254 wxButton
* m_nextButton
; // Next file button
255 wxButton
* m_vdButton
; // Volume down button
256 wxButton
* m_vuButton
; // Volume up button
257 wxGauge
* m_gauge
; // Gauge to keep in line with slider
260 // ----------------------------------------------------------------------------
261 // wxMediaPlayerTimer
262 // ----------------------------------------------------------------------------
264 class wxMediaPlayerTimer
: public wxTimer
268 wxMediaPlayerTimer(wxMediaPlayerFrame
* frame
) {m_frame
= frame
;}
270 // Called each time the timer's timeout expires
273 wxMediaPlayerFrame
* m_frame
; // The wxMediaPlayerFrame
276 // ----------------------------------------------------------------------------
277 // wxMediaPlayerListCtrl
278 // ----------------------------------------------------------------------------
279 class wxMediaPlayerListCtrl
: public wxListCtrl
282 void AddToPlayList(const wxString
& szString
)
285 kNewItem
.SetAlign(wxLIST_FORMAT_LEFT
);
287 int nID
= this->GetItemCount();
289 kNewItem
.SetMask(wxLIST_MASK_DATA
);
290 kNewItem
.SetData(new wxString(szString
));
292 this->InsertItem(kNewItem
);
293 this->SetItem(nID
, 0, wxT("*"));
294 this->SetItem(nID
, 1, wxFileName(szString
).GetName());
298 kNewItem
.SetBackgroundColour(wxColour(192,192,192));
299 this->SetItem(kNewItem
);
303 void GetSelectedItem(wxListItem
& listitem
)
305 listitem
.SetMask(wxLIST_MASK_TEXT
| wxLIST_MASK_DATA
);
306 int nLast
= -1, nLastSelected
= -1;
307 while ((nLast
= this->GetNextItem(nLast
,
309 wxLIST_STATE_SELECTED
)) != -1)
311 listitem
.SetId(nLast
);
312 this->GetItem(listitem
);
313 if ((listitem
.GetState() & wxLIST_STATE_FOCUSED
) )
315 nLastSelected
= nLast
;
317 if (nLast
== -1 && nLastSelected
== -1)
319 listitem
.SetId(nLastSelected
== -1 ? nLast
: nLastSelected
);
320 this->GetItem(listitem
);
324 // ----------------------------------------------------------------------------
325 // wxPlayListDropTarget
327 // Drop target for playlist (i.e. allows users to drag a file from explorer into
328 // the playlist to add that file)
329 // ----------------------------------------------------------------------------
330 #if wxUSE_DRAG_AND_DROP
331 class wxPlayListDropTarget
: public wxFileDropTarget
334 wxPlayListDropTarget(wxMediaPlayerListCtrl
& list
) : m_list(list
) {}
335 ~wxPlayListDropTarget(){}
336 virtual bool OnDropFiles(wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
),
337 const wxArrayString
& files
)
339 for (size_t i
= 0; i
< files
.GetCount(); ++i
)
341 m_list
.AddToPlayList(files
[i
]);
345 wxMediaPlayerListCtrl
& m_list
;
349 // ============================================================================
353 // ============================================================================
355 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
359 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
361 // ----------------------------------------------------------------------------
362 // wxGetMediaStateText
364 // Converts a wxMediaCtrl state into something useful that we can display
366 // ----------------------------------------------------------------------------
367 const wxChar
* wxGetMediaStateText(int nState
)
371 case wxMEDIASTATE_PLAYING
:
372 return wxT("Playing");
373 case wxMEDIASTATE_STOPPED
:
374 return wxT("Stopped");
375 ///case wxMEDIASTATE_PAUSED:
377 return wxT("Paused");
381 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
385 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
387 // ----------------------------------------------------------------------------
388 // This sets up this wxApp as the global wxApp that gui calls in wxWidgets
389 // use. For example, if you were to be in windows and use a file dialog,
390 // wxWidgets would use wxTheApp->GetHInstance() which would get the instance
391 // handle of the application. These routines in wx _DO NOT_ check to see if
392 // the wxApp exists, and thus will crash the application if you try it.
394 // IMPLEMENT_APP does this, and also implements the platform-specific entry
395 // routine, such as main or WinMain(). Use IMPLEMENT_APP_NO_MAIN if you do
396 // not desire this behavior.
397 // ----------------------------------------------------------------------------
398 IMPLEMENT_APP(wxMediaPlayerApp
)
400 // ----------------------------------------------------------------------------
401 // wxMediaPlayerApp::OnInit
403 // Where execution starts - akin to a main or WinMain.
404 // 1) Create the frame and show it to the user
405 // 2) Process filenames from the commandline
406 // 3) return true specifying that we want execution to continue past OnInit
407 // ----------------------------------------------------------------------------
408 bool wxMediaPlayerApp::OnInit()
410 if ( !wxApp::OnInit() )
413 // SetAppName() lets wxConfig and others know where to write
414 SetAppName(wxT("wxMediaPlayer"));
416 wxMediaPlayerFrame
*frame
=
417 new wxMediaPlayerFrame(wxT("MediaPlayer wxWidgets Sample"));
420 #if wxUSE_CMDLINE_PARSER
422 // What this does is get all the command line arguments
423 // and treat each one as a file to put to the initial playlist
425 wxCmdLineEntryDesc cmdLineDesc
[2];
426 cmdLineDesc
[0].kind
= wxCMD_LINE_PARAM
;
427 cmdLineDesc
[0].shortName
= NULL
;
428 cmdLineDesc
[0].longName
= NULL
;
429 cmdLineDesc
[0].description
= "input files";
430 cmdLineDesc
[0].type
= wxCMD_LINE_VAL_STRING
;
431 cmdLineDesc
[0].flags
= wxCMD_LINE_PARAM_OPTIONAL
| wxCMD_LINE_PARAM_MULTIPLE
;
433 cmdLineDesc
[1].kind
= wxCMD_LINE_NONE
;
435 // gets the passed media files from cmd line
436 wxCmdLineParser
parser (cmdLineDesc
, argc
, argv
);
438 // get filenames from the commandline
439 if (parser
.Parse() == 0)
441 for (size_t paramNr
=0; paramNr
< parser
.GetParamCount(); ++paramNr
)
443 frame
->AddToPlayList((parser
.GetParam (paramNr
)));
445 wxCommandEvent
theEvent(wxEVT_COMMAND_MENU_SELECTED
, wxID_NEXT
);
446 frame
->AddPendingEvent(theEvent
);
455 void wxMediaPlayerApp::MacOpenFile(const wxString
& fileName
)
457 // Called when a user drags a file over our app
458 m_frame
->DoOpenFile(fileName
, true /* new page */);
463 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
465 // wxMediaPlayerFrame
467 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
469 // ----------------------------------------------------------------------------
470 // wxMediaPlayerFrame Constructor
472 // 1) Create our menus
473 // 2) Create our notebook control and add it to the frame
474 // 3) Create our status bar
475 // 4) Connect our events
476 // 5) Start our timer
477 // ----------------------------------------------------------------------------
479 wxMediaPlayerFrame::wxMediaPlayerFrame(const wxString
& title
)
480 : wxFrame(NULL
, wxID_ANY
, title
, wxDefaultPosition
, wxSize(600,600))
482 SetIcon(wxICON(sample
));
487 wxMenu
*fileMenu
= new wxMenu
;
488 wxMenu
*controlsMenu
= new wxMenu
;
489 wxMenu
*optionsMenu
= new wxMenu
;
490 wxMenu
*helpMenu
= new wxMenu
;
491 wxMenu
*debugMenu
= new wxMenu
;
493 fileMenu
->Append(wxID_OPENFILESAMEPAGE
, wxT("&Open File\tCtrl-Shift-O"),
494 wxT("Open a File in the current notebook page"));
495 fileMenu
->Append(wxID_OPENFILENEWPAGE
, wxT("&Open File in a new page"),
496 wxT("Open a File in a new notebook page"));
497 fileMenu
->Append(wxID_OPENURLSAMEPAGE
, wxT("&Open URL"),
498 wxT("Open a URL in the current notebook page"));
499 fileMenu
->Append(wxID_OPENURLNEWPAGE
, wxT("&Open URL in a new page"),
500 wxT("Open a URL in a new notebook page"));
501 fileMenu
->AppendSeparator();
502 fileMenu
->Append(wxID_CLOSECURRENTPAGE
, wxT("&Close Current Page\tCtrl-C"),
503 wxT("Close current notebook page"));
504 fileMenu
->AppendSeparator();
505 fileMenu
->Append(wxID_EXIT
,
507 wxT("Quit this program"));
509 controlsMenu
->Append(wxID_PLAY
, wxT("&Play/Pause\tCtrl-P"), wxT("Resume/Pause playback"));
510 controlsMenu
->Append(wxID_STOP
, wxT("&Stop\tCtrl-S"), wxT("Stop playback"));
511 controlsMenu
->AppendSeparator();
512 controlsMenu
->Append(wxID_PREV
, wxT("&Previous\tCtrl-B"), wxT("Go to previous track"));
513 controlsMenu
->Append(wxID_NEXT
, wxT("&Next\tCtrl-N"), wxT("Skip to next track"));
515 optionsMenu
->AppendCheckItem(wxID_LOOP
,
516 wxT("&Loop\tCtrl-L"),
517 wxT("Loop Selected Media"));
518 optionsMenu
->AppendCheckItem(wxID_SHOWINTERFACE
,
519 wxT("&Show Interface\tCtrl-I"),
520 wxT("Show wxMediaCtrl native controls"));
522 debugMenu
->Append(wxID_SELECTBACKEND
,
523 wxT("&Select Backend...\tCtrl-D"),
524 wxT("Select a backend manually"));
526 helpMenu
->Append(wxID_ABOUT
,
527 wxT("&About...\tF1"),
528 wxT("Show about dialog"));
531 wxMenuBar
*menuBar
= new wxMenuBar();
532 menuBar
->Append(fileMenu
, wxT("&File"));
533 menuBar
->Append(controlsMenu
, wxT("&Controls"));
534 menuBar
->Append(optionsMenu
, wxT("&Options"));
535 menuBar
->Append(debugMenu
, wxT("&Debug"));
536 menuBar
->Append(helpMenu
, wxT("&Help"));
540 // Create our notebook - using wxNotebook is luckily pretty
541 // simple and self-explanatory in most cases
543 m_notebook
= new wxNotebook(this, wxID_NOTEBOOK
);
546 // Create our status bar
549 // create a status bar just for fun (by default with 1 pane only)
551 #endif // wxUSE_STATUSBAR
556 // There are two ways in wxWidgets to use events -
557 // Message Maps and Connections.
559 // Message Maps are implemented by putting
560 // DECLARE_MESSAGE_MAP in your wxEvtHandler-derived
561 // class you want to use for events, such as wxMediaPlayerFrame.
563 // Then after your class declaration you put
564 // BEGIN_EVENT_TABLE(wxMediaPlayerFrame, wxFrame)
568 // Where wxMediaPlayerFrame is the class with the DECLARE_MESSAGE_MAP
569 // in it. EVT_XXX(XXX) are each of your handlers, such
570 // as EVT_MENU for menu events and the XXX inside
571 // is the parameters to the event macro - in the case
572 // of EVT_MENU the menu id and then the function to call.
574 // However, with wxEvtHandler::Connect you can avoid a
575 // global message map for your class and those annoying
576 // macros. You can also change the context in which
577 // the call the handler (more later).
579 // The downside is that due to the limitation that
580 // wxWidgets doesn't use templates in certain areas,
581 // You have to triple-cast the event function.
583 // There are five parameters to wxEvtHandler::Connect -
585 // The first is the id of the instance whose events
586 // you want to handle - i.e. a menu id for menus,
587 // a control id for controls (wxControl::GetId())
590 // The second is the event id. This is the same
591 // as the message maps (EVT_MENU) except prefixed
592 // with "wx" (wxEVT_MENU).
594 // The third is the function handler for the event -
595 // You need to cast it to the specific event handler
596 // type, then to a wxEventFunction, then to a
597 // wxObjectEventFunction - I.E.
598 // (wxObjectEventFunction)(wxEventFunction)
599 // (wxCommandEventFunction) &wxMediaPlayerFrame::MyHandler
601 // Or, you can use the new (2.5.5+) event handler
602 // conversion macros - for instance the above could
604 // wxCommandEventHandler(wxMediaPlayerFrame::MyHandler)
605 // pretty simple, eh?
607 // The fourth is an optional userdata param -
608 // this is of historical relevance only and is
609 // there only for backwards compatibility.
611 // The fifth is the context in which to call the
612 // handler - by default (this param is optional)
613 // this. For example in your event handler
614 // if you were to call "this->MyFunc()"
615 // it would literally do this->MyFunc. However,
616 // if you were to pass myHandler as the fifth
617 // parameter, for instance, you would _really_
618 // be calling myHandler->MyFunc, even though
619 // the compiler doesn't really know it.
625 this->Connect(wxID_EXIT
, wxEVT_COMMAND_MENU_SELECTED
,
626 wxCommandEventHandler(wxMediaPlayerFrame::OnQuit
));
628 this->Connect(wxID_ABOUT
, wxEVT_COMMAND_MENU_SELECTED
,
629 wxCommandEventHandler(wxMediaPlayerFrame::OnAbout
));
631 this->Connect(wxID_LOOP
, wxEVT_COMMAND_MENU_SELECTED
,
632 wxCommandEventHandler(wxMediaPlayerFrame::OnLoop
));
634 this->Connect(wxID_SHOWINTERFACE
, wxEVT_COMMAND_MENU_SELECTED
,
635 wxCommandEventHandler(wxMediaPlayerFrame::OnShowInterface
));
637 this->Connect(wxID_OPENFILENEWPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
638 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileNewPage
));
640 this->Connect(wxID_OPENFILESAMEPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
641 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileSamePage
));
643 this->Connect(wxID_OPENURLNEWPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
644 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLNewPage
));
646 this->Connect(wxID_OPENURLSAMEPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
647 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLSamePage
));
649 this->Connect(wxID_CLOSECURRENTPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
650 wxCommandEventHandler(wxMediaPlayerFrame::OnCloseCurrentPage
));
652 this->Connect(wxID_PLAY
, wxEVT_COMMAND_MENU_SELECTED
,
653 wxCommandEventHandler(wxMediaPlayerFrame::OnPlay
));
655 this->Connect(wxID_STOP
, wxEVT_COMMAND_MENU_SELECTED
,
656 wxCommandEventHandler(wxMediaPlayerFrame::OnStop
));
658 this->Connect(wxID_NEXT
, wxEVT_COMMAND_MENU_SELECTED
,
659 wxCommandEventHandler(wxMediaPlayerFrame::OnNext
));
661 this->Connect(wxID_PREV
, wxEVT_COMMAND_MENU_SELECTED
,
662 wxCommandEventHandler(wxMediaPlayerFrame::OnPrev
));
664 this->Connect(wxID_SELECTBACKEND
, wxEVT_COMMAND_MENU_SELECTED
,
665 wxCommandEventHandler(wxMediaPlayerFrame::OnSelectBackend
));
670 wxTheApp
->Connect(wxID_ANY
, wxEVT_KEY_DOWN
,
671 wxKeyEventHandler(wxMediaPlayerFrame::OnKeyDown
),
677 this->Connect(wxID_ANY
, wxEVT_CLOSE_WINDOW
,
678 wxCloseEventHandler(wxMediaPlayerFrame::OnClose
));
685 // Create an initial notebook page so the user has something
686 // to work with without having to go file->open every time :).
688 wxMediaPlayerNotebookPage
* page
=
689 new wxMediaPlayerNotebookPage(this, m_notebook
);
690 m_notebook
->AddPage(page
,
695 // Here we load the our configuration -
696 // in our case we load all the files that were left in
697 // the playlist the last time the user closed our application
699 // As an exercise to the reader try modifying it so that
700 // it properly loads the playlist for each page without
701 // conflicting (loading the same data) with the other ones.
704 wxString key
, outstring
;
705 for(int i
= 0; ; ++i
)
709 if(!conf
.Read(key
, &outstring
))
711 page
->m_playlist
->AddToPlayList(outstring
);
715 // Create a timer to update our status bar
717 m_timer
= new wxMediaPlayerTimer(this);
721 // ----------------------------------------------------------------------------
722 // wxMediaPlayerFrame Destructor
724 // 1) Deletes child objects implicitly
725 // 2) Delete our timer explicitly
726 // ----------------------------------------------------------------------------
727 wxMediaPlayerFrame::~wxMediaPlayerFrame()
729 // Shut down our timer
733 // Here we save our info to the registry or whatever
734 // mechanism the OS uses.
736 // This makes it so that when mediaplayer loads up again
737 // it restores the same files that were in the playlist
738 // this time, rather than the user manually re-adding them.
740 // We need to do conf->DeleteAll() here because by default
741 // the config still contains the same files as last time
742 // so we need to clear it before writing our new ones.
744 // TODO: Maybe you could add a menu option to the
745 // options menu to delete the configuration on exit -
746 // all you'd need to do is just remove everything after
747 // conf->DeleteAll() here
749 // As an exercise to the reader, try modifying this so
750 // that it saves the data for each notebook page
752 wxMediaPlayerListCtrl
* playlist
=
753 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetPage(0))->m_playlist
;
758 for(int i
= 0; i
< playlist
->GetItemCount(); ++i
)
760 wxString
* pData
= (wxString
*) playlist
->GetItemData(i
);
763 conf
.Write(s
, *(pData
));
768 // ----------------------------------------------------------------------------
769 // wxMediaPlayerFrame::OnClose
770 // ----------------------------------------------------------------------------
771 void wxMediaPlayerFrame::OnClose(wxCloseEvent
& event
)
773 event
.Skip(); // really close the frame
776 // ----------------------------------------------------------------------------
777 // wxMediaPlayerFrame::AddToPlayList
778 // ----------------------------------------------------------------------------
779 void wxMediaPlayerFrame::AddToPlayList(const wxString
& szString
)
781 wxMediaPlayerNotebookPage
* currentpage
=
782 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
784 currentpage
->m_playlist
->AddToPlayList(szString
);
787 // ----------------------------------------------------------------------------
788 // wxMediaPlayerFrame::OnQuit
790 // Called from file->quit.
791 // Closes this application.
792 // ----------------------------------------------------------------------------
793 void wxMediaPlayerFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
795 // true is to force the frame to close
799 // ----------------------------------------------------------------------------
800 // wxMediaPlayerFrame::OnAbout
802 // Called from help->about.
803 // Gets some info about this application.
804 // ----------------------------------------------------------------------------
805 void wxMediaPlayerFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
808 msg
.Printf( wxT("This is a test of wxMediaCtrl.\n\n")
810 wxT("Instructions:\n")
812 wxT("The top slider shows the current the current position, ")
813 wxT("which you can change by dragging and releasing it.\n")
815 wxT("The gauge (progress bar) shows the progress in ")
816 wxT("downloading data of the current file - it may always be ")
817 wxT("empty due to lack of support from the current backend.\n")
819 wxT("The lower-left slider controls the volume and the lower-")
820 wxT("right slider controls the playback rate/speed of the ")
823 wxT("Currently using: %s"), wxVERSION_STRING
);
825 wxMessageBox(msg
, wxT("About wxMediaCtrl test"),
826 wxOK
| wxICON_INFORMATION
, this);
829 // ----------------------------------------------------------------------------
830 // wxMediaPlayerFrame::OnLoop
832 // Called from file->loop.
833 // Changes the state of whether we want to loop or not.
834 // ----------------------------------------------------------------------------
835 void wxMediaPlayerFrame::OnLoop(wxCommandEvent
& WXUNUSED(event
))
837 wxMediaPlayerNotebookPage
* currentpage
=
838 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
840 currentpage
->m_bLoop
= !currentpage
->m_bLoop
;
843 // ----------------------------------------------------------------------------
844 // wxMediaPlayerFrame::OnLoop
846 // Called from file->loop.
847 // Changes the state of whether we want to loop or not.
848 // ----------------------------------------------------------------------------
849 void wxMediaPlayerFrame::OnShowInterface(wxCommandEvent
& event
)
851 wxMediaPlayerNotebookPage
* currentpage
=
852 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
854 if( !currentpage
->m_mediactrl
->ShowPlayerControls(event
.IsChecked() ?
855 wxMEDIACTRLPLAYERCONTROLS_DEFAULT
:
856 wxMEDIACTRLPLAYERCONTROLS_NONE
) )
858 // error - uncheck and warn user
859 wxMenuItem
* pSIItem
= GetMenuBar()->FindItem(wxID_SHOWINTERFACE
);
861 pSIItem
->Check(!event
.IsChecked());
863 if(event
.IsChecked())
864 wxMessageBox(wxT("Could not show player controls"));
866 wxMessageBox(wxT("Could not hide player controls"));
870 // ----------------------------------------------------------------------------
871 // wxMediaPlayerFrame::OnOpenFileSamePage
873 // Called from file->openfile.
874 // Opens and plays a media file in the current notebook page
875 // ----------------------------------------------------------------------------
876 void wxMediaPlayerFrame::OnOpenFileSamePage(wxCommandEvent
& WXUNUSED(event
))
881 // ----------------------------------------------------------------------------
882 // wxMediaPlayerFrame::OnOpenFileNewPage
884 // Called from file->openfileinnewpage.
885 // Opens and plays a media file in a new notebook page
886 // ----------------------------------------------------------------------------
887 void wxMediaPlayerFrame::OnOpenFileNewPage(wxCommandEvent
& WXUNUSED(event
))
892 // ----------------------------------------------------------------------------
893 // wxMediaPlayerFrame::OpenFile
895 // Opens a file dialog asking the user for a filename, then
896 // calls DoOpenFile which will add the file to the playlist and play it
897 // ----------------------------------------------------------------------------
898 void wxMediaPlayerFrame::OpenFile(bool bNewPage
)
900 wxFileDialog
fd(this);
902 if(fd
.ShowModal() == wxID_OK
)
904 DoOpenFile(fd
.GetPath(), bNewPage
);
908 // ----------------------------------------------------------------------------
909 // wxMediaPlayerFrame::DoOpenFile
911 // Adds the file to our playlist, selects it in the playlist,
912 // and then calls DoPlayFile to play it
913 // ----------------------------------------------------------------------------
914 void wxMediaPlayerFrame::DoOpenFile(const wxString
& path
, bool bNewPage
)
919 new wxMediaPlayerNotebookPage(this, m_notebook
),
924 wxMediaPlayerNotebookPage
* currentpage
=
925 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
927 if(currentpage
->m_nLastFileId
!= -1)
928 currentpage
->m_playlist
->SetItemState(currentpage
->m_nLastFileId
,
929 0, wxLIST_STATE_SELECTED
);
931 wxListItem newlistitem
;
932 newlistitem
.SetAlign(wxLIST_FORMAT_LEFT
);
936 newlistitem
.SetId(nID
= currentpage
->m_playlist
->GetItemCount());
937 newlistitem
.SetMask(wxLIST_MASK_DATA
| wxLIST_MASK_STATE
);
938 newlistitem
.SetState(wxLIST_STATE_SELECTED
);
939 newlistitem
.SetData(new wxString(path
));
941 currentpage
->m_playlist
->InsertItem(newlistitem
);
942 currentpage
->m_playlist
->SetItem(nID
, 0, wxT("*"));
943 currentpage
->m_playlist
->SetItem(nID
, 1, wxFileName(path
).GetName());
947 newlistitem
.SetBackgroundColour(wxColour(192,192,192));
948 currentpage
->m_playlist
->SetItem(newlistitem
);
954 // ----------------------------------------------------------------------------
955 // wxMediaPlayerFrame::DoPlayFile
957 // Pauses the file if its the currently playing file,
958 // otherwise it plays the file
959 // ----------------------------------------------------------------------------
960 void wxMediaPlayerFrame::DoPlayFile(const wxString
& path
)
962 wxMediaPlayerNotebookPage
* currentpage
=
963 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
966 currentpage
->m_playlist
->GetSelectedItem(listitem
);
968 if( ( listitem
.GetData() &&
969 currentpage
->m_nLastFileId
== listitem
.GetId() &&
970 currentpage
->m_szFile
.compare(path
) == 0 ) ||
971 ( !listitem
.GetData() &&
972 currentpage
->m_nLastFileId
!= -1 &&
973 currentpage
->m_szFile
.compare(path
) == 0)
976 if(currentpage
->m_mediactrl
->GetState() == wxMEDIASTATE_PLAYING
)
978 if( !currentpage
->m_mediactrl
->Pause() )
979 wxMessageBox(wxT("Couldn't pause movie!"));
983 if( !currentpage
->m_mediactrl
->Play() )
984 wxMessageBox(wxT("Couldn't play movie!"));
989 int nNewId
= listitem
.GetData() ? listitem
.GetId() :
990 currentpage
->m_playlist
->GetItemCount()-1;
991 m_notebook
->SetPageText(m_notebook
->GetSelection(),
992 wxFileName(path
).GetName());
994 if(currentpage
->m_nLastFileId
!= -1)
995 currentpage
->m_playlist
->SetItem(
996 currentpage
->m_nLastFileId
, 0, wxT("*"));
999 if( uripath
.IsReference() )
1001 if( !currentpage
->m_mediactrl
->Load(path
) )
1003 wxMessageBox(wxT("Couldn't load file!"));
1004 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("E"));
1008 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("O"));
1013 if( !currentpage
->m_mediactrl
->Load(uripath
) )
1015 wxMessageBox(wxT("Couldn't load URL!"));
1016 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("E"));
1020 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("O"));
1024 currentpage
->m_nLastFileId
= nNewId
;
1025 currentpage
->m_szFile
= path
;
1026 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
,
1027 1, wxFileName(path
).GetName());
1028 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
,
1033 // ----------------------------------------------------------------------------
1034 // wxMediaPlayerFrame::OnMediaLoaded
1036 // Called when the media is ready to be played - and does
1037 // so, also gets the length of media and shows that in the list control
1038 // ----------------------------------------------------------------------------
1039 void wxMediaPlayerFrame::OnMediaLoaded(wxMediaEvent
& WXUNUSED(evt
))
1041 wxMediaPlayerNotebookPage
* currentpage
=
1042 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1044 if( !currentpage
->m_mediactrl
->Play() )
1046 wxMessageBox(wxT("Couldn't play movie!"));
1047 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
, 0, wxT("E"));
1051 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
, 0, wxT(">"));
1057 // ----------------------------------------------------------------------------
1058 // wxMediaPlayerFrame::OnSelectBackend
1060 // Little debugging routine - enter the class name of a backend and it
1061 // will use that instead of letting wxMediaCtrl search the wxMediaBackend
1063 // ----------------------------------------------------------------------------
1064 void wxMediaPlayerFrame::OnSelectBackend(wxCommandEvent
& WXUNUSED(evt
))
1066 wxString sBackend
= wxGetTextFromUser(wxT("Enter backend to use"));
1068 if(sBackend
.empty() == false) // could have been cancelled by the user
1070 int sel
= m_notebook
->GetSelection();
1072 if (sel
!= wxNOT_FOUND
)
1074 m_notebook
->DeletePage(sel
);
1077 m_notebook
->AddPage(new wxMediaPlayerNotebookPage(this, m_notebook
,
1082 ((wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage())->m_szFile
,
1087 // ----------------------------------------------------------------------------
1088 // wxMediaPlayerFrame::OnOpenURLSamePage
1090 // Called from file->openurl.
1091 // Opens and plays a media file from a URL in the current notebook page
1092 // ----------------------------------------------------------------------------
1093 void wxMediaPlayerFrame::OnOpenURLSamePage(wxCommandEvent
& WXUNUSED(event
))
1098 // ----------------------------------------------------------------------------
1099 // wxMediaPlayerFrame::OnOpenURLNewPage
1101 // Called from file->openurlinnewpage.
1102 // Opens and plays a media file from a URL in a new notebook page
1103 // ----------------------------------------------------------------------------
1104 void wxMediaPlayerFrame::OnOpenURLNewPage(wxCommandEvent
& WXUNUSED(event
))
1109 // ----------------------------------------------------------------------------
1110 // wxMediaPlayerFrame::OpenURL
1112 // Just calls DoOpenFile with the url path - which calls DoPlayFile
1113 // which handles the real dirty work
1114 // ----------------------------------------------------------------------------
1115 void wxMediaPlayerFrame::OpenURL(bool bNewPage
)
1117 wxString sUrl
= wxGetTextFromUser(
1118 wxT("Enter the URL that has the movie to play")
1121 if(sUrl
.empty() == false) // could have been cancelled by user
1123 DoOpenFile(sUrl
, bNewPage
);
1127 // ----------------------------------------------------------------------------
1128 // wxMediaPlayerFrame::OnCloseCurrentPage
1130 // Called when the user wants to close the current notebook page
1132 // 1) Get the current page number (wxControl::GetSelection)
1133 // 2) If there is no current page, break out
1134 // 3) Delete the current page
1135 // ----------------------------------------------------------------------------
1136 void wxMediaPlayerFrame::OnCloseCurrentPage(wxCommandEvent
& WXUNUSED(event
))
1138 if( m_notebook
->GetPageCount() > 1 )
1140 int sel
= m_notebook
->GetSelection();
1142 if (sel
!= wxNOT_FOUND
)
1144 m_notebook
->DeletePage(sel
);
1149 wxMessageBox(wxT("Cannot close main page"));
1153 // ----------------------------------------------------------------------------
1154 // wxMediaPlayerFrame::OnPlay
1156 // Called from file->play.
1157 // Resumes the media if it is paused or stopped.
1158 // ----------------------------------------------------------------------------
1159 void wxMediaPlayerFrame::OnPlay(wxCommandEvent
& WXUNUSED(event
))
1161 wxMediaPlayerNotebookPage
* currentpage
=
1162 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1164 wxListItem listitem
;
1165 currentpage
->m_playlist
->GetSelectedItem(listitem
);
1166 if ( !listitem
.GetData() )
1169 if ((nLast
= currentpage
->m_playlist
->GetNextItem(nLast
,
1171 wxLIST_STATE_DONTCARE
)) == -1)
1174 wxMessageBox(wxT("No items in playlist!"));
1178 listitem
.SetId(nLast
);
1179 currentpage
->m_playlist
->GetItem(listitem
);
1180 listitem
.SetMask(listitem
.GetMask() | wxLIST_MASK_STATE
);
1181 listitem
.SetState(listitem
.GetState() | wxLIST_STATE_SELECTED
);
1182 currentpage
->m_playlist
->SetItem(listitem
);
1183 wxASSERT(listitem
.GetData());
1184 DoPlayFile((*((wxString
*) listitem
.GetData())));
1189 wxASSERT(listitem
.GetData());
1190 DoPlayFile((*((wxString
*) listitem
.GetData())));
1194 // ----------------------------------------------------------------------------
1195 // wxMediaPlayerFrame::OnKeyDown
1197 // Deletes all selected files from the playlist if the backspace key is pressed
1198 // ----------------------------------------------------------------------------
1199 void wxMediaPlayerFrame::OnKeyDown(wxKeyEvent
& event
)
1201 if(event
.GetKeyCode() == WXK_BACK
/*DELETE*/)
1203 wxMediaPlayerNotebookPage
* currentpage
=
1204 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1205 // delete all selected items
1208 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(
1209 -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1210 if (nSelectedItem
== -1)
1213 wxListItem listitem
;
1214 listitem
.SetId(nSelectedItem
);
1215 currentpage
->m_playlist
->GetItem(listitem
);
1216 delete (wxString
*) listitem
.GetData();
1218 currentpage
->m_playlist
->DeleteItem(nSelectedItem
);
1222 // Could be wxGetTextFromUser or something else important
1223 if(event
.GetEventObject() != this)
1227 // ----------------------------------------------------------------------------
1228 // wxMediaPlayerFrame::OnStop
1230 // Called from file->stop.
1231 // Where it stops depends on whether you can seek in the
1232 // media control or not - if you can it stops and seeks to the beginning,
1233 // otherwise it will appear to be at the end - but it will start over again
1234 // when Play() is called
1235 // ----------------------------------------------------------------------------
1236 void wxMediaPlayerFrame::OnStop(wxCommandEvent
& WXUNUSED(evt
))
1238 wxMediaPlayerNotebookPage
* currentpage
=
1239 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1241 if( !currentpage
->m_mediactrl
->Stop() )
1242 wxMessageBox(wxT("Couldn't stop movie!"));
1244 currentpage
->m_playlist
->SetItem(
1245 currentpage
->m_nLastFileId
, 0, wxT("[]"));
1249 // ----------------------------------------------------------------------------
1250 // wxMediaPlayerFrame::OnChangeSong
1252 // Routine that plays the currently selected file in the playlist.
1253 // Called when the user actives the song from the playlist,
1254 // and from other various places in the sample
1255 // ----------------------------------------------------------------------------
1256 void wxMediaPlayerFrame::OnChangeSong(wxListEvent
& WXUNUSED(evt
))
1258 wxMediaPlayerNotebookPage
* currentpage
=
1259 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1261 wxListItem listitem
;
1262 currentpage
->m_playlist
->GetSelectedItem(listitem
);
1263 if(listitem
.GetData())
1264 DoPlayFile((*((wxString
*) listitem
.GetData())));
1266 wxMessageBox(wxT("No selected item!"));
1269 // ----------------------------------------------------------------------------
1270 // wxMediaPlayerFrame::OnPrev
1272 // Tedious wxListCtrl stuff. Goes to prevous song in list, or if at the
1273 // beginning goes to the last in the list.
1274 // ----------------------------------------------------------------------------
1275 void wxMediaPlayerFrame::OnPrev(wxCommandEvent
& WXUNUSED(event
))
1277 wxMediaPlayerNotebookPage
* currentpage
=
1278 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1280 if (currentpage
->m_playlist
->GetItemCount() == 0)
1283 wxInt32 nLastSelectedItem
= -1;
1286 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(nLastSelectedItem
,
1287 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1288 if (nSelectedItem
== -1)
1290 nLastSelectedItem
= nSelectedItem
;
1291 currentpage
->m_playlist
->SetItemState(nSelectedItem
, 0, wxLIST_STATE_SELECTED
);
1294 if (nLastSelectedItem
== -1)
1296 // nothing selected, default to the file before the currently playing one
1297 if(currentpage
->m_nLastFileId
== 0)
1298 nLastSelectedItem
= currentpage
->m_playlist
->GetItemCount() - 1;
1300 nLastSelectedItem
= currentpage
->m_nLastFileId
- 1;
1302 else if (nLastSelectedItem
== 0)
1303 nLastSelectedItem
= currentpage
->m_playlist
->GetItemCount() - 1;
1305 nLastSelectedItem
-= 1;
1307 if(nLastSelectedItem
== currentpage
->m_nLastFileId
)
1308 return; // already playing... nothing to do
1310 wxListItem listitem
;
1311 listitem
.SetId(nLastSelectedItem
);
1312 listitem
.SetMask(wxLIST_MASK_TEXT
| wxLIST_MASK_DATA
);
1313 currentpage
->m_playlist
->GetItem(listitem
);
1314 listitem
.SetMask(listitem
.GetMask() | wxLIST_MASK_STATE
);
1315 listitem
.SetState(listitem
.GetState() | wxLIST_STATE_SELECTED
);
1316 currentpage
->m_playlist
->SetItem(listitem
);
1318 wxASSERT(listitem
.GetData());
1319 DoPlayFile((*((wxString
*) listitem
.GetData())));
1322 // ----------------------------------------------------------------------------
1323 // wxMediaPlayerFrame::OnNext
1325 // Tedious wxListCtrl stuff. Goes to next song in list, or if at the
1326 // end goes to the first in the list.
1327 // ----------------------------------------------------------------------------
1328 void wxMediaPlayerFrame::OnNext(wxCommandEvent
& WXUNUSED(event
))
1330 wxMediaPlayerNotebookPage
* currentpage
=
1331 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1333 if (currentpage
->m_playlist
->GetItemCount() == 0)
1336 wxInt32 nLastSelectedItem
= -1;
1339 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(nLastSelectedItem
,
1340 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1341 if (nSelectedItem
== -1)
1343 nLastSelectedItem
= nSelectedItem
;
1344 currentpage
->m_playlist
->SetItemState(nSelectedItem
, 0, wxLIST_STATE_SELECTED
);
1347 if (nLastSelectedItem
== -1)
1349 if(currentpage
->m_nLastFileId
== currentpage
->m_playlist
->GetItemCount() - 1)
1350 nLastSelectedItem
= 0;
1352 nLastSelectedItem
= currentpage
->m_nLastFileId
+ 1;
1354 else if (nLastSelectedItem
== currentpage
->m_playlist
->GetItemCount() - 1)
1355 nLastSelectedItem
= 0;
1357 nLastSelectedItem
+= 1;
1359 if(nLastSelectedItem
== currentpage
->m_nLastFileId
)
1360 return; // already playing... nothing to do
1362 wxListItem listitem
;
1363 listitem
.SetMask(wxLIST_MASK_TEXT
| wxLIST_MASK_DATA
);
1364 listitem
.SetId(nLastSelectedItem
);
1365 currentpage
->m_playlist
->GetItem(listitem
);
1366 listitem
.SetMask(listitem
.GetMask() | wxLIST_MASK_STATE
);
1367 listitem
.SetState(listitem
.GetState() | wxLIST_STATE_SELECTED
);
1368 currentpage
->m_playlist
->SetItem(listitem
);
1370 wxASSERT(listitem
.GetData());
1371 DoPlayFile((*((wxString
*) listitem
.GetData())));
1375 // ----------------------------------------------------------------------------
1376 // wxMediaPlayerFrame::OnVolumeDown
1378 // Lowers the volume of the media control by 5%
1379 // ----------------------------------------------------------------------------
1380 void wxMediaPlayerFrame::OnVolumeDown(wxCommandEvent
& WXUNUSED(event
))
1382 wxMediaPlayerNotebookPage
* currentpage
=
1383 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1385 double dVolume
= currentpage
->m_mediactrl
->GetVolume();
1386 currentpage
->m_mediactrl
->SetVolume(dVolume
< 0.05 ? 0.0 : dVolume
- .05);
1389 // ----------------------------------------------------------------------------
1390 // wxMediaPlayerFrame::OnVolumeUp
1392 // Increases the volume of the media control by 5%
1393 // ----------------------------------------------------------------------------
1394 void wxMediaPlayerFrame::OnVolumeUp(wxCommandEvent
& WXUNUSED(event
))
1396 wxMediaPlayerNotebookPage
* currentpage
=
1397 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1399 double dVolume
= currentpage
->m_mediactrl
->GetVolume();
1400 currentpage
->m_mediactrl
->SetVolume(dVolume
> 0.95 ? 1.0 : dVolume
+ .05);
1403 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1405 // wxMediaPlayerTimer
1407 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1409 // ----------------------------------------------------------------------------
1410 // wxMediaPlayerTimer::Notify
1412 // 1) Updates media information on the status bar
1413 // 2) Sets the max/min length of the slider and guage
1415 // Note that the reason we continually do this and don't cache it is because
1416 // some backends such as GStreamer are dynamic change values all the time
1417 // and often don't have things like duration or video size available
1418 // until the media is actually being played
1419 // ----------------------------------------------------------------------------
1420 void wxMediaPlayerTimer::Notify()
1422 wxMediaPlayerNotebookPage
* currentpage
=
1423 (wxMediaPlayerNotebookPage
*) m_frame
->m_notebook
->GetCurrentPage();
1424 wxMediaCtrl
* currentMediaCtrl
= currentpage
->m_mediactrl
;
1426 // Number of minutes/seconds total
1427 wxLongLong llLength
= currentpage
->m_mediactrl
->Length();
1428 int nMinutes
= (int) (llLength
/ 60000).GetValue();
1429 int nSeconds
= (int) ((llLength
% 60000)/1000).GetValue();
1431 // Duration string (i.e. MM:SS)
1433 sDuration
.Printf(wxT("%2i:%02i"), nMinutes
, nSeconds
);
1436 // Number of minutes/seconds total
1437 wxLongLong llTell
= currentpage
->m_mediactrl
->Tell();
1438 nMinutes
= (int) (llTell
/ 60000).GetValue();
1439 nSeconds
= (int) ((llTell
% 60000)/1000).GetValue();
1441 // Position string (i.e. MM:SS)
1443 sPosition
.Printf(wxT("%2i:%02i"), nMinutes
, nSeconds
);
1446 // Set the third item in the listctrl entry to the duration string
1447 if(currentpage
->m_nLastFileId
>= 0)
1448 currentpage
->m_playlist
->SetItem(
1449 currentpage
->m_nLastFileId
, 2, sDuration
);
1451 // Setup the slider and gauge min/max values
1452 currentpage
->m_slider
->SetRange(0, (int)(llLength
/ 1000).GetValue());
1453 currentpage
->m_gauge
->SetRange(100);
1456 // if the slider is not being dragged then update it with the song position
1457 if(currentpage
->IsBeingDragged() == false)
1458 currentpage
->m_slider
->SetValue((long)(llTell
/ 1000).GetValue());
1461 // Update the gauge with the download progress
1462 wxLongLong llDownloadProgress
=
1463 currentpage
->m_mediactrl
->GetDownloadProgress();
1464 wxLongLong llDownloadTotal
=
1465 currentpage
->m_mediactrl
->GetDownloadTotal();
1467 if(llDownloadTotal
.GetValue() != 0)
1469 currentpage
->m_gauge
->SetValue(
1470 (int) ((llDownloadProgress
* 100) / llDownloadTotal
).GetValue()
1474 // GetBestSize holds the original video size
1475 wxSize videoSize
= currentMediaCtrl
->GetBestSize();
1477 // Now the big part - set the status bar text to
1478 // hold various metadata about the media
1480 m_frame
->SetStatusText(wxString::Format(
1481 wxT("Size(x,y):%i,%i ")
1482 wxT("Position:%s/%s Speed:%1.1fx ")
1483 wxT("State:%s Loops:%i D/T:[%i]/[%i] V:%i%%"),
1488 currentMediaCtrl
->GetPlaybackRate(),
1489 wxGetMediaStateText(currentpage
->m_mediactrl
->GetState()),
1490 currentpage
->m_nLoops
,
1491 (int)llDownloadProgress
.GetValue(),
1492 (int)llDownloadTotal
.GetValue(),
1493 (int)(currentpage
->m_mediactrl
->GetVolume() * 100)));
1494 #endif // wxUSE_STATUSBAR
1497 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1499 // wxMediaPlayerNotebookPage
1501 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1503 // ----------------------------------------------------------------------------
1504 // wxMediaPlayerNotebookPage Constructor
1506 // Creates a media control and slider and adds it to this panel,
1507 // along with some sizers for positioning
1508 // ----------------------------------------------------------------------------
1509 wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame
* parentFrame
,
1510 wxNotebook
* theBook
,
1511 const wxString
& szBackend
)
1512 : wxPanel(theBook
, wxID_ANY
),
1516 m_bIsBeingDragged(false),
1517 m_parentFrame(parentFrame
)
1524 // [5 control buttons]
1530 // Create and attach a 2-column grid sizer
1532 wxFlexGridSizer
* sizer
= new wxFlexGridSizer(2);
1533 sizer
->AddGrowableCol(0);
1534 this->SetSizer(sizer
);
1537 // Create our media control
1539 m_mediactrl
= new wxMediaCtrl();
1541 // Make sure creation was successful
1542 bool bOK
= m_mediactrl
->Create(this, wxID_MEDIACTRL
, wxEmptyString
,
1543 wxDefaultPosition
, wxDefaultSize
, 0,
1544 // you could specify a macro backend here like
1545 // wxMEDIABACKEND_WMP10);
1546 // wxT("wxPDFMediaBackend"));
1548 // you could change the cursor here like
1549 // m_mediactrl->SetCursor(wxCURSOR_BLANK);
1550 // note that this may not effect it if SetPlayerControls
1551 // is set to something else than wxMEDIACTRLPLAYERCONTROLS_NONE
1552 wxASSERT_MSG(bOK
, wxT("Could not create media control!"));
1555 sizer
->Add(m_mediactrl
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1558 // Create the playlist/listctrl
1560 m_playlist
= new wxMediaPlayerListCtrl();
1561 m_playlist
->Create(this, wxID_LISTCTRL
, wxDefaultPosition
,
1563 wxLC_REPORT
// wxLC_LIST
1566 // Set the background of our listctrl to white
1567 m_playlist
->SetBackgroundColour(wxColour(255,255,255));
1569 // The layout of the headers of the listctrl are like
1570 // | | File | Length
1572 // Where Column one is a character representing the state the file is in:
1573 // * - not the current file
1574 // E - Error has occured
1575 // > - Currently Playing
1578 // (( - Volume Down 5%
1579 // )) - Volume Up 5%
1581 // Column two is the name of the file
1583 // Column three is the length in seconds of the file
1584 m_playlist
->InsertColumn(0,_(""), wxLIST_FORMAT_CENTER
, 20);
1585 m_playlist
->InsertColumn(1,_("File"), wxLIST_FORMAT_LEFT
, /*wxLIST_AUTOSIZE_USEHEADER*/305);
1586 m_playlist
->InsertColumn(2,_("Length"), wxLIST_FORMAT_CENTER
, 75);
1588 #if wxUSE_DRAG_AND_DROP
1589 m_playlist
->SetDropTarget(new wxPlayListDropTarget(*m_playlist
));
1592 sizer
->Add(m_playlist
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1595 // Create the control buttons
1596 // TODO/FIXME/HACK: This part about sizers is really a nice hack
1597 // and probably isn't proper
1599 wxBoxSizer
* horsizer1
= new wxBoxSizer(wxHORIZONTAL
);
1600 wxBoxSizer
* vertsizer
= new wxBoxSizer(wxHORIZONTAL
);
1602 m_prevButton
= new wxButton();
1603 m_playButton
= new wxButton();
1604 m_stopButton
= new wxButton();
1605 m_nextButton
= new wxButton();
1606 m_vdButton
= new wxButton();
1607 m_vuButton
= new wxButton();
1609 m_prevButton
->Create(this, wxID_BUTTONPREV
, wxT("|<"));
1610 m_prevButton
->SetToolTip("Previous");
1611 m_playButton
->Create(this, wxID_BUTTONPLAY
, wxT(">"));
1612 m_playButton
->SetToolTip("Play");
1613 m_stopButton
->Create(this, wxID_BUTTONSTOP
, wxT("[]"));
1614 m_stopButton
->SetToolTip("Stop");
1615 m_nextButton
->Create(this, wxID_BUTTONNEXT
, wxT(">|"));
1616 m_nextButton
->SetToolTip("Next");
1617 m_vdButton
->Create(this, wxID_BUTTONVD
, wxT("(("));
1618 m_vdButton
->SetToolTip("Volume down");
1619 m_vuButton
->Create(this, wxID_BUTTONVU
, wxT("))"));
1620 m_vuButton
->SetToolTip("Volume up");
1622 vertsizer
->Add(m_prevButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1623 vertsizer
->Add(m_playButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1624 vertsizer
->Add(m_stopButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1625 vertsizer
->Add(m_nextButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1626 vertsizer
->Add(m_vdButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1627 vertsizer
->Add(m_vuButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1628 horsizer1
->Add(vertsizer
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1629 sizer
->Add(horsizer1
, 0, wxALIGN_CENTER_VERTICAL
|wxALIGN_CENTER_HORIZONTAL
|wxALL
, 5);
1633 // Create our slider
1635 m_slider
= new wxSlider(this, wxID_SLIDER
, 0, // init
1638 wxDefaultPosition
, wxDefaultSize
,
1640 sizer
->Add(m_slider
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1645 m_gauge
= new wxGauge();
1646 m_gauge
->Create(this, wxID_GAUGE
, 0, wxDefaultPosition
, wxDefaultSize
,
1647 wxGA_HORIZONTAL
| wxGA_SMOOTH
);
1648 sizer
->Add(m_gauge
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1652 // Create the speed/volume sliders
1654 wxBoxSizer
* horsizer3
= new wxBoxSizer(wxHORIZONTAL
);
1656 m_volSlider
= new wxSlider(this, wxID_VOLSLIDER
, 100, // init
1659 wxDefaultPosition
, wxSize(250,20),
1661 horsizer3
->Add(m_volSlider
, 1, wxALL
, 5);
1663 m_pbSlider
= new wxSlider(this, wxID_PBSLIDER
, 4, // init
1666 wxDefaultPosition
, wxSize(250,20),
1668 horsizer3
->Add(m_pbSlider
, 1, wxALL
, 5);
1669 sizer
->Add(horsizer3
, 1, wxCENTRE
| wxALL
, 5);
1671 // Now that we have all our rows make some of them growable
1672 sizer
->AddGrowableRow(0);
1677 this->Connect( wxID_LISTCTRL
, wxEVT_COMMAND_LIST_ITEM_ACTIVATED
,
1678 wxListEventHandler(wxMediaPlayerFrame::OnChangeSong
),
1679 (wxObject
*)0, parentFrame
);
1684 this->Connect(wxID_SLIDER
, wxEVT_SCROLL_THUMBTRACK
,
1685 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnBeginSeek
));
1686 this->Connect(wxID_SLIDER
, wxEVT_SCROLL_THUMBRELEASE
,
1687 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnEndSeek
));
1688 this->Connect(wxID_PBSLIDER
, wxEVT_SCROLL_THUMBRELEASE
,
1689 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnPBChange
));
1690 this->Connect(wxID_VOLSLIDER
, wxEVT_SCROLL_THUMBRELEASE
,
1691 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnVolChange
));
1694 // Media Control events
1696 this->Connect(wxID_MEDIACTRL
, wxEVT_MEDIA_PLAY
,
1697 wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaPlay
));
1698 this->Connect(wxID_MEDIACTRL
, wxEVT_MEDIA_PAUSE
,
1699 wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaPause
));
1700 this->Connect(wxID_MEDIACTRL
, wxEVT_MEDIA_STOP
,
1701 wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaStop
));
1702 this->Connect(wxID_MEDIACTRL
, wxEVT_MEDIA_FINISHED
,
1703 wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaFinished
));
1704 this->Connect(wxID_MEDIACTRL
, wxEVT_MEDIA_LOADED
,
1705 wxMediaEventHandler(wxMediaPlayerFrame::OnMediaLoaded
),
1706 (wxObject
*)0, parentFrame
);
1711 this->Connect( wxID_BUTTONPREV
, wxEVT_COMMAND_BUTTON_CLICKED
,
1712 wxCommandEventHandler(wxMediaPlayerFrame::OnPrev
),
1713 (wxObject
*)0, parentFrame
);
1714 this->Connect( wxID_BUTTONPLAY
, wxEVT_COMMAND_BUTTON_CLICKED
,
1715 wxCommandEventHandler(wxMediaPlayerFrame::OnPlay
),
1716 (wxObject
*)0, parentFrame
);
1717 this->Connect( wxID_BUTTONSTOP
, wxEVT_COMMAND_BUTTON_CLICKED
,
1718 wxCommandEventHandler(wxMediaPlayerFrame::OnStop
),
1719 (wxObject
*)0, parentFrame
);
1720 this->Connect( wxID_BUTTONNEXT
, wxEVT_COMMAND_BUTTON_CLICKED
,
1721 wxCommandEventHandler(wxMediaPlayerFrame::OnNext
),
1722 (wxObject
*)0, parentFrame
);
1723 this->Connect( wxID_BUTTONVD
, wxEVT_COMMAND_BUTTON_CLICKED
,
1724 wxCommandEventHandler(wxMediaPlayerFrame::OnVolumeDown
),
1725 (wxObject
*)0, parentFrame
);
1726 this->Connect( wxID_BUTTONVU
, wxEVT_COMMAND_BUTTON_CLICKED
,
1727 wxCommandEventHandler(wxMediaPlayerFrame::OnVolumeUp
),
1728 (wxObject
*)0, parentFrame
);
1731 // ----------------------------------------------------------------------------
1732 // MyNotebook::OnBeginSeek
1734 // Sets m_bIsBeingDragged to true to stop the timer from changing the position
1736 // ----------------------------------------------------------------------------
1737 void wxMediaPlayerNotebookPage::OnBeginSeek(wxScrollEvent
& WXUNUSED(event
))
1739 m_bIsBeingDragged
= true;
1742 // ----------------------------------------------------------------------------
1743 // MyNotebook::OnEndSeek
1745 // Called from file->seek.
1746 // Called when the user moves the slider -
1747 // seeks to a position within the media
1748 // then sets m_bIsBeingDragged to false to ok the timer to change the position
1749 // ----------------------------------------------------------------------------
1750 void wxMediaPlayerNotebookPage::OnEndSeek(wxScrollEvent
& WXUNUSED(event
))
1752 if( m_mediactrl
->Seek(
1753 m_slider
->GetValue() * 1000
1754 ) == wxInvalidOffset
)
1755 wxMessageBox(wxT("Couldn't seek in movie!"));
1757 m_bIsBeingDragged
= false;
1760 // ----------------------------------------------------------------------------
1761 // wxMediaPlayerNotebookPage::IsBeingDragged
1763 // Returns true if the user is dragging the slider
1764 // ----------------------------------------------------------------------------
1765 bool wxMediaPlayerNotebookPage::IsBeingDragged()
1767 return m_bIsBeingDragged
;
1770 // ----------------------------------------------------------------------------
1771 // wxMediaPlayerNotebookPage::OnVolChange
1773 // Called when the user is done dragging the volume-changing slider
1774 // ----------------------------------------------------------------------------
1775 void wxMediaPlayerNotebookPage::OnVolChange(wxScrollEvent
& WXUNUSED(event
))
1777 if( m_mediactrl
->SetVolume(
1778 m_volSlider
->GetValue() / 100.0
1780 wxMessageBox(wxT("Couldn't set volume!"));
1784 // ----------------------------------------------------------------------------
1785 // wxMediaPlayerNotebookPage::OnPBChange
1787 // Called when the user is done dragging the speed-changing slider
1788 // ----------------------------------------------------------------------------
1789 void wxMediaPlayerNotebookPage::OnPBChange(wxScrollEvent
& WXUNUSED(event
))
1791 if( m_mediactrl
->SetPlaybackRate(
1792 m_pbSlider
->GetValue() * .25
1794 wxMessageBox(wxT("Couldn't set playbackrate!"));
1798 // ----------------------------------------------------------------------------
1799 // wxMediaPlayerNotebookPage::OnMediaPlay
1801 // Called when the media plays.
1802 // ----------------------------------------------------------------------------
1803 void wxMediaPlayerNotebookPage::OnMediaPlay(wxMediaEvent
& WXUNUSED(event
))
1805 m_playlist
->SetItem(m_nLastFileId
, 0, wxT(">"));
1808 // ----------------------------------------------------------------------------
1809 // wxMediaPlayerNotebookPage::OnMediaPause
1811 // Called when the media is paused.
1812 // ----------------------------------------------------------------------------
1813 void wxMediaPlayerNotebookPage::OnMediaPause(wxMediaEvent
& WXUNUSED(event
))
1815 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("||"));
1818 // ----------------------------------------------------------------------------
1819 // wxMediaPlayerNotebookPage::OnMediaStop
1821 // Called when the media stops.
1822 // ----------------------------------------------------------------------------
1823 void wxMediaPlayerNotebookPage::OnMediaStop(wxMediaEvent
& WXUNUSED(event
))
1825 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("[]"));
1828 // ----------------------------------------------------------------------------
1829 // wxMediaPlayerNotebookPage::OnMediaFinished
1831 // Called when the media finishes playing.
1832 // Here we loop it if the user wants to (has been selected from file menu)
1833 // ----------------------------------------------------------------------------
1834 void wxMediaPlayerNotebookPage::OnMediaFinished(wxMediaEvent
& WXUNUSED(event
))
1838 if ( !m_mediactrl
->Play() )
1840 wxMessageBox(wxT("Couldn't loop movie!"));
1841 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("E"));
1848 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("[]"));
1853 // End of MediaPlayer sample