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
70 // Under MSW we have several different backends but when linking statically
71 // they may be discarded by the linker (this definitely happens with MSVC) so
72 // force linking them. You don't have to do this in your code if you don't plan
73 // to use them, of course.
74 #if defined(__WXMSW__) && !defined(WXUSINGDLL)
76 wxFORCE_LINK_MODULE(wxmediabackend_am
)
77 wxFORCE_LINK_MODULE(wxmediabackend_qt
)
78 wxFORCE_LINK_MODULE(wxmediabackend_wmp10
)
79 #endif // static wxMSW build
82 #include "../sample.xpm"
85 // ----------------------------------------------------------------------------
86 // Bail out if the user doesn't want one of the
88 // ----------------------------------------------------------------------------
90 #if !wxUSE_MEDIACTRL || !wxUSE_MENUS || !wxUSE_SLIDER || !wxUSE_TIMER || \
91 !wxUSE_NOTEBOOK || !wxUSE_LISTCTRL
92 #error "Not all required elements are enabled. Please modify setup.h!"
95 // ============================================================================
97 // ============================================================================
99 // ----------------------------------------------------------------------------
101 // ----------------------------------------------------------------------------
103 // IDs for the controls and the menu commands
108 wxID_OPENFILESAMEPAGE
,
109 wxID_OPENFILENEWPAGE
,
110 wxID_OPENURLSAMEPAGE
,
112 wxID_CLOSECURRENTPAGE
,
119 // wxID_STOP, [built-in to wxWidgets]
120 // wxID_ABOUT, [built-in to wxWidgets]
121 // wxID_EXIT, [built-in to wxWidgets]
138 // ----------------------------------------------------------------------------
140 // ----------------------------------------------------------------------------
142 class wxMediaPlayerApp
: public wxApp
146 virtual void MacOpenFile(const wxString
& fileName
);
149 virtual bool OnInit();
152 class wxMediaPlayerFrame
* m_frame
;
155 // ----------------------------------------------------------------------------
156 // wxMediaPlayerFrame
157 // ----------------------------------------------------------------------------
159 class wxMediaPlayerFrame
: public wxFrame
163 wxMediaPlayerFrame(const wxString
& title
);
164 ~wxMediaPlayerFrame();
166 // Menu event handlers
167 void OnQuit(wxCommandEvent
& event
);
168 void OnAbout(wxCommandEvent
& event
);
170 void OnOpenFileSamePage(wxCommandEvent
& event
);
171 void OnOpenFileNewPage(wxCommandEvent
& event
);
172 void OnOpenURLSamePage(wxCommandEvent
& event
);
173 void OnOpenURLNewPage(wxCommandEvent
& event
);
174 void OnCloseCurrentPage(wxCommandEvent
& event
);
176 void OnPlay(wxCommandEvent
& event
);
177 void OnPause(wxCommandEvent
& event
);
178 void OnStop(wxCommandEvent
& event
);
179 void OnNext(wxCommandEvent
& event
);
180 void OnPrev(wxCommandEvent
& event
);
181 void OnVolumeDown(wxCommandEvent
& event
);
182 void OnVolumeUp(wxCommandEvent
& event
);
184 void OnLoop(wxCommandEvent
& event
);
185 void OnShowInterface(wxCommandEvent
& event
);
187 void OnSelectBackend(wxCommandEvent
& event
);
189 // Key event handlers
190 void OnKeyDown(wxKeyEvent
& event
);
192 // Quickie for playing from command line
193 void AddToPlayList(const wxString
& szString
);
195 // ListCtrl event handlers
196 void OnChangeSong(wxListEvent
& event
);
198 // Media event handlers
199 void OnMediaLoaded(wxMediaEvent
& event
);
201 // Close event handlers
202 void OnClose(wxCloseEvent
& event
);
205 // Common open file code
206 void OpenFile(bool bNewPage
);
207 void OpenURL(bool bNewPage
);
208 void DoOpenFile(const wxString
& path
, bool bNewPage
);
209 void DoPlayFile(const wxString
& path
);
211 class wxMediaPlayerTimer
* m_timer
; // Timer to write info to status bar
212 wxNotebook
* m_notebook
; // Notebook containing our pages
214 // Maybe I should use more accessors, but for simplicity
215 // I'll allow the other classes access to our members
216 friend class wxMediaPlayerApp
;
217 friend class wxMediaPlayerNotebookPage
;
218 friend class wxMediaPlayerTimer
;
223 // ----------------------------------------------------------------------------
224 // wxMediaPlayerNotebookPage
225 // ----------------------------------------------------------------------------
227 class wxMediaPlayerNotebookPage
: public wxPanel
229 wxMediaPlayerNotebookPage(wxMediaPlayerFrame
* parentFrame
,
230 wxNotebook
* book
, const wxString
& be
= wxEmptyString
);
232 // Slider event handlers
233 void OnBeginSeek(wxScrollEvent
& event
);
234 void OnEndSeek(wxScrollEvent
& event
);
235 void OnPBChange(wxScrollEvent
& event
);
236 void OnVolChange(wxScrollEvent
& event
);
238 // Media event handlers
239 void OnMediaPlay(wxMediaEvent
& event
);
240 void OnMediaPause(wxMediaEvent
& event
);
241 void OnMediaStop(wxMediaEvent
& event
);
242 void OnMediaFinished(wxMediaEvent
& event
);
245 bool IsBeingDragged(); // accessor for m_bIsBeingDragged
247 // make wxMediaPlayerFrame able to access the private members
248 friend class wxMediaPlayerFrame
;
250 int m_nLastFileId
; // List ID of played file in listctrl
251 wxString m_szFile
; // Name of currently playing file/location
253 wxMediaCtrl
* m_mediactrl
; // Our media control
254 class wxMediaPlayerListCtrl
* m_playlist
; // Our playlist
255 wxSlider
* m_slider
; // The slider below our media control
256 wxSlider
* m_pbSlider
; // Lower-left slider for adjusting speed
257 wxSlider
* m_volSlider
; // Lower-right slider for adjusting volume
258 int m_nLoops
; // Number of times media has looped
259 bool m_bLoop
; // Whether we are looping or not
260 bool m_bIsBeingDragged
; // Whether the user is dragging the scroll bar
261 wxMediaPlayerFrame
* m_parentFrame
; // Main wxFrame of our sample
262 wxButton
* m_prevButton
; // Go to previous file button
263 wxButton
* m_playButton
; // Play/pause file button
264 wxButton
* m_stopButton
; // Stop playing file button
265 wxButton
* m_nextButton
; // Next file button
266 wxButton
* m_vdButton
; // Volume down button
267 wxButton
* m_vuButton
; // Volume up button
268 wxGauge
* m_gauge
; // Gauge to keep in line with slider
271 // ----------------------------------------------------------------------------
272 // wxMediaPlayerTimer
273 // ----------------------------------------------------------------------------
275 class wxMediaPlayerTimer
: public wxTimer
279 wxMediaPlayerTimer(wxMediaPlayerFrame
* frame
) {m_frame
= frame
;}
281 // Called each time the timer's timeout expires
284 wxMediaPlayerFrame
* m_frame
; // The wxMediaPlayerFrame
287 // ----------------------------------------------------------------------------
288 // wxMediaPlayerListCtrl
289 // ----------------------------------------------------------------------------
290 class wxMediaPlayerListCtrl
: public wxListCtrl
293 void AddToPlayList(const wxString
& szString
)
296 kNewItem
.SetAlign(wxLIST_FORMAT_LEFT
);
298 int nID
= this->GetItemCount();
300 kNewItem
.SetMask(wxLIST_MASK_DATA
);
301 kNewItem
.SetData(new wxString(szString
));
303 this->InsertItem(kNewItem
);
304 this->SetItem(nID
, 0, wxT("*"));
305 this->SetItem(nID
, 1, wxFileName(szString
).GetName());
309 kNewItem
.SetBackgroundColour(wxColour(192,192,192));
310 this->SetItem(kNewItem
);
314 void GetSelectedItem(wxListItem
& listitem
)
316 listitem
.SetMask(wxLIST_MASK_TEXT
| wxLIST_MASK_DATA
);
317 int nLast
= -1, nLastSelected
= -1;
318 while ((nLast
= this->GetNextItem(nLast
,
320 wxLIST_STATE_SELECTED
)) != -1)
322 listitem
.SetId(nLast
);
323 this->GetItem(listitem
);
324 if ((listitem
.GetState() & wxLIST_STATE_FOCUSED
) )
326 nLastSelected
= nLast
;
328 if (nLast
== -1 && nLastSelected
== -1)
330 listitem
.SetId(nLastSelected
== -1 ? nLast
: nLastSelected
);
331 this->GetItem(listitem
);
335 // ----------------------------------------------------------------------------
336 // wxPlayListDropTarget
338 // Drop target for playlist (i.e. allows users to drag a file from explorer into
339 // the playlist to add that file)
340 // ----------------------------------------------------------------------------
341 #if wxUSE_DRAG_AND_DROP
342 class wxPlayListDropTarget
: public wxFileDropTarget
345 wxPlayListDropTarget(wxMediaPlayerListCtrl
& list
) : m_list(list
) {}
346 ~wxPlayListDropTarget(){}
347 virtual bool OnDropFiles(wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
),
348 const wxArrayString
& files
)
350 for (size_t i
= 0; i
< files
.GetCount(); ++i
)
352 m_list
.AddToPlayList(files
[i
]);
356 wxMediaPlayerListCtrl
& m_list
;
360 // ============================================================================
364 // ============================================================================
366 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
370 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
372 // ----------------------------------------------------------------------------
373 // wxGetMediaStateText
375 // Converts a wxMediaCtrl state into something useful that we can display
377 // ----------------------------------------------------------------------------
378 const wxChar
* wxGetMediaStateText(int nState
)
382 case wxMEDIASTATE_PLAYING
:
383 return wxT("Playing");
384 case wxMEDIASTATE_STOPPED
:
385 return wxT("Stopped");
386 ///case wxMEDIASTATE_PAUSED:
388 return wxT("Paused");
392 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
396 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
398 // ----------------------------------------------------------------------------
399 // This sets up this wxApp as the global wxApp that gui calls in wxWidgets
400 // use. For example, if you were to be in windows and use a file dialog,
401 // wxWidgets would use wxTheApp->GetHInstance() which would get the instance
402 // handle of the application. These routines in wx _DO NOT_ check to see if
403 // the wxApp exists, and thus will crash the application if you try it.
405 // IMPLEMENT_APP does this, and also implements the platform-specific entry
406 // routine, such as main or WinMain(). Use IMPLEMENT_APP_NO_MAIN if you do
407 // not desire this behavior.
408 // ----------------------------------------------------------------------------
409 IMPLEMENT_APP(wxMediaPlayerApp
)
411 // ----------------------------------------------------------------------------
412 // wxMediaPlayerApp::OnInit
414 // Where execution starts - akin to a main or WinMain.
415 // 1) Create the frame and show it to the user
416 // 2) Process filenames from the commandline
417 // 3) return true specifying that we want execution to continue past OnInit
418 // ----------------------------------------------------------------------------
419 bool wxMediaPlayerApp::OnInit()
421 if ( !wxApp::OnInit() )
424 // SetAppName() lets wxConfig and others know where to write
425 SetAppName(wxT("wxMediaPlayer"));
427 wxMediaPlayerFrame
*frame
=
428 new wxMediaPlayerFrame(wxT("MediaPlayer wxWidgets Sample"));
431 #if wxUSE_CMDLINE_PARSER
433 // What this does is get all the command line arguments
434 // and treat each one as a file to put to the initial playlist
436 wxCmdLineEntryDesc cmdLineDesc
[2];
437 cmdLineDesc
[0].kind
= wxCMD_LINE_PARAM
;
438 cmdLineDesc
[0].shortName
= NULL
;
439 cmdLineDesc
[0].longName
= NULL
;
440 cmdLineDesc
[0].description
= "input files";
441 cmdLineDesc
[0].type
= wxCMD_LINE_VAL_STRING
;
442 cmdLineDesc
[0].flags
= wxCMD_LINE_PARAM_OPTIONAL
| wxCMD_LINE_PARAM_MULTIPLE
;
444 cmdLineDesc
[1].kind
= wxCMD_LINE_NONE
;
446 // gets the passed media files from cmd line
447 wxCmdLineParser
parser (cmdLineDesc
, argc
, argv
);
449 // get filenames from the commandline
450 if (parser
.Parse() == 0)
452 for (size_t paramNr
=0; paramNr
< parser
.GetParamCount(); ++paramNr
)
454 frame
->AddToPlayList((parser
.GetParam (paramNr
)));
456 wxCommandEvent
theEvent(wxEVT_COMMAND_MENU_SELECTED
, wxID_NEXT
);
457 frame
->AddPendingEvent(theEvent
);
466 void wxMediaPlayerApp::MacOpenFile(const wxString
& fileName
)
468 // Called when a user drags a file over our app
469 m_frame
->DoOpenFile(fileName
, true /* new page */);
474 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
476 // wxMediaPlayerFrame
478 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
480 // ----------------------------------------------------------------------------
481 // wxMediaPlayerFrame Constructor
483 // 1) Create our menus
484 // 2) Create our notebook control and add it to the frame
485 // 3) Create our status bar
486 // 4) Connect our events
487 // 5) Start our timer
488 // ----------------------------------------------------------------------------
490 wxMediaPlayerFrame::wxMediaPlayerFrame(const wxString
& title
)
491 : wxFrame(NULL
, wxID_ANY
, title
, wxDefaultPosition
, wxSize(600,600))
493 SetIcon(wxICON(sample
));
498 wxMenu
*fileMenu
= new wxMenu
;
499 wxMenu
*controlsMenu
= new wxMenu
;
500 wxMenu
*optionsMenu
= new wxMenu
;
501 wxMenu
*helpMenu
= new wxMenu
;
502 wxMenu
*debugMenu
= new wxMenu
;
504 fileMenu
->Append(wxID_OPENFILESAMEPAGE
, wxT("&Open File\tCtrl-Shift-O"),
505 wxT("Open a File in the current notebook page"));
506 fileMenu
->Append(wxID_OPENFILENEWPAGE
, wxT("&Open File in a new page"),
507 wxT("Open a File in a new notebook page"));
508 fileMenu
->Append(wxID_OPENURLSAMEPAGE
, wxT("&Open URL"),
509 wxT("Open a URL in the current notebook page"));
510 fileMenu
->Append(wxID_OPENURLNEWPAGE
, wxT("&Open URL in a new page"),
511 wxT("Open a URL in a new notebook page"));
512 fileMenu
->AppendSeparator();
513 fileMenu
->Append(wxID_CLOSECURRENTPAGE
, wxT("&Close Current Page\tCtrl-C"),
514 wxT("Close current notebook page"));
515 fileMenu
->AppendSeparator();
516 fileMenu
->Append(wxID_EXIT
,
518 wxT("Quit this program"));
520 controlsMenu
->Append(wxID_PLAY
, wxT("&Play/Pause\tCtrl-P"), wxT("Resume/Pause playback"));
521 controlsMenu
->Append(wxID_STOP
, wxT("&Stop\tCtrl-S"), wxT("Stop playback"));
522 controlsMenu
->AppendSeparator();
523 controlsMenu
->Append(wxID_PREV
, wxT("&Previous\tCtrl-B"), wxT("Go to previous track"));
524 controlsMenu
->Append(wxID_NEXT
, wxT("&Next\tCtrl-N"), wxT("Skip to next track"));
526 optionsMenu
->AppendCheckItem(wxID_LOOP
,
527 wxT("&Loop\tCtrl-L"),
528 wxT("Loop Selected Media"));
529 optionsMenu
->AppendCheckItem(wxID_SHOWINTERFACE
,
530 wxT("&Show Interface\tCtrl-I"),
531 wxT("Show wxMediaCtrl native controls"));
533 debugMenu
->Append(wxID_SELECTBACKEND
,
534 wxT("&Select Backend...\tCtrl-D"),
535 wxT("Select a backend manually"));
537 helpMenu
->Append(wxID_ABOUT
,
538 wxT("&About...\tF1"),
539 wxT("Show about dialog"));
542 wxMenuBar
*menuBar
= new wxMenuBar();
543 menuBar
->Append(fileMenu
, wxT("&File"));
544 menuBar
->Append(controlsMenu
, wxT("&Controls"));
545 menuBar
->Append(optionsMenu
, wxT("&Options"));
546 menuBar
->Append(debugMenu
, wxT("&Debug"));
547 menuBar
->Append(helpMenu
, wxT("&Help"));
551 // Create our notebook - using wxNotebook is luckily pretty
552 // simple and self-explanatory in most cases
554 m_notebook
= new wxNotebook(this, wxID_NOTEBOOK
);
557 // Create our status bar
560 // create a status bar just for fun (by default with 1 pane only)
562 #endif // wxUSE_STATUSBAR
567 // There are two ways in wxWidgets to use events -
568 // Message Maps and Connections.
570 // Message Maps are implemented by putting
571 // DECLARE_MESSAGE_MAP in your wxEvtHandler-derived
572 // class you want to use for events, such as wxMediaPlayerFrame.
574 // Then after your class declaration you put
575 // BEGIN_EVENT_TABLE(wxMediaPlayerFrame, wxFrame)
579 // Where wxMediaPlayerFrame is the class with the DECLARE_MESSAGE_MAP
580 // in it. EVT_XXX(XXX) are each of your handlers, such
581 // as EVT_MENU for menu events and the XXX inside
582 // is the parameters to the event macro - in the case
583 // of EVT_MENU the menu id and then the function to call.
585 // However, with wxEvtHandler::Connect you can avoid a
586 // global message map for your class and those annoying
587 // macros. You can also change the context in which
588 // the call the handler (more later).
590 // The downside is that due to the limitation that
591 // wxWidgets doesn't use templates in certain areas,
592 // You have to triple-cast the event function.
594 // There are five parameters to wxEvtHandler::Connect -
596 // The first is the id of the instance whose events
597 // you want to handle - i.e. a menu id for menus,
598 // a control id for controls (wxControl::GetId())
601 // The second is the event id. This is the same
602 // as the message maps (EVT_MENU) except prefixed
603 // with "wx" (wxEVT_MENU).
605 // The third is the function handler for the event -
606 // You need to cast it to the specific event handler
607 // type, then to a wxEventFunction, then to a
608 // wxObjectEventFunction - I.E.
609 // (wxObjectEventFunction)(wxEventFunction)
610 // (wxCommandEventFunction) &wxMediaPlayerFrame::MyHandler
612 // Or, you can use the new (2.5.5+) event handler
613 // conversion macros - for instance the above could
615 // wxCommandEventHandler(wxMediaPlayerFrame::MyHandler)
616 // pretty simple, eh?
618 // The fourth is an optional userdata param -
619 // this is of historical relevance only and is
620 // there only for backwards compatibility.
622 // The fifth is the context in which to call the
623 // handler - by default (this param is optional)
624 // this. For example in your event handler
625 // if you were to call "this->MyFunc()"
626 // it would literally do this->MyFunc. However,
627 // if you were to pass myHandler as the fifth
628 // parameter, for instance, you would _really_
629 // be calling myHandler->MyFunc, even though
630 // the compiler doesn't really know it.
636 this->Connect(wxID_EXIT
, wxEVT_COMMAND_MENU_SELECTED
,
637 wxCommandEventHandler(wxMediaPlayerFrame::OnQuit
));
639 this->Connect(wxID_ABOUT
, wxEVT_COMMAND_MENU_SELECTED
,
640 wxCommandEventHandler(wxMediaPlayerFrame::OnAbout
));
642 this->Connect(wxID_LOOP
, wxEVT_COMMAND_MENU_SELECTED
,
643 wxCommandEventHandler(wxMediaPlayerFrame::OnLoop
));
645 this->Connect(wxID_SHOWINTERFACE
, wxEVT_COMMAND_MENU_SELECTED
,
646 wxCommandEventHandler(wxMediaPlayerFrame::OnShowInterface
));
648 this->Connect(wxID_OPENFILENEWPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
649 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileNewPage
));
651 this->Connect(wxID_OPENFILESAMEPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
652 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileSamePage
));
654 this->Connect(wxID_OPENURLNEWPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
655 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLNewPage
));
657 this->Connect(wxID_OPENURLSAMEPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
658 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLSamePage
));
660 this->Connect(wxID_CLOSECURRENTPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
661 wxCommandEventHandler(wxMediaPlayerFrame::OnCloseCurrentPage
));
663 this->Connect(wxID_PLAY
, wxEVT_COMMAND_MENU_SELECTED
,
664 wxCommandEventHandler(wxMediaPlayerFrame::OnPlay
));
666 this->Connect(wxID_STOP
, wxEVT_COMMAND_MENU_SELECTED
,
667 wxCommandEventHandler(wxMediaPlayerFrame::OnStop
));
669 this->Connect(wxID_NEXT
, wxEVT_COMMAND_MENU_SELECTED
,
670 wxCommandEventHandler(wxMediaPlayerFrame::OnNext
));
672 this->Connect(wxID_PREV
, wxEVT_COMMAND_MENU_SELECTED
,
673 wxCommandEventHandler(wxMediaPlayerFrame::OnPrev
));
675 this->Connect(wxID_SELECTBACKEND
, wxEVT_COMMAND_MENU_SELECTED
,
676 wxCommandEventHandler(wxMediaPlayerFrame::OnSelectBackend
));
681 wxTheApp
->Connect(wxID_ANY
, wxEVT_KEY_DOWN
,
682 wxKeyEventHandler(wxMediaPlayerFrame::OnKeyDown
),
688 this->Connect(wxID_ANY
, wxEVT_CLOSE_WINDOW
,
689 wxCloseEventHandler(wxMediaPlayerFrame::OnClose
));
696 // Create an initial notebook page so the user has something
697 // to work with without having to go file->open every time :).
699 wxMediaPlayerNotebookPage
* page
=
700 new wxMediaPlayerNotebookPage(this, m_notebook
);
701 m_notebook
->AddPage(page
,
706 // Here we load the our configuration -
707 // in our case we load all the files that were left in
708 // the playlist the last time the user closed our application
710 // As an exercise to the reader try modifying it so that
711 // it properly loads the playlist for each page without
712 // conflicting (loading the same data) with the other ones.
715 wxString key
, outstring
;
716 for(int i
= 0; ; ++i
)
720 if(!conf
.Read(key
, &outstring
))
722 page
->m_playlist
->AddToPlayList(outstring
);
726 // Create a timer to update our status bar
728 m_timer
= new wxMediaPlayerTimer(this);
732 // ----------------------------------------------------------------------------
733 // wxMediaPlayerFrame Destructor
735 // 1) Deletes child objects implicitly
736 // 2) Delete our timer explicitly
737 // ----------------------------------------------------------------------------
738 wxMediaPlayerFrame::~wxMediaPlayerFrame()
740 // Shut down our timer
744 // Here we save our info to the registry or whatever
745 // mechanism the OS uses.
747 // This makes it so that when mediaplayer loads up again
748 // it restores the same files that were in the playlist
749 // this time, rather than the user manually re-adding them.
751 // We need to do conf->DeleteAll() here because by default
752 // the config still contains the same files as last time
753 // so we need to clear it before writing our new ones.
755 // TODO: Maybe you could add a menu option to the
756 // options menu to delete the configuration on exit -
757 // all you'd need to do is just remove everything after
758 // conf->DeleteAll() here
760 // As an exercise to the reader, try modifying this so
761 // that it saves the data for each notebook page
763 wxMediaPlayerListCtrl
* playlist
=
764 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetPage(0))->m_playlist
;
769 for(int i
= 0; i
< playlist
->GetItemCount(); ++i
)
771 wxString
* pData
= (wxString
*) playlist
->GetItemData(i
);
774 conf
.Write(s
, *(pData
));
779 // ----------------------------------------------------------------------------
780 // wxMediaPlayerFrame::OnClose
781 // ----------------------------------------------------------------------------
782 void wxMediaPlayerFrame::OnClose(wxCloseEvent
& event
)
784 event
.Skip(); // really close the frame
787 // ----------------------------------------------------------------------------
788 // wxMediaPlayerFrame::AddToPlayList
789 // ----------------------------------------------------------------------------
790 void wxMediaPlayerFrame::AddToPlayList(const wxString
& szString
)
792 wxMediaPlayerNotebookPage
* currentpage
=
793 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
795 currentpage
->m_playlist
->AddToPlayList(szString
);
798 // ----------------------------------------------------------------------------
799 // wxMediaPlayerFrame::OnQuit
801 // Called from file->quit.
802 // Closes this application.
803 // ----------------------------------------------------------------------------
804 void wxMediaPlayerFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
806 // true is to force the frame to close
810 // ----------------------------------------------------------------------------
811 // wxMediaPlayerFrame::OnAbout
813 // Called from help->about.
814 // Gets some info about this application.
815 // ----------------------------------------------------------------------------
816 void wxMediaPlayerFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
819 msg
.Printf( wxT("This is a test of wxMediaCtrl.\n\n")
821 wxT("Instructions:\n")
823 wxT("The top slider shows the current the current position, ")
824 wxT("which you can change by dragging and releasing it.\n")
826 wxT("The gauge (progress bar) shows the progress in ")
827 wxT("downloading data of the current file - it may always be ")
828 wxT("empty due to lack of support from the current backend.\n")
830 wxT("The lower-left slider controls the volume and the lower-")
831 wxT("right slider controls the playback rate/speed of the ")
834 wxT("Currently using: %s"), wxVERSION_STRING
);
836 wxMessageBox(msg
, wxT("About wxMediaCtrl test"),
837 wxOK
| wxICON_INFORMATION
, this);
840 // ----------------------------------------------------------------------------
841 // wxMediaPlayerFrame::OnLoop
843 // Called from file->loop.
844 // Changes the state of whether we want to loop or not.
845 // ----------------------------------------------------------------------------
846 void wxMediaPlayerFrame::OnLoop(wxCommandEvent
& WXUNUSED(event
))
848 wxMediaPlayerNotebookPage
* currentpage
=
849 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
851 currentpage
->m_bLoop
= !currentpage
->m_bLoop
;
854 // ----------------------------------------------------------------------------
855 // wxMediaPlayerFrame::OnLoop
857 // Called from file->loop.
858 // Changes the state of whether we want to loop or not.
859 // ----------------------------------------------------------------------------
860 void wxMediaPlayerFrame::OnShowInterface(wxCommandEvent
& event
)
862 wxMediaPlayerNotebookPage
* currentpage
=
863 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
865 if( !currentpage
->m_mediactrl
->ShowPlayerControls(event
.IsChecked() ?
866 wxMEDIACTRLPLAYERCONTROLS_DEFAULT
:
867 wxMEDIACTRLPLAYERCONTROLS_NONE
) )
869 // error - uncheck and warn user
870 wxMenuItem
* pSIItem
= GetMenuBar()->FindItem(wxID_SHOWINTERFACE
);
872 pSIItem
->Check(!event
.IsChecked());
874 if(event
.IsChecked())
875 wxMessageBox(wxT("Could not show player controls"));
877 wxMessageBox(wxT("Could not hide player controls"));
881 // ----------------------------------------------------------------------------
882 // wxMediaPlayerFrame::OnOpenFileSamePage
884 // Called from file->openfile.
885 // Opens and plays a media file in the current notebook page
886 // ----------------------------------------------------------------------------
887 void wxMediaPlayerFrame::OnOpenFileSamePage(wxCommandEvent
& WXUNUSED(event
))
892 // ----------------------------------------------------------------------------
893 // wxMediaPlayerFrame::OnOpenFileNewPage
895 // Called from file->openfileinnewpage.
896 // Opens and plays a media file in a new notebook page
897 // ----------------------------------------------------------------------------
898 void wxMediaPlayerFrame::OnOpenFileNewPage(wxCommandEvent
& WXUNUSED(event
))
903 // ----------------------------------------------------------------------------
904 // wxMediaPlayerFrame::OpenFile
906 // Opens a file dialog asking the user for a filename, then
907 // calls DoOpenFile which will add the file to the playlist and play it
908 // ----------------------------------------------------------------------------
909 void wxMediaPlayerFrame::OpenFile(bool bNewPage
)
911 wxFileDialog
fd(this);
913 if(fd
.ShowModal() == wxID_OK
)
915 DoOpenFile(fd
.GetPath(), bNewPage
);
919 // ----------------------------------------------------------------------------
920 // wxMediaPlayerFrame::DoOpenFile
922 // Adds the file to our playlist, selects it in the playlist,
923 // and then calls DoPlayFile to play it
924 // ----------------------------------------------------------------------------
925 void wxMediaPlayerFrame::DoOpenFile(const wxString
& path
, bool bNewPage
)
930 new wxMediaPlayerNotebookPage(this, m_notebook
),
935 wxMediaPlayerNotebookPage
* currentpage
=
936 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
938 if(currentpage
->m_nLastFileId
!= -1)
939 currentpage
->m_playlist
->SetItemState(currentpage
->m_nLastFileId
,
940 0, wxLIST_STATE_SELECTED
);
942 wxListItem newlistitem
;
943 newlistitem
.SetAlign(wxLIST_FORMAT_LEFT
);
947 newlistitem
.SetId(nID
= currentpage
->m_playlist
->GetItemCount());
948 newlistitem
.SetMask(wxLIST_MASK_DATA
| wxLIST_MASK_STATE
);
949 newlistitem
.SetState(wxLIST_STATE_SELECTED
);
950 newlistitem
.SetData(new wxString(path
));
952 currentpage
->m_playlist
->InsertItem(newlistitem
);
953 currentpage
->m_playlist
->SetItem(nID
, 0, wxT("*"));
954 currentpage
->m_playlist
->SetItem(nID
, 1, wxFileName(path
).GetName());
958 newlistitem
.SetBackgroundColour(wxColour(192,192,192));
959 currentpage
->m_playlist
->SetItem(newlistitem
);
965 // ----------------------------------------------------------------------------
966 // wxMediaPlayerFrame::DoPlayFile
968 // Pauses the file if its the currently playing file,
969 // otherwise it plays the file
970 // ----------------------------------------------------------------------------
971 void wxMediaPlayerFrame::DoPlayFile(const wxString
& path
)
973 wxMediaPlayerNotebookPage
* currentpage
=
974 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
977 currentpage
->m_playlist
->GetSelectedItem(listitem
);
979 if( ( listitem
.GetData() &&
980 currentpage
->m_nLastFileId
== listitem
.GetId() &&
981 currentpage
->m_szFile
.compare(path
) == 0 ) ||
982 ( !listitem
.GetData() &&
983 currentpage
->m_nLastFileId
!= -1 &&
984 currentpage
->m_szFile
.compare(path
) == 0)
987 if(currentpage
->m_mediactrl
->GetState() == wxMEDIASTATE_PLAYING
)
989 if( !currentpage
->m_mediactrl
->Pause() )
990 wxMessageBox(wxT("Couldn't pause movie!"));
994 if( !currentpage
->m_mediactrl
->Play() )
995 wxMessageBox(wxT("Couldn't play movie!"));
1000 int nNewId
= listitem
.GetData() ? listitem
.GetId() :
1001 currentpage
->m_playlist
->GetItemCount()-1;
1002 m_notebook
->SetPageText(m_notebook
->GetSelection(),
1003 wxFileName(path
).GetName());
1005 if(currentpage
->m_nLastFileId
!= -1)
1006 currentpage
->m_playlist
->SetItem(
1007 currentpage
->m_nLastFileId
, 0, wxT("*"));
1009 wxURI
uripath(path
);
1010 if( uripath
.IsReference() )
1012 if( !currentpage
->m_mediactrl
->Load(path
) )
1014 wxMessageBox(wxT("Couldn't load file!"));
1015 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("E"));
1019 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("O"));
1024 if( !currentpage
->m_mediactrl
->Load(uripath
) )
1026 wxMessageBox(wxT("Couldn't load URL!"));
1027 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("E"));
1031 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("O"));
1035 currentpage
->m_nLastFileId
= nNewId
;
1036 currentpage
->m_szFile
= path
;
1037 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
,
1038 1, wxFileName(path
).GetName());
1039 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
,
1044 // ----------------------------------------------------------------------------
1045 // wxMediaPlayerFrame::OnMediaLoaded
1047 // Called when the media is ready to be played - and does
1048 // so, also gets the length of media and shows that in the list control
1049 // ----------------------------------------------------------------------------
1050 void wxMediaPlayerFrame::OnMediaLoaded(wxMediaEvent
& WXUNUSED(evt
))
1052 wxMediaPlayerNotebookPage
* currentpage
=
1053 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1055 if( !currentpage
->m_mediactrl
->Play() )
1057 wxMessageBox(wxT("Couldn't play movie!"));
1058 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
, 0, wxT("E"));
1062 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
, 0, wxT(">"));
1068 // ----------------------------------------------------------------------------
1069 // wxMediaPlayerFrame::OnSelectBackend
1071 // Little debugging routine - enter the class name of a backend and it
1072 // will use that instead of letting wxMediaCtrl search the wxMediaBackend
1074 // ----------------------------------------------------------------------------
1075 void wxMediaPlayerFrame::OnSelectBackend(wxCommandEvent
& WXUNUSED(evt
))
1077 wxString sBackend
= wxGetTextFromUser(wxT("Enter backend to use"));
1079 if(sBackend
.empty() == false) // could have been cancelled by the user
1081 int sel
= m_notebook
->GetSelection();
1083 if (sel
!= wxNOT_FOUND
)
1085 m_notebook
->DeletePage(sel
);
1088 m_notebook
->AddPage(new wxMediaPlayerNotebookPage(this, m_notebook
,
1093 ((wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage())->m_szFile
,
1098 // ----------------------------------------------------------------------------
1099 // wxMediaPlayerFrame::OnOpenURLSamePage
1101 // Called from file->openurl.
1102 // Opens and plays a media file from a URL in the current notebook page
1103 // ----------------------------------------------------------------------------
1104 void wxMediaPlayerFrame::OnOpenURLSamePage(wxCommandEvent
& WXUNUSED(event
))
1109 // ----------------------------------------------------------------------------
1110 // wxMediaPlayerFrame::OnOpenURLNewPage
1112 // Called from file->openurlinnewpage.
1113 // Opens and plays a media file from a URL in a new notebook page
1114 // ----------------------------------------------------------------------------
1115 void wxMediaPlayerFrame::OnOpenURLNewPage(wxCommandEvent
& WXUNUSED(event
))
1120 // ----------------------------------------------------------------------------
1121 // wxMediaPlayerFrame::OpenURL
1123 // Just calls DoOpenFile with the url path - which calls DoPlayFile
1124 // which handles the real dirty work
1125 // ----------------------------------------------------------------------------
1126 void wxMediaPlayerFrame::OpenURL(bool bNewPage
)
1128 wxString sUrl
= wxGetTextFromUser(
1129 wxT("Enter the URL that has the movie to play")
1132 if(sUrl
.empty() == false) // could have been cancelled by user
1134 DoOpenFile(sUrl
, bNewPage
);
1138 // ----------------------------------------------------------------------------
1139 // wxMediaPlayerFrame::OnCloseCurrentPage
1141 // Called when the user wants to close the current notebook page
1143 // 1) Get the current page number (wxControl::GetSelection)
1144 // 2) If there is no current page, break out
1145 // 3) Delete the current page
1146 // ----------------------------------------------------------------------------
1147 void wxMediaPlayerFrame::OnCloseCurrentPage(wxCommandEvent
& WXUNUSED(event
))
1149 if( m_notebook
->GetPageCount() > 1 )
1151 int sel
= m_notebook
->GetSelection();
1153 if (sel
!= wxNOT_FOUND
)
1155 m_notebook
->DeletePage(sel
);
1160 wxMessageBox(wxT("Cannot close main page"));
1164 // ----------------------------------------------------------------------------
1165 // wxMediaPlayerFrame::OnPlay
1167 // Called from file->play.
1168 // Resumes the media if it is paused or stopped.
1169 // ----------------------------------------------------------------------------
1170 void wxMediaPlayerFrame::OnPlay(wxCommandEvent
& WXUNUSED(event
))
1172 wxMediaPlayerNotebookPage
* currentpage
=
1173 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1175 wxListItem listitem
;
1176 currentpage
->m_playlist
->GetSelectedItem(listitem
);
1177 if ( !listitem
.GetData() )
1180 if ((nLast
= currentpage
->m_playlist
->GetNextItem(nLast
,
1182 wxLIST_STATE_DONTCARE
)) == -1)
1185 wxMessageBox(wxT("No items in playlist!"));
1189 listitem
.SetId(nLast
);
1190 currentpage
->m_playlist
->GetItem(listitem
);
1191 listitem
.SetMask(listitem
.GetMask() | wxLIST_MASK_STATE
);
1192 listitem
.SetState(listitem
.GetState() | wxLIST_STATE_SELECTED
);
1193 currentpage
->m_playlist
->SetItem(listitem
);
1194 wxASSERT(listitem
.GetData());
1195 DoPlayFile((*((wxString
*) listitem
.GetData())));
1200 wxASSERT(listitem
.GetData());
1201 DoPlayFile((*((wxString
*) listitem
.GetData())));
1205 // ----------------------------------------------------------------------------
1206 // wxMediaPlayerFrame::OnKeyDown
1208 // Deletes all selected files from the playlist if the backspace key is pressed
1209 // ----------------------------------------------------------------------------
1210 void wxMediaPlayerFrame::OnKeyDown(wxKeyEvent
& event
)
1212 if(event
.GetKeyCode() == WXK_BACK
/*DELETE*/)
1214 wxMediaPlayerNotebookPage
* currentpage
=
1215 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1216 // delete all selected items
1219 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(
1220 -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1221 if (nSelectedItem
== -1)
1224 wxListItem listitem
;
1225 listitem
.SetId(nSelectedItem
);
1226 currentpage
->m_playlist
->GetItem(listitem
);
1227 delete (wxString
*) listitem
.GetData();
1229 currentpage
->m_playlist
->DeleteItem(nSelectedItem
);
1233 // Could be wxGetTextFromUser or something else important
1234 if(event
.GetEventObject() != this)
1238 // ----------------------------------------------------------------------------
1239 // wxMediaPlayerFrame::OnStop
1241 // Called from file->stop.
1242 // Where it stops depends on whether you can seek in the
1243 // media control or not - if you can it stops and seeks to the beginning,
1244 // otherwise it will appear to be at the end - but it will start over again
1245 // when Play() is called
1246 // ----------------------------------------------------------------------------
1247 void wxMediaPlayerFrame::OnStop(wxCommandEvent
& WXUNUSED(evt
))
1249 wxMediaPlayerNotebookPage
* currentpage
=
1250 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1252 if( !currentpage
->m_mediactrl
->Stop() )
1253 wxMessageBox(wxT("Couldn't stop movie!"));
1255 currentpage
->m_playlist
->SetItem(
1256 currentpage
->m_nLastFileId
, 0, wxT("[]"));
1260 // ----------------------------------------------------------------------------
1261 // wxMediaPlayerFrame::OnChangeSong
1263 // Routine that plays the currently selected file in the playlist.
1264 // Called when the user actives the song from the playlist,
1265 // and from other various places in the sample
1266 // ----------------------------------------------------------------------------
1267 void wxMediaPlayerFrame::OnChangeSong(wxListEvent
& WXUNUSED(evt
))
1269 wxMediaPlayerNotebookPage
* currentpage
=
1270 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1272 wxListItem listitem
;
1273 currentpage
->m_playlist
->GetSelectedItem(listitem
);
1274 if(listitem
.GetData())
1275 DoPlayFile((*((wxString
*) listitem
.GetData())));
1277 wxMessageBox(wxT("No selected item!"));
1280 // ----------------------------------------------------------------------------
1281 // wxMediaPlayerFrame::OnPrev
1283 // Tedious wxListCtrl stuff. Goes to prevous song in list, or if at the
1284 // beginning goes to the last in the list.
1285 // ----------------------------------------------------------------------------
1286 void wxMediaPlayerFrame::OnPrev(wxCommandEvent
& WXUNUSED(event
))
1288 wxMediaPlayerNotebookPage
* currentpage
=
1289 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1291 if (currentpage
->m_playlist
->GetItemCount() == 0)
1294 wxInt32 nLastSelectedItem
= -1;
1297 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(nLastSelectedItem
,
1298 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1299 if (nSelectedItem
== -1)
1301 nLastSelectedItem
= nSelectedItem
;
1302 currentpage
->m_playlist
->SetItemState(nSelectedItem
, 0, wxLIST_STATE_SELECTED
);
1305 if (nLastSelectedItem
== -1)
1307 // nothing selected, default to the file before the currently playing one
1308 if(currentpage
->m_nLastFileId
== 0)
1309 nLastSelectedItem
= currentpage
->m_playlist
->GetItemCount() - 1;
1311 nLastSelectedItem
= currentpage
->m_nLastFileId
- 1;
1313 else if (nLastSelectedItem
== 0)
1314 nLastSelectedItem
= currentpage
->m_playlist
->GetItemCount() - 1;
1316 nLastSelectedItem
-= 1;
1318 if(nLastSelectedItem
== currentpage
->m_nLastFileId
)
1319 return; // already playing... nothing to do
1321 wxListItem listitem
;
1322 listitem
.SetId(nLastSelectedItem
);
1323 listitem
.SetMask(wxLIST_MASK_TEXT
| wxLIST_MASK_DATA
);
1324 currentpage
->m_playlist
->GetItem(listitem
);
1325 listitem
.SetMask(listitem
.GetMask() | wxLIST_MASK_STATE
);
1326 listitem
.SetState(listitem
.GetState() | wxLIST_STATE_SELECTED
);
1327 currentpage
->m_playlist
->SetItem(listitem
);
1329 wxASSERT(listitem
.GetData());
1330 DoPlayFile((*((wxString
*) listitem
.GetData())));
1333 // ----------------------------------------------------------------------------
1334 // wxMediaPlayerFrame::OnNext
1336 // Tedious wxListCtrl stuff. Goes to next song in list, or if at the
1337 // end goes to the first in the list.
1338 // ----------------------------------------------------------------------------
1339 void wxMediaPlayerFrame::OnNext(wxCommandEvent
& WXUNUSED(event
))
1341 wxMediaPlayerNotebookPage
* currentpage
=
1342 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1344 if (currentpage
->m_playlist
->GetItemCount() == 0)
1347 wxInt32 nLastSelectedItem
= -1;
1350 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(nLastSelectedItem
,
1351 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1352 if (nSelectedItem
== -1)
1354 nLastSelectedItem
= nSelectedItem
;
1355 currentpage
->m_playlist
->SetItemState(nSelectedItem
, 0, wxLIST_STATE_SELECTED
);
1358 if (nLastSelectedItem
== -1)
1360 if(currentpage
->m_nLastFileId
== currentpage
->m_playlist
->GetItemCount() - 1)
1361 nLastSelectedItem
= 0;
1363 nLastSelectedItem
= currentpage
->m_nLastFileId
+ 1;
1365 else if (nLastSelectedItem
== currentpage
->m_playlist
->GetItemCount() - 1)
1366 nLastSelectedItem
= 0;
1368 nLastSelectedItem
+= 1;
1370 if(nLastSelectedItem
== currentpage
->m_nLastFileId
)
1371 return; // already playing... nothing to do
1373 wxListItem listitem
;
1374 listitem
.SetMask(wxLIST_MASK_TEXT
| wxLIST_MASK_DATA
);
1375 listitem
.SetId(nLastSelectedItem
);
1376 currentpage
->m_playlist
->GetItem(listitem
);
1377 listitem
.SetMask(listitem
.GetMask() | wxLIST_MASK_STATE
);
1378 listitem
.SetState(listitem
.GetState() | wxLIST_STATE_SELECTED
);
1379 currentpage
->m_playlist
->SetItem(listitem
);
1381 wxASSERT(listitem
.GetData());
1382 DoPlayFile((*((wxString
*) listitem
.GetData())));
1386 // ----------------------------------------------------------------------------
1387 // wxMediaPlayerFrame::OnVolumeDown
1389 // Lowers the volume of the media control by 5%
1390 // ----------------------------------------------------------------------------
1391 void wxMediaPlayerFrame::OnVolumeDown(wxCommandEvent
& WXUNUSED(event
))
1393 wxMediaPlayerNotebookPage
* currentpage
=
1394 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1396 double dVolume
= currentpage
->m_mediactrl
->GetVolume();
1397 currentpage
->m_mediactrl
->SetVolume(dVolume
< 0.05 ? 0.0 : dVolume
- .05);
1400 // ----------------------------------------------------------------------------
1401 // wxMediaPlayerFrame::OnVolumeUp
1403 // Increases the volume of the media control by 5%
1404 // ----------------------------------------------------------------------------
1405 void wxMediaPlayerFrame::OnVolumeUp(wxCommandEvent
& WXUNUSED(event
))
1407 wxMediaPlayerNotebookPage
* currentpage
=
1408 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1410 double dVolume
= currentpage
->m_mediactrl
->GetVolume();
1411 currentpage
->m_mediactrl
->SetVolume(dVolume
> 0.95 ? 1.0 : dVolume
+ .05);
1414 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1416 // wxMediaPlayerTimer
1418 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1420 // ----------------------------------------------------------------------------
1421 // wxMediaPlayerTimer::Notify
1423 // 1) Updates media information on the status bar
1424 // 2) Sets the max/min length of the slider and guage
1426 // Note that the reason we continually do this and don't cache it is because
1427 // some backends such as GStreamer are dynamic change values all the time
1428 // and often don't have things like duration or video size available
1429 // until the media is actually being played
1430 // ----------------------------------------------------------------------------
1431 void wxMediaPlayerTimer::Notify()
1433 wxMediaPlayerNotebookPage
* currentpage
=
1434 (wxMediaPlayerNotebookPage
*) m_frame
->m_notebook
->GetCurrentPage();
1435 wxMediaCtrl
* currentMediaCtrl
= currentpage
->m_mediactrl
;
1437 // Number of minutes/seconds total
1438 wxLongLong llLength
= currentpage
->m_mediactrl
->Length();
1439 int nMinutes
= (int) (llLength
/ 60000).GetValue();
1440 int nSeconds
= (int) ((llLength
% 60000)/1000).GetValue();
1442 // Duration string (i.e. MM:SS)
1444 sDuration
.Printf(wxT("%2i:%02i"), nMinutes
, nSeconds
);
1447 // Number of minutes/seconds total
1448 wxLongLong llTell
= currentpage
->m_mediactrl
->Tell();
1449 nMinutes
= (int) (llTell
/ 60000).GetValue();
1450 nSeconds
= (int) ((llTell
% 60000)/1000).GetValue();
1452 // Position string (i.e. MM:SS)
1454 sPosition
.Printf(wxT("%2i:%02i"), nMinutes
, nSeconds
);
1457 // Set the third item in the listctrl entry to the duration string
1458 if(currentpage
->m_nLastFileId
>= 0)
1459 currentpage
->m_playlist
->SetItem(
1460 currentpage
->m_nLastFileId
, 2, sDuration
);
1462 // Setup the slider and gauge min/max values
1463 currentpage
->m_slider
->SetRange(0, (int)(llLength
/ 1000).GetValue());
1464 currentpage
->m_gauge
->SetRange(100);
1467 // if the slider is not being dragged then update it with the song position
1468 if(currentpage
->IsBeingDragged() == false)
1469 currentpage
->m_slider
->SetValue((long)(llTell
/ 1000).GetValue());
1472 // Update the gauge with the download progress
1473 wxLongLong llDownloadProgress
=
1474 currentpage
->m_mediactrl
->GetDownloadProgress();
1475 wxLongLong llDownloadTotal
=
1476 currentpage
->m_mediactrl
->GetDownloadTotal();
1478 if(llDownloadTotal
.GetValue() != 0)
1480 currentpage
->m_gauge
->SetValue(
1481 (int) ((llDownloadProgress
* 100) / llDownloadTotal
).GetValue()
1485 // GetBestSize holds the original video size
1486 wxSize videoSize
= currentMediaCtrl
->GetBestSize();
1488 // Now the big part - set the status bar text to
1489 // hold various metadata about the media
1491 m_frame
->SetStatusText(wxString::Format(
1492 wxT("Size(x,y):%i,%i ")
1493 wxT("Position:%s/%s Speed:%1.1fx ")
1494 wxT("State:%s Loops:%i D/T:[%i]/[%i] V:%i%%"),
1499 currentMediaCtrl
->GetPlaybackRate(),
1500 wxGetMediaStateText(currentpage
->m_mediactrl
->GetState()),
1501 currentpage
->m_nLoops
,
1502 (int)llDownloadProgress
.GetValue(),
1503 (int)llDownloadTotal
.GetValue(),
1504 (int)(currentpage
->m_mediactrl
->GetVolume() * 100)));
1505 #endif // wxUSE_STATUSBAR
1508 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1510 // wxMediaPlayerNotebookPage
1512 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1514 // ----------------------------------------------------------------------------
1515 // wxMediaPlayerNotebookPage Constructor
1517 // Creates a media control and slider and adds it to this panel,
1518 // along with some sizers for positioning
1519 // ----------------------------------------------------------------------------
1520 wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame
* parentFrame
,
1521 wxNotebook
* theBook
,
1522 const wxString
& szBackend
)
1523 : wxPanel(theBook
, wxID_ANY
),
1527 m_bIsBeingDragged(false),
1528 m_parentFrame(parentFrame
)
1535 // [5 control buttons]
1541 // Create and attach a 2-column grid sizer
1543 wxFlexGridSizer
* sizer
= new wxFlexGridSizer(2);
1544 sizer
->AddGrowableCol(0);
1545 this->SetSizer(sizer
);
1548 // Create our media control
1550 m_mediactrl
= new wxMediaCtrl();
1552 // Make sure creation was successful
1553 bool bOK
= m_mediactrl
->Create(this, wxID_MEDIACTRL
, wxEmptyString
,
1554 wxDefaultPosition
, wxDefaultSize
, 0,
1555 // you could specify a macro backend here like
1556 // wxMEDIABACKEND_WMP10);
1557 // wxT("wxPDFMediaBackend"));
1559 // you could change the cursor here like
1560 // m_mediactrl->SetCursor(wxCURSOR_BLANK);
1561 // note that this may not effect it if SetPlayerControls
1562 // is set to something else than wxMEDIACTRLPLAYERCONTROLS_NONE
1563 wxASSERT_MSG(bOK
, wxT("Could not create media control!"));
1566 sizer
->Add(m_mediactrl
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1569 // Create the playlist/listctrl
1571 m_playlist
= new wxMediaPlayerListCtrl();
1572 m_playlist
->Create(this, wxID_LISTCTRL
, wxDefaultPosition
,
1574 wxLC_REPORT
// wxLC_LIST
1577 // Set the background of our listctrl to white
1578 m_playlist
->SetBackgroundColour(wxColour(255,255,255));
1580 // The layout of the headers of the listctrl are like
1581 // | | File | Length
1583 // Where Column one is a character representing the state the file is in:
1584 // * - not the current file
1585 // E - Error has occured
1586 // > - Currently Playing
1589 // (( - Volume Down 5%
1590 // )) - Volume Up 5%
1592 // Column two is the name of the file
1594 // Column three is the length in seconds of the file
1595 m_playlist
->InsertColumn(0,_(""), wxLIST_FORMAT_CENTER
, 20);
1596 m_playlist
->InsertColumn(1,_("File"), wxLIST_FORMAT_LEFT
, /*wxLIST_AUTOSIZE_USEHEADER*/305);
1597 m_playlist
->InsertColumn(2,_("Length"), wxLIST_FORMAT_CENTER
, 75);
1599 #if wxUSE_DRAG_AND_DROP
1600 m_playlist
->SetDropTarget(new wxPlayListDropTarget(*m_playlist
));
1603 sizer
->Add(m_playlist
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1606 // Create the control buttons
1607 // TODO/FIXME/HACK: This part about sizers is really a nice hack
1608 // and probably isn't proper
1610 wxBoxSizer
* horsizer1
= new wxBoxSizer(wxHORIZONTAL
);
1611 wxBoxSizer
* vertsizer
= new wxBoxSizer(wxHORIZONTAL
);
1613 m_prevButton
= new wxButton();
1614 m_playButton
= new wxButton();
1615 m_stopButton
= new wxButton();
1616 m_nextButton
= new wxButton();
1617 m_vdButton
= new wxButton();
1618 m_vuButton
= new wxButton();
1620 m_prevButton
->Create(this, wxID_BUTTONPREV
, wxT("|<"));
1621 m_prevButton
->SetToolTip("Previous");
1622 m_playButton
->Create(this, wxID_BUTTONPLAY
, wxT(">"));
1623 m_playButton
->SetToolTip("Play");
1624 m_stopButton
->Create(this, wxID_BUTTONSTOP
, wxT("[]"));
1625 m_stopButton
->SetToolTip("Stop");
1626 m_nextButton
->Create(this, wxID_BUTTONNEXT
, wxT(">|"));
1627 m_nextButton
->SetToolTip("Next");
1628 m_vdButton
->Create(this, wxID_BUTTONVD
, wxT("(("));
1629 m_vdButton
->SetToolTip("Volume down");
1630 m_vuButton
->Create(this, wxID_BUTTONVU
, wxT("))"));
1631 m_vuButton
->SetToolTip("Volume up");
1633 vertsizer
->Add(m_prevButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1634 vertsizer
->Add(m_playButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1635 vertsizer
->Add(m_stopButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1636 vertsizer
->Add(m_nextButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1637 vertsizer
->Add(m_vdButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1638 vertsizer
->Add(m_vuButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1639 horsizer1
->Add(vertsizer
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1640 sizer
->Add(horsizer1
, 0, wxALIGN_CENTER_VERTICAL
|wxALIGN_CENTER_HORIZONTAL
|wxALL
, 5);
1644 // Create our slider
1646 m_slider
= new wxSlider(this, wxID_SLIDER
, 0, // init
1648 1, // end, dummy but must be greater than start
1649 wxDefaultPosition
, wxDefaultSize
,
1651 sizer
->Add(m_slider
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1656 m_gauge
= new wxGauge();
1657 m_gauge
->Create(this, wxID_GAUGE
, 0, wxDefaultPosition
, wxDefaultSize
,
1658 wxGA_HORIZONTAL
| wxGA_SMOOTH
);
1659 sizer
->Add(m_gauge
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1663 // Create the speed/volume sliders
1665 wxBoxSizer
* horsizer3
= new wxBoxSizer(wxHORIZONTAL
);
1667 m_volSlider
= new wxSlider(this, wxID_VOLSLIDER
, 100, // init
1670 wxDefaultPosition
, wxSize(250,20),
1672 horsizer3
->Add(m_volSlider
, 1, wxALL
, 5);
1674 m_pbSlider
= new wxSlider(this, wxID_PBSLIDER
, 4, // init
1677 wxDefaultPosition
, wxSize(250,20),
1679 horsizer3
->Add(m_pbSlider
, 1, wxALL
, 5);
1680 sizer
->Add(horsizer3
, 1, wxCENTRE
| wxALL
, 5);
1682 // Now that we have all our rows make some of them growable
1683 sizer
->AddGrowableRow(0);
1688 this->Connect( wxID_LISTCTRL
, wxEVT_COMMAND_LIST_ITEM_ACTIVATED
,
1689 wxListEventHandler(wxMediaPlayerFrame::OnChangeSong
),
1690 (wxObject
*)0, parentFrame
);
1695 this->Connect(wxID_SLIDER
, wxEVT_SCROLL_THUMBTRACK
,
1696 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnBeginSeek
));
1697 this->Connect(wxID_SLIDER
, wxEVT_SCROLL_THUMBRELEASE
,
1698 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnEndSeek
));
1699 this->Connect(wxID_PBSLIDER
, wxEVT_SCROLL_THUMBRELEASE
,
1700 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnPBChange
));
1701 this->Connect(wxID_VOLSLIDER
, wxEVT_SCROLL_THUMBRELEASE
,
1702 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnVolChange
));
1705 // Media Control events
1707 this->Connect(wxID_MEDIACTRL
, wxEVT_MEDIA_PLAY
,
1708 wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaPlay
));
1709 this->Connect(wxID_MEDIACTRL
, wxEVT_MEDIA_PAUSE
,
1710 wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaPause
));
1711 this->Connect(wxID_MEDIACTRL
, wxEVT_MEDIA_STOP
,
1712 wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaStop
));
1713 this->Connect(wxID_MEDIACTRL
, wxEVT_MEDIA_FINISHED
,
1714 wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaFinished
));
1715 this->Connect(wxID_MEDIACTRL
, wxEVT_MEDIA_LOADED
,
1716 wxMediaEventHandler(wxMediaPlayerFrame::OnMediaLoaded
),
1717 (wxObject
*)0, parentFrame
);
1722 this->Connect( wxID_BUTTONPREV
, wxEVT_COMMAND_BUTTON_CLICKED
,
1723 wxCommandEventHandler(wxMediaPlayerFrame::OnPrev
),
1724 (wxObject
*)0, parentFrame
);
1725 this->Connect( wxID_BUTTONPLAY
, wxEVT_COMMAND_BUTTON_CLICKED
,
1726 wxCommandEventHandler(wxMediaPlayerFrame::OnPlay
),
1727 (wxObject
*)0, parentFrame
);
1728 this->Connect( wxID_BUTTONSTOP
, wxEVT_COMMAND_BUTTON_CLICKED
,
1729 wxCommandEventHandler(wxMediaPlayerFrame::OnStop
),
1730 (wxObject
*)0, parentFrame
);
1731 this->Connect( wxID_BUTTONNEXT
, wxEVT_COMMAND_BUTTON_CLICKED
,
1732 wxCommandEventHandler(wxMediaPlayerFrame::OnNext
),
1733 (wxObject
*)0, parentFrame
);
1734 this->Connect( wxID_BUTTONVD
, wxEVT_COMMAND_BUTTON_CLICKED
,
1735 wxCommandEventHandler(wxMediaPlayerFrame::OnVolumeDown
),
1736 (wxObject
*)0, parentFrame
);
1737 this->Connect( wxID_BUTTONVU
, wxEVT_COMMAND_BUTTON_CLICKED
,
1738 wxCommandEventHandler(wxMediaPlayerFrame::OnVolumeUp
),
1739 (wxObject
*)0, parentFrame
);
1742 // ----------------------------------------------------------------------------
1743 // MyNotebook::OnBeginSeek
1745 // Sets m_bIsBeingDragged to true to stop the timer from changing the position
1747 // ----------------------------------------------------------------------------
1748 void wxMediaPlayerNotebookPage::OnBeginSeek(wxScrollEvent
& WXUNUSED(event
))
1750 m_bIsBeingDragged
= true;
1753 // ----------------------------------------------------------------------------
1754 // MyNotebook::OnEndSeek
1756 // Called from file->seek.
1757 // Called when the user moves the slider -
1758 // seeks to a position within the media
1759 // then sets m_bIsBeingDragged to false to ok the timer to change the position
1760 // ----------------------------------------------------------------------------
1761 void wxMediaPlayerNotebookPage::OnEndSeek(wxScrollEvent
& WXUNUSED(event
))
1763 if( m_mediactrl
->Seek(
1764 m_slider
->GetValue() * 1000
1765 ) == wxInvalidOffset
)
1766 wxMessageBox(wxT("Couldn't seek in movie!"));
1768 m_bIsBeingDragged
= false;
1771 // ----------------------------------------------------------------------------
1772 // wxMediaPlayerNotebookPage::IsBeingDragged
1774 // Returns true if the user is dragging the slider
1775 // ----------------------------------------------------------------------------
1776 bool wxMediaPlayerNotebookPage::IsBeingDragged()
1778 return m_bIsBeingDragged
;
1781 // ----------------------------------------------------------------------------
1782 // wxMediaPlayerNotebookPage::OnVolChange
1784 // Called when the user is done dragging the volume-changing slider
1785 // ----------------------------------------------------------------------------
1786 void wxMediaPlayerNotebookPage::OnVolChange(wxScrollEvent
& WXUNUSED(event
))
1788 if( m_mediactrl
->SetVolume(
1789 m_volSlider
->GetValue() / 100.0
1791 wxMessageBox(wxT("Couldn't set volume!"));
1795 // ----------------------------------------------------------------------------
1796 // wxMediaPlayerNotebookPage::OnPBChange
1798 // Called when the user is done dragging the speed-changing slider
1799 // ----------------------------------------------------------------------------
1800 void wxMediaPlayerNotebookPage::OnPBChange(wxScrollEvent
& WXUNUSED(event
))
1802 if( m_mediactrl
->SetPlaybackRate(
1803 m_pbSlider
->GetValue() * .25
1805 wxMessageBox(wxT("Couldn't set playbackrate!"));
1809 // ----------------------------------------------------------------------------
1810 // wxMediaPlayerNotebookPage::OnMediaPlay
1812 // Called when the media plays.
1813 // ----------------------------------------------------------------------------
1814 void wxMediaPlayerNotebookPage::OnMediaPlay(wxMediaEvent
& WXUNUSED(event
))
1816 m_playlist
->SetItem(m_nLastFileId
, 0, wxT(">"));
1819 // ----------------------------------------------------------------------------
1820 // wxMediaPlayerNotebookPage::OnMediaPause
1822 // Called when the media is paused.
1823 // ----------------------------------------------------------------------------
1824 void wxMediaPlayerNotebookPage::OnMediaPause(wxMediaEvent
& WXUNUSED(event
))
1826 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("||"));
1829 // ----------------------------------------------------------------------------
1830 // wxMediaPlayerNotebookPage::OnMediaStop
1832 // Called when the media stops.
1833 // ----------------------------------------------------------------------------
1834 void wxMediaPlayerNotebookPage::OnMediaStop(wxMediaEvent
& WXUNUSED(event
))
1836 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("[]"));
1839 // ----------------------------------------------------------------------------
1840 // wxMediaPlayerNotebookPage::OnMediaFinished
1842 // Called when the media finishes playing.
1843 // Here we loop it if the user wants to (has been selected from file menu)
1844 // ----------------------------------------------------------------------------
1845 void wxMediaPlayerNotebookPage::OnMediaFinished(wxMediaEvent
& WXUNUSED(event
))
1849 if ( !m_mediactrl
->Play() )
1851 wxMessageBox(wxT("Couldn't loop movie!"));
1852 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("E"));
1859 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("[]"));
1864 // End of MediaPlayer sample