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 // RN: I'm not sure why this is here - even minimal doesn't check for
80 // wxUSE_GUI. I may have added it myself though...
82 #error "This is a GUI sample"
85 #if !wxUSE_MEDIACTRL || !wxUSE_MENUS || !wxUSE_SLIDER || !wxUSE_TIMER || \
86 !wxUSE_NOTEBOOK || !wxUSE_LISTCTRL
87 #error "Not all required elements are enabled. Please modify setup.h!"
90 // ============================================================================
92 // ============================================================================
94 // ----------------------------------------------------------------------------
96 // ----------------------------------------------------------------------------
98 // IDs for the controls and the menu commands
103 wxID_OPENFILESAMEPAGE
,
104 wxID_OPENFILENEWPAGE
,
105 wxID_OPENURLSAMEPAGE
,
107 wxID_CLOSECURRENTPAGE
,
114 // wxID_STOP, [built-in to wxWidgets]
115 // wxID_ABOUT, [built-in to wxWidgets]
116 // wxID_EXIT, [built-in to wxWidgets]
133 // ----------------------------------------------------------------------------
135 // ----------------------------------------------------------------------------
137 class wxMediaPlayerApp
: public wxApp
141 virtual void MacOpenFile(const wxString
& fileName
);
144 virtual bool OnInit();
147 class wxMediaPlayerFrame
* m_frame
;
150 // ----------------------------------------------------------------------------
151 // wxMediaPlayerFrame
152 // ----------------------------------------------------------------------------
154 class wxMediaPlayerFrame
: public wxFrame
158 wxMediaPlayerFrame(const wxString
& title
);
159 ~wxMediaPlayerFrame();
161 // Menu event handlers
162 void OnQuit(wxCommandEvent
& event
);
163 void OnAbout(wxCommandEvent
& event
);
165 void OnOpenFileSamePage(wxCommandEvent
& event
);
166 void OnOpenFileNewPage(wxCommandEvent
& event
);
167 void OnOpenURLSamePage(wxCommandEvent
& event
);
168 void OnOpenURLNewPage(wxCommandEvent
& event
);
169 void OnCloseCurrentPage(wxCommandEvent
& event
);
171 void OnPlay(wxCommandEvent
& event
);
172 void OnPause(wxCommandEvent
& event
);
173 void OnStop(wxCommandEvent
& event
);
174 void OnNext(wxCommandEvent
& event
);
175 void OnPrev(wxCommandEvent
& event
);
176 void OnVolumeDown(wxCommandEvent
& event
);
177 void OnVolumeUp(wxCommandEvent
& event
);
179 void OnLoop(wxCommandEvent
& event
);
180 void OnShowInterface(wxCommandEvent
& event
);
182 void OnSelectBackend(wxCommandEvent
& event
);
184 // Key event handlers
185 void OnKeyDown(wxKeyEvent
& event
);
187 // Quickie for playing from command line
188 void AddToPlayList(const wxString
& szString
);
190 // ListCtrl event handlers
191 void OnChangeSong(wxListEvent
& event
);
193 // Media event handlers
194 void OnMediaLoaded(wxMediaEvent
& event
);
196 // Close event handlers
197 void OnClose(wxCloseEvent
& event
);
200 // Common open file code
201 void OpenFile(bool bNewPage
);
202 void OpenURL(bool bNewPage
);
203 void DoOpenFile(const wxString
& path
, bool bNewPage
);
204 void DoPlayFile(const wxString
& path
);
206 class wxMediaPlayerTimer
* m_timer
; // Timer to write info to status bar
207 wxNotebook
* m_notebook
; // Notebook containing our pages
209 // Maybe I should use more accessors, but for simplicity
210 // I'll allow the other classes access to our members
211 friend class wxMediaPlayerApp
;
212 friend class wxMediaPlayerNotebookPage
;
213 friend class wxMediaPlayerTimer
;
218 // ----------------------------------------------------------------------------
219 // wxMediaPlayerNotebookPage
220 // ----------------------------------------------------------------------------
222 class wxMediaPlayerNotebookPage
: public wxPanel
224 wxMediaPlayerNotebookPage(wxMediaPlayerFrame
* parentFrame
,
225 wxNotebook
* book
, const wxString
& be
= wxEmptyString
);
227 // Slider event handlers
228 void OnBeginSeek(wxScrollEvent
& event
);
229 void OnEndSeek(wxScrollEvent
& event
);
230 void OnPBChange(wxScrollEvent
& event
);
231 void OnVolChange(wxScrollEvent
& event
);
233 // Media event handlers
234 void OnMediaPlay(wxMediaEvent
& event
);
235 void OnMediaPause(wxMediaEvent
& event
);
236 void OnMediaStop(wxMediaEvent
& event
);
237 void OnMediaFinished(wxMediaEvent
& event
);
240 bool IsBeingDragged(); // accessor for m_bIsBeingDragged
242 // make wxMediaPlayerFrame able to access the private members
243 friend class wxMediaPlayerFrame
;
245 int m_nLastFileId
; // List ID of played file in listctrl
246 wxString m_szFile
; // Name of currently playing file/location
248 wxMediaCtrl
* m_mediactrl
; // Our media control
249 class wxMediaPlayerListCtrl
* m_playlist
; // Our playlist
250 wxSlider
* m_slider
; // The slider below our media control
251 wxSlider
* m_pbSlider
; // Lower-left slider for adjusting speed
252 wxSlider
* m_volSlider
; // Lower-right slider for adjusting volume
253 int m_nLoops
; // Number of times media has looped
254 bool m_bLoop
; // Whether we are looping or not
255 bool m_bIsBeingDragged
; // Whether the user is dragging the scroll bar
256 wxMediaPlayerFrame
* m_parentFrame
; // Main wxFrame of our sample
257 wxButton
* m_prevButton
; // Go to previous file button
258 wxButton
* m_playButton
; // Play/pause file button
259 wxButton
* m_stopButton
; // Stop playing file button
260 wxButton
* m_nextButton
; // Next file button
261 wxButton
* m_vdButton
; // Volume down button
262 wxButton
* m_vuButton
; // Volume up button
263 wxGauge
* m_gauge
; // Gauge to keep in line with slider
266 // ----------------------------------------------------------------------------
267 // wxMediaPlayerTimer
268 // ----------------------------------------------------------------------------
270 class wxMediaPlayerTimer
: public wxTimer
274 wxMediaPlayerTimer(wxMediaPlayerFrame
* frame
) {m_frame
= frame
;}
276 // Called each time the timer's timeout expires
279 wxMediaPlayerFrame
* m_frame
; // The wxMediaPlayerFrame
282 // ----------------------------------------------------------------------------
283 // wxMediaPlayerListCtrl
284 // ----------------------------------------------------------------------------
285 class wxMediaPlayerListCtrl
: public wxListCtrl
288 void AddToPlayList(const wxString
& szString
)
291 kNewItem
.SetAlign(wxLIST_FORMAT_LEFT
);
293 int nID
= this->GetItemCount();
295 kNewItem
.SetMask(wxLIST_MASK_DATA
);
296 kNewItem
.SetData(new wxString(szString
));
298 this->InsertItem(kNewItem
);
299 this->SetItem(nID
, 0, wxT("*"));
300 this->SetItem(nID
, 1, wxFileName(szString
).GetName());
304 kNewItem
.SetBackgroundColour(wxColour(192,192,192));
305 this->SetItem(kNewItem
);
309 void GetSelectedItem(wxListItem
& listitem
)
311 listitem
.SetMask(wxLIST_MASK_TEXT
| wxLIST_MASK_DATA
);
312 int nLast
= -1, nLastSelected
= -1;
313 while ((nLast
= this->GetNextItem(nLast
,
315 wxLIST_STATE_SELECTED
)) != -1)
317 listitem
.SetId(nLast
);
318 this->GetItem(listitem
);
319 if ((listitem
.GetState() & wxLIST_STATE_FOCUSED
) )
321 nLastSelected
= nLast
;
323 if (nLast
== -1 && nLastSelected
== -1)
325 listitem
.SetId(nLastSelected
== -1 ? nLast
: nLastSelected
);
326 this->GetItem(listitem
);
330 // ----------------------------------------------------------------------------
331 // wxPlayListDropTarget
333 // Drop target for playlist (i.e. allows users to drag a file from explorer into
334 // the playlist to add that file)
335 // ----------------------------------------------------------------------------
336 #if wxUSE_DRAG_AND_DROP
337 class wxPlayListDropTarget
: public wxFileDropTarget
340 wxPlayListDropTarget(wxMediaPlayerListCtrl
& list
) : m_list(list
) {}
341 ~wxPlayListDropTarget(){}
342 virtual bool OnDropFiles(wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
),
343 const wxArrayString
& files
)
345 for (size_t i
= 0; i
< files
.GetCount(); ++i
)
347 m_list
.AddToPlayList(files
[i
]);
351 wxMediaPlayerListCtrl
& m_list
;
355 // ============================================================================
359 // ============================================================================
361 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
365 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
367 // ----------------------------------------------------------------------------
368 // wxGetMediaStateText
370 // Converts a wxMediaCtrl state into something useful that we can display
372 // ----------------------------------------------------------------------------
373 const wxChar
* wxGetMediaStateText(int nState
)
377 case wxMEDIASTATE_PLAYING
:
378 return wxT("Playing");
379 case wxMEDIASTATE_STOPPED
:
380 return wxT("Stopped");
381 ///case wxMEDIASTATE_PAUSED:
383 return wxT("Paused");
387 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
391 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
393 // ----------------------------------------------------------------------------
394 // This sets up this wxApp as the global wxApp that gui calls in wxWidgets
395 // use. For example, if you were to be in windows and use a file dialog,
396 // wxWidgets would use wxTheApp->GetHInstance() which would get the instance
397 // handle of the application. These routines in wx _DO NOT_ check to see if
398 // the wxApp exists, and thus will crash the application if you try it.
400 // IMPLEMENT_APP does this, and also implements the platform-specific entry
401 // routine, such as main or WinMain(). Use IMPLEMENT_APP_NO_MAIN if you do
402 // not desire this behavior.
403 // ----------------------------------------------------------------------------
404 IMPLEMENT_APP(wxMediaPlayerApp
)
406 // ----------------------------------------------------------------------------
407 // wxMediaPlayerApp::OnInit
409 // Where execution starts - akin to a main or WinMain.
410 // 1) Create the frame and show it to the user
411 // 2) Process filenames from the commandline
412 // 3) return true specifying that we want execution to continue past OnInit
413 // ----------------------------------------------------------------------------
414 bool wxMediaPlayerApp::OnInit()
416 if ( !wxApp::OnInit() )
419 // SetAppName() lets wxConfig and others know where to write
420 SetAppName(wxT("wxMediaPlayer"));
422 wxMediaPlayerFrame
*frame
=
423 new wxMediaPlayerFrame(wxT("MediaPlayer wxWidgets Sample"));
426 #if wxUSE_CMDLINE_PARSER
428 // What this does is get all the command line arguments
429 // and treat each one as a file to put to the initial playlist
431 wxCmdLineEntryDesc cmdLineDesc
[2];
432 cmdLineDesc
[0].kind
= wxCMD_LINE_PARAM
;
433 cmdLineDesc
[0].shortName
= NULL
;
434 cmdLineDesc
[0].longName
= NULL
;
435 cmdLineDesc
[0].description
= "input files";
436 cmdLineDesc
[0].type
= wxCMD_LINE_VAL_STRING
;
437 cmdLineDesc
[0].flags
= wxCMD_LINE_PARAM_OPTIONAL
| wxCMD_LINE_PARAM_MULTIPLE
;
439 cmdLineDesc
[1].kind
= wxCMD_LINE_NONE
;
441 // gets the passed media files from cmd line
442 wxCmdLineParser
parser (cmdLineDesc
, argc
, argv
);
444 // get filenames from the commandline
445 if (parser
.Parse() == 0)
447 for (size_t paramNr
=0; paramNr
< parser
.GetParamCount(); ++paramNr
)
449 frame
->AddToPlayList((parser
.GetParam (paramNr
)));
451 wxCommandEvent
theEvent(wxEVT_COMMAND_MENU_SELECTED
, wxID_NEXT
);
452 frame
->AddPendingEvent(theEvent
);
461 void wxMediaPlayerApp::MacOpenFile(const wxString
& fileName
)
463 // Called when a user drags a file over our app
464 m_frame
->DoOpenFile(fileName
, true /* new page */);
469 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
471 // wxMediaPlayerFrame
473 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
475 // ----------------------------------------------------------------------------
476 // wxMediaPlayerFrame Constructor
478 // 1) Create our menus
479 // 2) Create our notebook control and add it to the frame
480 // 3) Create our status bar
481 // 4) Connect our events
482 // 5) Start our timer
483 // ----------------------------------------------------------------------------
485 wxMediaPlayerFrame::wxMediaPlayerFrame(const wxString
& title
)
486 : wxFrame(NULL
, wxID_ANY
, title
, wxDefaultPosition
, wxSize(600,600))
488 SetIcon(wxICON(sample
));
493 wxMenu
*fileMenu
= new wxMenu
;
494 wxMenu
*controlsMenu
= new wxMenu
;
495 wxMenu
*optionsMenu
= new wxMenu
;
496 wxMenu
*helpMenu
= new wxMenu
;
497 wxMenu
*debugMenu
= new wxMenu
;
499 fileMenu
->Append(wxID_OPENFILESAMEPAGE
, wxT("&Open File\tCtrl-Shift-O"),
500 wxT("Open a File in the current notebook page"));
501 fileMenu
->Append(wxID_OPENFILENEWPAGE
, wxT("&Open File in a new page"),
502 wxT("Open a File in a new notebook page"));
503 fileMenu
->Append(wxID_OPENURLSAMEPAGE
, wxT("&Open URL"),
504 wxT("Open a URL in the current notebook page"));
505 fileMenu
->Append(wxID_OPENURLNEWPAGE
, wxT("&Open URL in a new page"),
506 wxT("Open a URL in a new notebook page"));
507 fileMenu
->AppendSeparator();
508 fileMenu
->Append(wxID_CLOSECURRENTPAGE
, wxT("&Close Current Page\tCtrl-C"),
509 wxT("Close current notebook page"));
510 fileMenu
->AppendSeparator();
511 fileMenu
->Append(wxID_EXIT
,
513 wxT("Quit this program"));
515 controlsMenu
->Append(wxID_PLAY
, wxT("&Play/Pause\tCtrl-P"), wxT("Resume/Pause playback"));
516 controlsMenu
->Append(wxID_STOP
, wxT("&Stop\tCtrl-S"), wxT("Stop playback"));
517 controlsMenu
->AppendSeparator();
518 controlsMenu
->Append(wxID_PREV
, wxT("&Previous\tCtrl-B"), wxT("Go to previous track"));
519 controlsMenu
->Append(wxID_NEXT
, wxT("&Next\tCtrl-N"), wxT("Skip to next track"));
521 optionsMenu
->AppendCheckItem(wxID_LOOP
,
522 wxT("&Loop\tCtrl-L"),
523 wxT("Loop Selected Media"));
524 optionsMenu
->AppendCheckItem(wxID_SHOWINTERFACE
,
525 wxT("&Show Interface\tCtrl-I"),
526 wxT("Show wxMediaCtrl native controls"));
528 debugMenu
->Append(wxID_SELECTBACKEND
,
529 wxT("&Select Backend...\tCtrl-D"),
530 wxT("Select a backend manually"));
532 helpMenu
->Append(wxID_ABOUT
,
533 wxT("&About...\tF1"),
534 wxT("Show about dialog"));
537 wxMenuBar
*menuBar
= new wxMenuBar();
538 menuBar
->Append(fileMenu
, wxT("&File"));
539 menuBar
->Append(controlsMenu
, wxT("&Controls"));
540 menuBar
->Append(optionsMenu
, wxT("&Options"));
541 menuBar
->Append(debugMenu
, wxT("&Debug"));
542 menuBar
->Append(helpMenu
, wxT("&Help"));
546 // Create our notebook - using wxNotebook is luckily pretty
547 // simple and self-explanatory in most cases
549 m_notebook
= new wxNotebook(this, wxID_NOTEBOOK
);
552 // Create our status bar
555 // create a status bar just for fun (by default with 1 pane only)
557 #endif // wxUSE_STATUSBAR
562 // There are two ways in wxWidgets to use events -
563 // Message Maps and Connections.
565 // Message Maps are implemented by putting
566 // DECLARE_MESSAGE_MAP in your wxEvtHandler-derived
567 // class you want to use for events, such as wxMediaPlayerFrame.
569 // Then after your class declaration you put
570 // BEGIN_EVENT_TABLE(wxMediaPlayerFrame, wxFrame)
574 // Where wxMediaPlayerFrame is the class with the DECLARE_MESSAGE_MAP
575 // in it. EVT_XXX(XXX) are each of your handlers, such
576 // as EVT_MENU for menu events and the XXX inside
577 // is the parameters to the event macro - in the case
578 // of EVT_MENU the menu id and then the function to call.
580 // However, with wxEvtHandler::Connect you can avoid a
581 // global message map for your class and those annoying
582 // macros. You can also change the context in which
583 // the call the handler (more later).
585 // The downside is that due to the limitation that
586 // wxWidgets doesn't use templates in certain areas,
587 // You have to triple-cast the event function.
589 // There are five parameters to wxEvtHandler::Connect -
591 // The first is the id of the instance whose events
592 // you want to handle - i.e. a menu id for menus,
593 // a control id for controls (wxControl::GetId())
596 // The second is the event id. This is the same
597 // as the message maps (EVT_MENU) except prefixed
598 // with "wx" (wxEVT_MENU).
600 // The third is the function handler for the event -
601 // You need to cast it to the specific event handler
602 // type, then to a wxEventFunction, then to a
603 // wxObjectEventFunction - I.E.
604 // (wxObjectEventFunction)(wxEventFunction)
605 // (wxCommandEventFunction) &wxMediaPlayerFrame::MyHandler
607 // Or, you can use the new (2.5.5+) event handler
608 // conversion macros - for instance the above could
610 // wxCommandEventHandler(wxMediaPlayerFrame::MyHandler)
611 // pretty simple, eh?
613 // The fourth is an optional userdata param -
614 // this is of historical relevance only and is
615 // there only for backwards compatibility.
617 // The fifth is the context in which to call the
618 // handler - by default (this param is optional)
619 // this. For example in your event handler
620 // if you were to call "this->MyFunc()"
621 // it would literally do this->MyFunc. However,
622 // if you were to pass myHandler as the fifth
623 // parameter, for instance, you would _really_
624 // be calling myHandler->MyFunc, even though
625 // the compiler doesn't really know it.
631 this->Connect(wxID_EXIT
, wxEVT_COMMAND_MENU_SELECTED
,
632 wxCommandEventHandler(wxMediaPlayerFrame::OnQuit
));
634 this->Connect(wxID_ABOUT
, wxEVT_COMMAND_MENU_SELECTED
,
635 wxCommandEventHandler(wxMediaPlayerFrame::OnAbout
));
637 this->Connect(wxID_LOOP
, wxEVT_COMMAND_MENU_SELECTED
,
638 wxCommandEventHandler(wxMediaPlayerFrame::OnLoop
));
640 this->Connect(wxID_SHOWINTERFACE
, wxEVT_COMMAND_MENU_SELECTED
,
641 wxCommandEventHandler(wxMediaPlayerFrame::OnShowInterface
));
643 this->Connect(wxID_OPENFILENEWPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
644 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileNewPage
));
646 this->Connect(wxID_OPENFILESAMEPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
647 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileSamePage
));
649 this->Connect(wxID_OPENURLNEWPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
650 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLNewPage
));
652 this->Connect(wxID_OPENURLSAMEPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
653 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLSamePage
));
655 this->Connect(wxID_CLOSECURRENTPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
656 wxCommandEventHandler(wxMediaPlayerFrame::OnCloseCurrentPage
));
658 this->Connect(wxID_PLAY
, wxEVT_COMMAND_MENU_SELECTED
,
659 wxCommandEventHandler(wxMediaPlayerFrame::OnPlay
));
661 this->Connect(wxID_STOP
, wxEVT_COMMAND_MENU_SELECTED
,
662 wxCommandEventHandler(wxMediaPlayerFrame::OnStop
));
664 this->Connect(wxID_NEXT
, wxEVT_COMMAND_MENU_SELECTED
,
665 wxCommandEventHandler(wxMediaPlayerFrame::OnNext
));
667 this->Connect(wxID_PREV
, wxEVT_COMMAND_MENU_SELECTED
,
668 wxCommandEventHandler(wxMediaPlayerFrame::OnPrev
));
670 this->Connect(wxID_SELECTBACKEND
, wxEVT_COMMAND_MENU_SELECTED
,
671 wxCommandEventHandler(wxMediaPlayerFrame::OnSelectBackend
));
676 wxTheApp
->Connect(wxID_ANY
, wxEVT_KEY_DOWN
,
677 wxKeyEventHandler(wxMediaPlayerFrame::OnKeyDown
),
683 this->Connect(wxID_ANY
, wxEVT_CLOSE_WINDOW
,
684 wxCloseEventHandler(wxMediaPlayerFrame::OnClose
));
691 // Create an initial notebook page so the user has something
692 // to work with without having to go file->open every time :).
694 wxMediaPlayerNotebookPage
* page
=
695 new wxMediaPlayerNotebookPage(this, m_notebook
);
696 m_notebook
->AddPage(page
,
701 // Here we load the our configuration -
702 // in our case we load all the files that were left in
703 // the playlist the last time the user closed our application
705 // As an exercise to the reader try modifying it so that
706 // it properly loads the playlist for each page without
707 // conflicting (loading the same data) with the other ones.
710 wxString key
, outstring
;
711 for(int i
= 0; ; ++i
)
715 if(!conf
.Read(key
, &outstring
))
717 page
->m_playlist
->AddToPlayList(outstring
);
721 // Create a timer to update our status bar
723 m_timer
= new wxMediaPlayerTimer(this);
727 // ----------------------------------------------------------------------------
728 // wxMediaPlayerFrame Destructor
730 // 1) Deletes child objects implicitly
731 // 2) Delete our timer explicitly
732 // ----------------------------------------------------------------------------
733 wxMediaPlayerFrame::~wxMediaPlayerFrame()
735 // Shut down our timer
739 // Here we save our info to the registry or whatever
740 // mechanism the OS uses.
742 // This makes it so that when mediaplayer loads up again
743 // it restores the same files that were in the playlist
744 // this time, rather than the user manually re-adding them.
746 // We need to do conf->DeleteAll() here because by default
747 // the config still contains the same files as last time
748 // so we need to clear it before writing our new ones.
750 // TODO: Maybe you could add a menu option to the
751 // options menu to delete the configuration on exit -
752 // all you'd need to do is just remove everything after
753 // conf->DeleteAll() here
755 // As an exercise to the reader, try modifying this so
756 // that it saves the data for each notebook page
758 wxMediaPlayerListCtrl
* playlist
=
759 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetPage(0))->m_playlist
;
764 for(int i
= 0; i
< playlist
->GetItemCount(); ++i
)
766 wxString
* pData
= (wxString
*) playlist
->GetItemData(i
);
769 conf
.Write(s
, *(pData
));
774 // ----------------------------------------------------------------------------
775 // wxMediaPlayerFrame::OnClose
776 // ----------------------------------------------------------------------------
777 void wxMediaPlayerFrame::OnClose(wxCloseEvent
& event
)
779 event
.Skip(); // really close the frame
782 // ----------------------------------------------------------------------------
783 // wxMediaPlayerFrame::AddToPlayList
784 // ----------------------------------------------------------------------------
785 void wxMediaPlayerFrame::AddToPlayList(const wxString
& szString
)
787 wxMediaPlayerNotebookPage
* currentpage
=
788 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
790 currentpage
->m_playlist
->AddToPlayList(szString
);
793 // ----------------------------------------------------------------------------
794 // wxMediaPlayerFrame::OnQuit
796 // Called from file->quit.
797 // Closes this application.
798 // ----------------------------------------------------------------------------
799 void wxMediaPlayerFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
801 // true is to force the frame to close
805 // ----------------------------------------------------------------------------
806 // wxMediaPlayerFrame::OnAbout
808 // Called from help->about.
809 // Gets some info about this application.
810 // ----------------------------------------------------------------------------
811 void wxMediaPlayerFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
814 msg
.Printf( wxT("This is a test of wxMediaCtrl.\n\n")
816 wxT("Instructions:\n")
818 wxT("The top slider shows the current the current position, ")
819 wxT("which you can change by dragging and releasing it.\n")
821 wxT("The gauge (progress bar) shows the progress in ")
822 wxT("downloading data of the current file - it may always be ")
823 wxT("empty due to lack of support from the current backend.\n")
825 wxT("The lower-left slider controls the volume and the lower-")
826 wxT("right slider controls the playback rate/speed of the ")
829 wxT("Currently using: %s"), wxVERSION_STRING
);
831 wxMessageBox(msg
, wxT("About wxMediaCtrl test"),
832 wxOK
| wxICON_INFORMATION
, this);
835 // ----------------------------------------------------------------------------
836 // wxMediaPlayerFrame::OnLoop
838 // Called from file->loop.
839 // Changes the state of whether we want to loop or not.
840 // ----------------------------------------------------------------------------
841 void wxMediaPlayerFrame::OnLoop(wxCommandEvent
& WXUNUSED(event
))
843 wxMediaPlayerNotebookPage
* currentpage
=
844 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
846 currentpage
->m_bLoop
= !currentpage
->m_bLoop
;
849 // ----------------------------------------------------------------------------
850 // wxMediaPlayerFrame::OnLoop
852 // Called from file->loop.
853 // Changes the state of whether we want to loop or not.
854 // ----------------------------------------------------------------------------
855 void wxMediaPlayerFrame::OnShowInterface(wxCommandEvent
& event
)
857 wxMediaPlayerNotebookPage
* currentpage
=
858 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
860 if( !currentpage
->m_mediactrl
->ShowPlayerControls(event
.IsChecked() ?
861 wxMEDIACTRLPLAYERCONTROLS_DEFAULT
:
862 wxMEDIACTRLPLAYERCONTROLS_NONE
) )
864 // error - uncheck and warn user
865 wxMenuItem
* pSIItem
= GetMenuBar()->FindItem(wxID_SHOWINTERFACE
);
867 pSIItem
->Check(!event
.IsChecked());
869 if(event
.IsChecked())
870 wxMessageBox(wxT("Could not show player controls"));
872 wxMessageBox(wxT("Could not hide player controls"));
876 // ----------------------------------------------------------------------------
877 // wxMediaPlayerFrame::OnOpenFileSamePage
879 // Called from file->openfile.
880 // Opens and plays a media file in the current notebook page
881 // ----------------------------------------------------------------------------
882 void wxMediaPlayerFrame::OnOpenFileSamePage(wxCommandEvent
& WXUNUSED(event
))
887 // ----------------------------------------------------------------------------
888 // wxMediaPlayerFrame::OnOpenFileNewPage
890 // Called from file->openfileinnewpage.
891 // Opens and plays a media file in a new notebook page
892 // ----------------------------------------------------------------------------
893 void wxMediaPlayerFrame::OnOpenFileNewPage(wxCommandEvent
& WXUNUSED(event
))
898 // ----------------------------------------------------------------------------
899 // wxMediaPlayerFrame::OpenFile
901 // Opens a file dialog asking the user for a filename, then
902 // calls DoOpenFile which will add the file to the playlist and play it
903 // ----------------------------------------------------------------------------
904 void wxMediaPlayerFrame::OpenFile(bool bNewPage
)
906 wxFileDialog
fd(this);
908 if(fd
.ShowModal() == wxID_OK
)
910 DoOpenFile(fd
.GetPath(), bNewPage
);
914 // ----------------------------------------------------------------------------
915 // wxMediaPlayerFrame::DoOpenFile
917 // Adds the file to our playlist, selects it in the playlist,
918 // and then calls DoPlayFile to play it
919 // ----------------------------------------------------------------------------
920 void wxMediaPlayerFrame::DoOpenFile(const wxString
& path
, bool bNewPage
)
925 new wxMediaPlayerNotebookPage(this, m_notebook
),
930 wxMediaPlayerNotebookPage
* currentpage
=
931 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
933 if(currentpage
->m_nLastFileId
!= -1)
934 currentpage
->m_playlist
->SetItemState(currentpage
->m_nLastFileId
,
935 0, wxLIST_STATE_SELECTED
);
937 wxListItem newlistitem
;
938 newlistitem
.SetAlign(wxLIST_FORMAT_LEFT
);
942 newlistitem
.SetId(nID
= currentpage
->m_playlist
->GetItemCount());
943 newlistitem
.SetMask(wxLIST_MASK_DATA
| wxLIST_MASK_STATE
);
944 newlistitem
.SetState(wxLIST_STATE_SELECTED
);
945 newlistitem
.SetData(new wxString(path
));
947 currentpage
->m_playlist
->InsertItem(newlistitem
);
948 currentpage
->m_playlist
->SetItem(nID
, 0, wxT("*"));
949 currentpage
->m_playlist
->SetItem(nID
, 1, wxFileName(path
).GetName());
953 newlistitem
.SetBackgroundColour(wxColour(192,192,192));
954 currentpage
->m_playlist
->SetItem(newlistitem
);
960 // ----------------------------------------------------------------------------
961 // wxMediaPlayerFrame::DoPlayFile
963 // Pauses the file if its the currently playing file,
964 // otherwise it plays the file
965 // ----------------------------------------------------------------------------
966 void wxMediaPlayerFrame::DoPlayFile(const wxString
& path
)
968 wxMediaPlayerNotebookPage
* currentpage
=
969 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
972 currentpage
->m_playlist
->GetSelectedItem(listitem
);
974 if( ( listitem
.GetData() &&
975 currentpage
->m_nLastFileId
== listitem
.GetId() &&
976 currentpage
->m_szFile
.compare(path
) == 0 ) ||
977 ( !listitem
.GetData() &&
978 currentpage
->m_nLastFileId
!= -1 &&
979 currentpage
->m_szFile
.compare(path
) == 0)
982 if(currentpage
->m_mediactrl
->GetState() == wxMEDIASTATE_PLAYING
)
984 if( !currentpage
->m_mediactrl
->Pause() )
985 wxMessageBox(wxT("Couldn't pause movie!"));
989 if( !currentpage
->m_mediactrl
->Play() )
990 wxMessageBox(wxT("Couldn't play movie!"));
995 int nNewId
= listitem
.GetData() ? listitem
.GetId() :
996 currentpage
->m_playlist
->GetItemCount()-1;
997 m_notebook
->SetPageText(m_notebook
->GetSelection(),
998 wxFileName(path
).GetName());
1000 if(currentpage
->m_nLastFileId
!= -1)
1001 currentpage
->m_playlist
->SetItem(
1002 currentpage
->m_nLastFileId
, 0, wxT("*"));
1004 wxURI
uripath(path
);
1005 if( uripath
.IsReference() )
1007 if( !currentpage
->m_mediactrl
->Load(path
) )
1009 wxMessageBox(wxT("Couldn't load file!"));
1010 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("E"));
1014 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("O"));
1019 if( !currentpage
->m_mediactrl
->Load(uripath
) )
1021 wxMessageBox(wxT("Couldn't load URL!"));
1022 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("E"));
1026 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("O"));
1030 currentpage
->m_nLastFileId
= nNewId
;
1031 currentpage
->m_szFile
= path
;
1032 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
,
1033 1, wxFileName(path
).GetName());
1034 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
,
1039 // ----------------------------------------------------------------------------
1040 // wxMediaPlayerFrame::OnMediaLoaded
1042 // Called when the media is ready to be played - and does
1043 // so, also gets the length of media and shows that in the list control
1044 // ----------------------------------------------------------------------------
1045 void wxMediaPlayerFrame::OnMediaLoaded(wxMediaEvent
& WXUNUSED(evt
))
1047 wxMediaPlayerNotebookPage
* currentpage
=
1048 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1050 if( !currentpage
->m_mediactrl
->Play() )
1052 wxMessageBox(wxT("Couldn't play movie!"));
1053 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
, 0, wxT("E"));
1057 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
, 0, wxT(">"));
1063 // ----------------------------------------------------------------------------
1064 // wxMediaPlayerFrame::OnSelectBackend
1066 // Little debugging routine - enter the class name of a backend and it
1067 // will use that instead of letting wxMediaCtrl search the wxMediaBackend
1069 // ----------------------------------------------------------------------------
1070 void wxMediaPlayerFrame::OnSelectBackend(wxCommandEvent
& WXUNUSED(evt
))
1072 wxString sBackend
= wxGetTextFromUser(wxT("Enter backend to use"));
1074 if(sBackend
.empty() == false) // could have been cancelled by the user
1076 int sel
= m_notebook
->GetSelection();
1078 if (sel
!= wxNOT_FOUND
)
1080 m_notebook
->DeletePage(sel
);
1083 m_notebook
->AddPage(new wxMediaPlayerNotebookPage(this, m_notebook
,
1088 ((wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage())->m_szFile
,
1093 // ----------------------------------------------------------------------------
1094 // wxMediaPlayerFrame::OnOpenURLSamePage
1096 // Called from file->openurl.
1097 // Opens and plays a media file from a URL in the current notebook page
1098 // ----------------------------------------------------------------------------
1099 void wxMediaPlayerFrame::OnOpenURLSamePage(wxCommandEvent
& WXUNUSED(event
))
1104 // ----------------------------------------------------------------------------
1105 // wxMediaPlayerFrame::OnOpenURLNewPage
1107 // Called from file->openurlinnewpage.
1108 // Opens and plays a media file from a URL in a new notebook page
1109 // ----------------------------------------------------------------------------
1110 void wxMediaPlayerFrame::OnOpenURLNewPage(wxCommandEvent
& WXUNUSED(event
))
1115 // ----------------------------------------------------------------------------
1116 // wxMediaPlayerFrame::OpenURL
1118 // Just calls DoOpenFile with the url path - which calls DoPlayFile
1119 // which handles the real dirty work
1120 // ----------------------------------------------------------------------------
1121 void wxMediaPlayerFrame::OpenURL(bool bNewPage
)
1123 wxString sUrl
= wxGetTextFromUser(
1124 wxT("Enter the URL that has the movie to play")
1127 if(sUrl
.empty() == false) // could have been cancelled by user
1129 DoOpenFile(sUrl
, bNewPage
);
1133 // ----------------------------------------------------------------------------
1134 // wxMediaPlayerFrame::OnCloseCurrentPage
1136 // Called when the user wants to close the current notebook page
1138 // 1) Get the current page number (wxControl::GetSelection)
1139 // 2) If there is no current page, break out
1140 // 3) Delete the current page
1141 // ----------------------------------------------------------------------------
1142 void wxMediaPlayerFrame::OnCloseCurrentPage(wxCommandEvent
& WXUNUSED(event
))
1144 if( m_notebook
->GetPageCount() > 1 )
1146 int sel
= m_notebook
->GetSelection();
1148 if (sel
!= wxNOT_FOUND
)
1150 m_notebook
->DeletePage(sel
);
1155 wxMessageBox(wxT("Cannot close main page"));
1159 // ----------------------------------------------------------------------------
1160 // wxMediaPlayerFrame::OnPlay
1162 // Called from file->play.
1163 // Resumes the media if it is paused or stopped.
1164 // ----------------------------------------------------------------------------
1165 void wxMediaPlayerFrame::OnPlay(wxCommandEvent
& WXUNUSED(event
))
1167 wxMediaPlayerNotebookPage
* currentpage
=
1168 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1170 wxListItem listitem
;
1171 currentpage
->m_playlist
->GetSelectedItem(listitem
);
1172 if ( !listitem
.GetData() )
1175 if ((nLast
= currentpage
->m_playlist
->GetNextItem(nLast
,
1177 wxLIST_STATE_DONTCARE
)) == -1)
1180 wxMessageBox(wxT("No items in playlist!"));
1184 listitem
.SetId(nLast
);
1185 currentpage
->m_playlist
->GetItem(listitem
);
1186 listitem
.SetMask(listitem
.GetMask() | wxLIST_MASK_STATE
);
1187 listitem
.SetState(listitem
.GetState() | wxLIST_STATE_SELECTED
);
1188 currentpage
->m_playlist
->SetItem(listitem
);
1189 wxASSERT(listitem
.GetData());
1190 DoPlayFile((*((wxString
*) listitem
.GetData())));
1195 wxASSERT(listitem
.GetData());
1196 DoPlayFile((*((wxString
*) listitem
.GetData())));
1200 // ----------------------------------------------------------------------------
1201 // wxMediaPlayerFrame::OnKeyDown
1203 // Deletes all selected files from the playlist if the backspace key is pressed
1204 // ----------------------------------------------------------------------------
1205 void wxMediaPlayerFrame::OnKeyDown(wxKeyEvent
& event
)
1207 if(event
.GetKeyCode() == WXK_BACK
/*DELETE*/)
1209 wxMediaPlayerNotebookPage
* currentpage
=
1210 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1211 // delete all selected items
1214 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(
1215 -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1216 if (nSelectedItem
== -1)
1219 wxListItem listitem
;
1220 listitem
.SetId(nSelectedItem
);
1221 currentpage
->m_playlist
->GetItem(listitem
);
1222 delete (wxString
*) listitem
.GetData();
1224 currentpage
->m_playlist
->DeleteItem(nSelectedItem
);
1228 // Could be wxGetTextFromUser or something else important
1229 if(event
.GetEventObject() != this)
1233 // ----------------------------------------------------------------------------
1234 // wxMediaPlayerFrame::OnStop
1236 // Called from file->stop.
1237 // Where it stops depends on whether you can seek in the
1238 // media control or not - if you can it stops and seeks to the beginning,
1239 // otherwise it will appear to be at the end - but it will start over again
1240 // when Play() is called
1241 // ----------------------------------------------------------------------------
1242 void wxMediaPlayerFrame::OnStop(wxCommandEvent
& WXUNUSED(evt
))
1244 wxMediaPlayerNotebookPage
* currentpage
=
1245 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1247 if( !currentpage
->m_mediactrl
->Stop() )
1248 wxMessageBox(wxT("Couldn't stop movie!"));
1250 currentpage
->m_playlist
->SetItem(
1251 currentpage
->m_nLastFileId
, 0, wxT("[]"));
1255 // ----------------------------------------------------------------------------
1256 // wxMediaPlayerFrame::OnChangeSong
1258 // Routine that plays the currently selected file in the playlist.
1259 // Called when the user actives the song from the playlist,
1260 // and from other various places in the sample
1261 // ----------------------------------------------------------------------------
1262 void wxMediaPlayerFrame::OnChangeSong(wxListEvent
& WXUNUSED(evt
))
1264 wxMediaPlayerNotebookPage
* currentpage
=
1265 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1267 wxListItem listitem
;
1268 currentpage
->m_playlist
->GetSelectedItem(listitem
);
1269 if(listitem
.GetData())
1270 DoPlayFile((*((wxString
*) listitem
.GetData())));
1272 wxMessageBox(wxT("No selected item!"));
1275 // ----------------------------------------------------------------------------
1276 // wxMediaPlayerFrame::OnPrev
1278 // Tedious wxListCtrl stuff. Goes to prevous song in list, or if at the
1279 // beginning goes to the last in the list.
1280 // ----------------------------------------------------------------------------
1281 void wxMediaPlayerFrame::OnPrev(wxCommandEvent
& WXUNUSED(event
))
1283 wxMediaPlayerNotebookPage
* currentpage
=
1284 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1286 if (currentpage
->m_playlist
->GetItemCount() == 0)
1289 wxInt32 nLastSelectedItem
= -1;
1292 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(nLastSelectedItem
,
1293 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1294 if (nSelectedItem
== -1)
1296 nLastSelectedItem
= nSelectedItem
;
1297 currentpage
->m_playlist
->SetItemState(nSelectedItem
, 0, wxLIST_STATE_SELECTED
);
1300 if (nLastSelectedItem
== -1)
1302 // nothing selected, default to the file before the currently playing one
1303 if(currentpage
->m_nLastFileId
== 0)
1304 nLastSelectedItem
= currentpage
->m_playlist
->GetItemCount() - 1;
1306 nLastSelectedItem
= currentpage
->m_nLastFileId
- 1;
1308 else if (nLastSelectedItem
== 0)
1309 nLastSelectedItem
= currentpage
->m_playlist
->GetItemCount() - 1;
1311 nLastSelectedItem
-= 1;
1313 if(nLastSelectedItem
== currentpage
->m_nLastFileId
)
1314 return; // already playing... nothing to do
1316 wxListItem listitem
;
1317 listitem
.SetId(nLastSelectedItem
);
1318 listitem
.SetMask(wxLIST_MASK_TEXT
| wxLIST_MASK_DATA
);
1319 currentpage
->m_playlist
->GetItem(listitem
);
1320 listitem
.SetMask(listitem
.GetMask() | wxLIST_MASK_STATE
);
1321 listitem
.SetState(listitem
.GetState() | wxLIST_STATE_SELECTED
);
1322 currentpage
->m_playlist
->SetItem(listitem
);
1324 wxASSERT(listitem
.GetData());
1325 DoPlayFile((*((wxString
*) listitem
.GetData())));
1328 // ----------------------------------------------------------------------------
1329 // wxMediaPlayerFrame::OnNext
1331 // Tedious wxListCtrl stuff. Goes to next song in list, or if at the
1332 // end goes to the first in the list.
1333 // ----------------------------------------------------------------------------
1334 void wxMediaPlayerFrame::OnNext(wxCommandEvent
& WXUNUSED(event
))
1336 wxMediaPlayerNotebookPage
* currentpage
=
1337 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1339 if (currentpage
->m_playlist
->GetItemCount() == 0)
1342 wxInt32 nLastSelectedItem
= -1;
1345 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(nLastSelectedItem
,
1346 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1347 if (nSelectedItem
== -1)
1349 nLastSelectedItem
= nSelectedItem
;
1350 currentpage
->m_playlist
->SetItemState(nSelectedItem
, 0, wxLIST_STATE_SELECTED
);
1353 if (nLastSelectedItem
== -1)
1355 if(currentpage
->m_nLastFileId
== currentpage
->m_playlist
->GetItemCount() - 1)
1356 nLastSelectedItem
= 0;
1358 nLastSelectedItem
= currentpage
->m_nLastFileId
+ 1;
1360 else if (nLastSelectedItem
== currentpage
->m_playlist
->GetItemCount() - 1)
1361 nLastSelectedItem
= 0;
1363 nLastSelectedItem
+= 1;
1365 if(nLastSelectedItem
== currentpage
->m_nLastFileId
)
1366 return; // already playing... nothing to do
1368 wxListItem listitem
;
1369 listitem
.SetMask(wxLIST_MASK_TEXT
| wxLIST_MASK_DATA
);
1370 listitem
.SetId(nLastSelectedItem
);
1371 currentpage
->m_playlist
->GetItem(listitem
);
1372 listitem
.SetMask(listitem
.GetMask() | wxLIST_MASK_STATE
);
1373 listitem
.SetState(listitem
.GetState() | wxLIST_STATE_SELECTED
);
1374 currentpage
->m_playlist
->SetItem(listitem
);
1376 wxASSERT(listitem
.GetData());
1377 DoPlayFile((*((wxString
*) listitem
.GetData())));
1381 // ----------------------------------------------------------------------------
1382 // wxMediaPlayerFrame::OnVolumeDown
1384 // Lowers the volume of the media control by 5%
1385 // ----------------------------------------------------------------------------
1386 void wxMediaPlayerFrame::OnVolumeDown(wxCommandEvent
& WXUNUSED(event
))
1388 wxMediaPlayerNotebookPage
* currentpage
=
1389 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1391 double dVolume
= currentpage
->m_mediactrl
->GetVolume();
1392 currentpage
->m_mediactrl
->SetVolume(dVolume
< 0.05 ? 0.0 : dVolume
- .05);
1395 // ----------------------------------------------------------------------------
1396 // wxMediaPlayerFrame::OnVolumeUp
1398 // Increases the volume of the media control by 5%
1399 // ----------------------------------------------------------------------------
1400 void wxMediaPlayerFrame::OnVolumeUp(wxCommandEvent
& WXUNUSED(event
))
1402 wxMediaPlayerNotebookPage
* currentpage
=
1403 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1405 double dVolume
= currentpage
->m_mediactrl
->GetVolume();
1406 currentpage
->m_mediactrl
->SetVolume(dVolume
> 0.95 ? 1.0 : dVolume
+ .05);
1409 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1411 // wxMediaPlayerTimer
1413 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1415 // ----------------------------------------------------------------------------
1416 // wxMediaPlayerTimer::Notify
1418 // 1) Updates media information on the status bar
1419 // 2) Sets the max/min length of the slider and guage
1421 // Note that the reason we continually do this and don't cache it is because
1422 // some backends such as GStreamer are dynamic change values all the time
1423 // and often don't have things like duration or video size available
1424 // until the media is actually being played
1425 // ----------------------------------------------------------------------------
1426 void wxMediaPlayerTimer::Notify()
1428 wxMediaPlayerNotebookPage
* currentpage
=
1429 (wxMediaPlayerNotebookPage
*) m_frame
->m_notebook
->GetCurrentPage();
1430 wxMediaCtrl
* currentMediaCtrl
= currentpage
->m_mediactrl
;
1432 // Number of minutes/seconds total
1433 wxLongLong llLength
= currentpage
->m_mediactrl
->Length();
1434 int nMinutes
= (int) (llLength
/ 60000).GetValue();
1435 int nSeconds
= (int) ((llLength
% 60000)/1000).GetValue();
1437 // Duration string (i.e. MM:SS)
1439 sDuration
.Printf(wxT("%2i:%02i"), nMinutes
, nSeconds
);
1442 // Number of minutes/seconds total
1443 wxLongLong llTell
= currentpage
->m_mediactrl
->Tell();
1444 nMinutes
= (int) (llTell
/ 60000).GetValue();
1445 nSeconds
= (int) ((llTell
% 60000)/1000).GetValue();
1447 // Position string (i.e. MM:SS)
1449 sPosition
.Printf(wxT("%2i:%02i"), nMinutes
, nSeconds
);
1452 // Set the third item in the listctrl entry to the duration string
1453 if(currentpage
->m_nLastFileId
>= 0)
1454 currentpage
->m_playlist
->SetItem(
1455 currentpage
->m_nLastFileId
, 2, sDuration
);
1457 // Setup the slider and gauge min/max values
1458 currentpage
->m_slider
->SetRange(0, (int)(llLength
/ 1000).GetValue());
1459 currentpage
->m_gauge
->SetRange(100);
1462 // if the slider is not being dragged then update it with the song position
1463 if(currentpage
->IsBeingDragged() == false)
1464 currentpage
->m_slider
->SetValue((long)(llTell
/ 1000).GetValue());
1467 // Update the gauge with the download progress
1468 wxLongLong llDownloadProgress
=
1469 currentpage
->m_mediactrl
->GetDownloadProgress();
1470 wxLongLong llDownloadTotal
=
1471 currentpage
->m_mediactrl
->GetDownloadTotal();
1473 if(llDownloadTotal
.GetValue() != 0)
1475 currentpage
->m_gauge
->SetValue(
1476 (int) ((llDownloadProgress
* 100) / llDownloadTotal
).GetValue()
1480 // GetBestSize holds the original video size
1481 wxSize videoSize
= currentMediaCtrl
->GetBestSize();
1483 // Now the big part - set the status bar text to
1484 // hold various metadata about the media
1486 m_frame
->SetStatusText(wxString::Format(
1487 wxT("Size(x,y):%i,%i ")
1488 wxT("Position:%s/%s Speed:%1.1fx ")
1489 wxT("State:%s Loops:%i D/T:[%i]/[%i] V:%i%%"),
1494 currentMediaCtrl
->GetPlaybackRate(),
1495 wxGetMediaStateText(currentpage
->m_mediactrl
->GetState()),
1496 currentpage
->m_nLoops
,
1497 (int)llDownloadProgress
.GetValue(),
1498 (int)llDownloadTotal
.GetValue(),
1499 (int)(currentpage
->m_mediactrl
->GetVolume() * 100)));
1500 #endif // wxUSE_STATUSBAR
1503 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1505 // wxMediaPlayerNotebookPage
1507 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1509 // ----------------------------------------------------------------------------
1510 // wxMediaPlayerNotebookPage Constructor
1512 // Creates a media control and slider and adds it to this panel,
1513 // along with some sizers for positioning
1514 // ----------------------------------------------------------------------------
1515 wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame
* parentFrame
,
1516 wxNotebook
* theBook
,
1517 const wxString
& szBackend
)
1518 : wxPanel(theBook
, wxID_ANY
),
1522 m_bIsBeingDragged(false),
1523 m_parentFrame(parentFrame
)
1530 // [5 control buttons]
1536 // Create and attach a 2-column grid sizer
1538 wxFlexGridSizer
* sizer
= new wxFlexGridSizer(2);
1539 sizer
->AddGrowableCol(0);
1540 this->SetSizer(sizer
);
1543 // Create our media control
1545 m_mediactrl
= new wxMediaCtrl();
1547 // Make sure creation was successful
1548 bool bOK
= m_mediactrl
->Create(this, wxID_MEDIACTRL
, wxEmptyString
,
1549 wxDefaultPosition
, wxDefaultSize
, 0,
1550 // you could specify a macro backend here like
1551 // wxMEDIABACKEND_WMP10);
1552 // wxT("wxPDFMediaBackend"));
1554 // you could change the cursor here like
1555 // m_mediactrl->SetCursor(wxCURSOR_BLANK);
1556 // note that this may not effect it if SetPlayerControls
1557 // is set to something else than wxMEDIACTRLPLAYERCONTROLS_NONE
1558 wxASSERT_MSG(bOK
, wxT("Could not create media control!"));
1561 sizer
->Add(m_mediactrl
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1564 // Create the playlist/listctrl
1566 m_playlist
= new wxMediaPlayerListCtrl();
1567 m_playlist
->Create(this, wxID_LISTCTRL
, wxDefaultPosition
,
1569 wxLC_REPORT
// wxLC_LIST
1572 // Set the background of our listctrl to white
1573 m_playlist
->SetBackgroundColour(wxColour(255,255,255));
1575 // The layout of the headers of the listctrl are like
1576 // | | File | Length
1578 // Where Column one is a character representing the state the file is in:
1579 // * - not the current file
1580 // E - Error has occured
1581 // > - Currently Playing
1584 // (( - Volume Down 5%
1585 // )) - Volume Up 5%
1587 // Column two is the name of the file
1589 // Column three is the length in seconds of the file
1590 m_playlist
->InsertColumn(0,_(""), wxLIST_FORMAT_CENTER
, 20);
1591 m_playlist
->InsertColumn(1,_("File"), wxLIST_FORMAT_LEFT
, /*wxLIST_AUTOSIZE_USEHEADER*/305);
1592 m_playlist
->InsertColumn(2,_("Length"), wxLIST_FORMAT_CENTER
, 75);
1594 #if wxUSE_DRAG_AND_DROP
1595 m_playlist
->SetDropTarget(new wxPlayListDropTarget(*m_playlist
));
1598 sizer
->Add(m_playlist
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1601 // Create the control buttons
1602 // TODO/FIXME/HACK: This part about sizers is really a nice hack
1603 // and probably isn't proper
1605 wxBoxSizer
* horsizer1
= new wxBoxSizer(wxHORIZONTAL
);
1606 wxBoxSizer
* vertsizer
= new wxBoxSizer(wxHORIZONTAL
);
1608 m_prevButton
= new wxButton();
1609 m_playButton
= new wxButton();
1610 m_stopButton
= new wxButton();
1611 m_nextButton
= new wxButton();
1612 m_vdButton
= new wxButton();
1613 m_vuButton
= new wxButton();
1615 m_prevButton
->Create(this, wxID_BUTTONPREV
, wxT("|<"));
1616 m_prevButton
->SetToolTip("Previous");
1617 m_playButton
->Create(this, wxID_BUTTONPLAY
, wxT(">"));
1618 m_playButton
->SetToolTip("Play");
1619 m_stopButton
->Create(this, wxID_BUTTONSTOP
, wxT("[]"));
1620 m_stopButton
->SetToolTip("Stop");
1621 m_nextButton
->Create(this, wxID_BUTTONNEXT
, wxT(">|"));
1622 m_nextButton
->SetToolTip("Next");
1623 m_vdButton
->Create(this, wxID_BUTTONVD
, wxT("(("));
1624 m_vdButton
->SetToolTip("Volume down");
1625 m_vuButton
->Create(this, wxID_BUTTONVU
, wxT("))"));
1626 m_vuButton
->SetToolTip("Volume up");
1628 vertsizer
->Add(m_prevButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1629 vertsizer
->Add(m_playButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1630 vertsizer
->Add(m_stopButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1631 vertsizer
->Add(m_nextButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1632 vertsizer
->Add(m_vdButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1633 vertsizer
->Add(m_vuButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1634 horsizer1
->Add(vertsizer
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1635 sizer
->Add(horsizer1
, 0, wxALIGN_CENTER_VERTICAL
|wxALIGN_CENTER_HORIZONTAL
|wxALL
, 5);
1639 // Create our slider
1641 m_slider
= new wxSlider(this, wxID_SLIDER
, 0, // init
1644 wxDefaultPosition
, wxDefaultSize
,
1646 sizer
->Add(m_slider
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1651 m_gauge
= new wxGauge();
1652 m_gauge
->Create(this, wxID_GAUGE
, 0, wxDefaultPosition
, wxDefaultSize
,
1653 wxGA_HORIZONTAL
| wxGA_SMOOTH
);
1654 sizer
->Add(m_gauge
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1658 // Create the speed/volume sliders
1660 wxBoxSizer
* horsizer3
= new wxBoxSizer(wxHORIZONTAL
);
1662 m_volSlider
= new wxSlider(this, wxID_VOLSLIDER
, 100, // init
1665 wxDefaultPosition
, wxSize(250,20),
1667 horsizer3
->Add(m_volSlider
, 1, wxALL
, 5);
1669 m_pbSlider
= new wxSlider(this, wxID_PBSLIDER
, 4, // init
1672 wxDefaultPosition
, wxSize(250,20),
1674 horsizer3
->Add(m_pbSlider
, 1, wxALL
, 5);
1675 sizer
->Add(horsizer3
, 1, wxCENTRE
| wxALL
, 5);
1677 // Now that we have all our rows make some of them growable
1678 sizer
->AddGrowableRow(0);
1683 this->Connect( wxID_LISTCTRL
, wxEVT_COMMAND_LIST_ITEM_ACTIVATED
,
1684 wxListEventHandler(wxMediaPlayerFrame::OnChangeSong
),
1685 (wxObject
*)0, parentFrame
);
1690 this->Connect(wxID_SLIDER
, wxEVT_SCROLL_THUMBTRACK
,
1691 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnBeginSeek
));
1692 this->Connect(wxID_SLIDER
, wxEVT_SCROLL_THUMBRELEASE
,
1693 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnEndSeek
));
1694 this->Connect(wxID_PBSLIDER
, wxEVT_SCROLL_THUMBRELEASE
,
1695 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnPBChange
));
1696 this->Connect(wxID_VOLSLIDER
, wxEVT_SCROLL_THUMBRELEASE
,
1697 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnVolChange
));
1700 // Media Control events
1702 this->Connect(wxID_MEDIACTRL
, wxEVT_MEDIA_PLAY
,
1703 wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaPlay
));
1704 this->Connect(wxID_MEDIACTRL
, wxEVT_MEDIA_PAUSE
,
1705 wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaPause
));
1706 this->Connect(wxID_MEDIACTRL
, wxEVT_MEDIA_STOP
,
1707 wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaStop
));
1708 this->Connect(wxID_MEDIACTRL
, wxEVT_MEDIA_FINISHED
,
1709 wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaFinished
));
1710 this->Connect(wxID_MEDIACTRL
, wxEVT_MEDIA_LOADED
,
1711 wxMediaEventHandler(wxMediaPlayerFrame::OnMediaLoaded
),
1712 (wxObject
*)0, parentFrame
);
1717 this->Connect( wxID_BUTTONPREV
, wxEVT_COMMAND_BUTTON_CLICKED
,
1718 wxCommandEventHandler(wxMediaPlayerFrame::OnPrev
),
1719 (wxObject
*)0, parentFrame
);
1720 this->Connect( wxID_BUTTONPLAY
, wxEVT_COMMAND_BUTTON_CLICKED
,
1721 wxCommandEventHandler(wxMediaPlayerFrame::OnPlay
),
1722 (wxObject
*)0, parentFrame
);
1723 this->Connect( wxID_BUTTONSTOP
, wxEVT_COMMAND_BUTTON_CLICKED
,
1724 wxCommandEventHandler(wxMediaPlayerFrame::OnStop
),
1725 (wxObject
*)0, parentFrame
);
1726 this->Connect( wxID_BUTTONNEXT
, wxEVT_COMMAND_BUTTON_CLICKED
,
1727 wxCommandEventHandler(wxMediaPlayerFrame::OnNext
),
1728 (wxObject
*)0, parentFrame
);
1729 this->Connect( wxID_BUTTONVD
, wxEVT_COMMAND_BUTTON_CLICKED
,
1730 wxCommandEventHandler(wxMediaPlayerFrame::OnVolumeDown
),
1731 (wxObject
*)0, parentFrame
);
1732 this->Connect( wxID_BUTTONVU
, wxEVT_COMMAND_BUTTON_CLICKED
,
1733 wxCommandEventHandler(wxMediaPlayerFrame::OnVolumeUp
),
1734 (wxObject
*)0, parentFrame
);
1737 // ----------------------------------------------------------------------------
1738 // MyNotebook::OnBeginSeek
1740 // Sets m_bIsBeingDragged to true to stop the timer from changing the position
1742 // ----------------------------------------------------------------------------
1743 void wxMediaPlayerNotebookPage::OnBeginSeek(wxScrollEvent
& WXUNUSED(event
))
1745 m_bIsBeingDragged
= true;
1748 // ----------------------------------------------------------------------------
1749 // MyNotebook::OnEndSeek
1751 // Called from file->seek.
1752 // Called when the user moves the slider -
1753 // seeks to a position within the media
1754 // then sets m_bIsBeingDragged to false to ok the timer to change the position
1755 // ----------------------------------------------------------------------------
1756 void wxMediaPlayerNotebookPage::OnEndSeek(wxScrollEvent
& WXUNUSED(event
))
1758 if( m_mediactrl
->Seek(
1759 m_slider
->GetValue() * 1000
1760 ) == wxInvalidOffset
)
1761 wxMessageBox(wxT("Couldn't seek in movie!"));
1763 m_bIsBeingDragged
= false;
1766 // ----------------------------------------------------------------------------
1767 // wxMediaPlayerNotebookPage::IsBeingDragged
1769 // Returns true if the user is dragging the slider
1770 // ----------------------------------------------------------------------------
1771 bool wxMediaPlayerNotebookPage::IsBeingDragged()
1773 return m_bIsBeingDragged
;
1776 // ----------------------------------------------------------------------------
1777 // wxMediaPlayerNotebookPage::OnVolChange
1779 // Called when the user is done dragging the volume-changing slider
1780 // ----------------------------------------------------------------------------
1781 void wxMediaPlayerNotebookPage::OnVolChange(wxScrollEvent
& WXUNUSED(event
))
1783 if( m_mediactrl
->SetVolume(
1784 m_volSlider
->GetValue() / 100.0
1786 wxMessageBox(wxT("Couldn't set volume!"));
1790 // ----------------------------------------------------------------------------
1791 // wxMediaPlayerNotebookPage::OnPBChange
1793 // Called when the user is done dragging the speed-changing slider
1794 // ----------------------------------------------------------------------------
1795 void wxMediaPlayerNotebookPage::OnPBChange(wxScrollEvent
& WXUNUSED(event
))
1797 if( m_mediactrl
->SetPlaybackRate(
1798 m_pbSlider
->GetValue() * .25
1800 wxMessageBox(wxT("Couldn't set playbackrate!"));
1804 // ----------------------------------------------------------------------------
1805 // wxMediaPlayerNotebookPage::OnMediaPlay
1807 // Called when the media plays.
1808 // ----------------------------------------------------------------------------
1809 void wxMediaPlayerNotebookPage::OnMediaPlay(wxMediaEvent
& WXUNUSED(event
))
1811 m_playlist
->SetItem(m_nLastFileId
, 0, wxT(">"));
1814 // ----------------------------------------------------------------------------
1815 // wxMediaPlayerNotebookPage::OnMediaPause
1817 // Called when the media is paused.
1818 // ----------------------------------------------------------------------------
1819 void wxMediaPlayerNotebookPage::OnMediaPause(wxMediaEvent
& WXUNUSED(event
))
1821 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("||"));
1824 // ----------------------------------------------------------------------------
1825 // wxMediaPlayerNotebookPage::OnMediaStop
1827 // Called when the media stops.
1828 // ----------------------------------------------------------------------------
1829 void wxMediaPlayerNotebookPage::OnMediaStop(wxMediaEvent
& WXUNUSED(event
))
1831 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("[]"));
1834 // ----------------------------------------------------------------------------
1835 // wxMediaPlayerNotebookPage::OnMediaFinished
1837 // Called when the media finishes playing.
1838 // Here we loop it if the user wants to (has been selected from file menu)
1839 // ----------------------------------------------------------------------------
1840 void wxMediaPlayerNotebookPage::OnMediaFinished(wxMediaEvent
& WXUNUSED(event
))
1844 if ( !m_mediactrl
->Play() )
1846 wxMessageBox(wxT("Couldn't loop movie!"));
1847 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("E"));
1854 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("[]"));
1859 // End of MediaPlayer sample