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) on OS versions < 10.2.
33 // 3) On unix the video may not work - it only checks for a few video
34 // sinks - xvimagesink, ximagesink and whatever gnome preferences has -
35 // if gnome preferences is not available or you have a different video
36 // sink then those two (such as sdlvideosink) then you'll get black video
37 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
39 // ============================================================================
41 // ============================================================================
43 // ----------------------------------------------------------------------------
44 // Pre-compiled header stuff
45 // ----------------------------------------------------------------------------
47 #include "wx/wxprec.h"
57 // ----------------------------------------------------------------------------
59 // ----------------------------------------------------------------------------
61 #include "wx/mediactrl.h" //for wxMediaCtrl
62 #include "wx/filedlg.h" //for opening files from OpenFile
63 #include "wx/slider.h" //for a slider for seeking within media
64 #include "wx/sizer.h" //for positioning controls/wxBoxSizer
65 #include "wx/timer.h" //timer for updating status bar
66 #include "wx/textdlg.h" //for getting user text from OpenURL/Debug
67 #include "wx/notebook.h" //for wxNotebook and putting movies in pages
68 #include "wx/cmdline.h" //for wxCmdLineParser (optional)
69 #include "wx/listctrl.h" //for wxListCtrl
70 #include "wx/dnd.h" //drag and drop for the playlist
71 #include "wx/filename.h" //For wxFileName::GetName()
72 #include "wx/config.h" //for native wxConfig
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 || !wxUSE_DRAG_AND_DROP
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]
131 // ----------------------------------------------------------------------------
133 // ----------------------------------------------------------------------------
135 class wxMediaPlayerApp
: public wxApp
139 virtual void MacOpenFile(const wxString
& fileName
);
142 virtual bool OnInit();
145 class wxMediaPlayerFrame
* m_frame
;
148 // ----------------------------------------------------------------------------
149 // wxMediaPlayerFrame
150 // ----------------------------------------------------------------------------
152 class wxMediaPlayerFrame
: public wxFrame
156 wxMediaPlayerFrame(const wxString
& title
);
157 ~wxMediaPlayerFrame();
159 // Menu event handlers
160 void OnQuit(wxCommandEvent
& event
);
161 void OnAbout(wxCommandEvent
& event
);
163 void OnOpenFileSamePage(wxCommandEvent
& event
);
164 void OnOpenFileNewPage(wxCommandEvent
& event
);
165 void OnOpenURLSamePage(wxCommandEvent
& event
);
166 void OnOpenURLNewPage(wxCommandEvent
& event
);
167 void OnCloseCurrentPage(wxCommandEvent
& event
);
169 void OnPlay(wxCommandEvent
& event
);
170 void OnPause(wxCommandEvent
& event
);
171 void OnStop(wxCommandEvent
& event
);
172 void OnNext(wxCommandEvent
& event
);
173 void OnPrev(wxCommandEvent
& event
);
174 void OnVolumeDown(wxCommandEvent
& event
);
175 void OnVolumeUp(wxCommandEvent
& event
);
177 void OnLoop(wxCommandEvent
& event
);
178 void OnShowInterface(wxCommandEvent
& event
);
180 void OnSelectBackend(wxCommandEvent
& event
);
182 // Notebook event handlers
183 void OnPageChange(wxNotebookEvent
& event
);
185 // Key event handlers
186 void OnKeyDown(wxKeyEvent
& event
);
188 // Quickie for playing from command line
189 void AddToPlayList(const wxString
& szString
);
191 // ListCtrl event handlers
192 void OnChangeSong(wxListEvent
& event
);
194 // Media event handlers
195 void OnMediaLoaded(wxMediaEvent
& event
);
197 // Close event handlers
198 void OnClose(wxCloseEvent
& event
);
201 // Rebuild base status string (see Implementation)
204 // Common open file code
205 void OpenFile(bool bNewPage
);
206 void OpenURL(bool bNewPage
);
207 void DoOpenFile(const wxString
& path
, bool bNewPage
);
208 void DoPlayFile(const wxString
& path
);
210 class wxMediaPlayerTimer
* m_timer
; //Timer to write info to status bar
211 wxString m_basestatus
; //Base status string (see ResetStatus())
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
);
236 // Media event handlers
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 int m_nLoops
; //Number of times media has looped
252 bool m_bLoop
; //Whether we are looping or not
253 bool m_bIsBeingDragged
; //Whether the user is dragging the scroll bar
254 wxMediaPlayerFrame
* m_parentFrame
; //Main wxFrame of our sample
255 wxButton
* m_prevButton
; //Go to previous file button
256 wxButton
* m_playButton
; //Play/pause file button
257 wxButton
* m_stopButton
; //Stop playing file button
258 wxButton
* m_nextButton
; //Next file button
259 wxButton
* m_vdButton
; //Volume down button
260 wxButton
* m_vuButton
; //Volume up button
261 wxGauge
* m_gauge
; //Gauge to keep in line with slider
264 // ----------------------------------------------------------------------------
265 // wxMediaPlayerTimer
266 // ----------------------------------------------------------------------------
268 class wxMediaPlayerTimer
: public wxTimer
272 wxMediaPlayerTimer(wxMediaPlayerFrame
* frame
) {m_frame
= frame
;}
274 //Called each time the timer's timeout expires
277 wxMediaPlayerFrame
* m_frame
; //The wxMediaPlayerFrame
280 // ----------------------------------------------------------------------------
281 // wxMediaPlayerListCtrl
282 // ----------------------------------------------------------------------------
283 class wxMediaPlayerListCtrl
: public wxListCtrl
286 void AddToPlayList(const wxString
& szString
)
289 kNewItem
.SetAlign(wxLIST_FORMAT_LEFT
);
291 int nID
= this->GetItemCount();
293 kNewItem
.SetMask(wxLIST_MASK_DATA
);
294 kNewItem
.SetData(new wxString(szString
));
296 this->InsertItem(kNewItem
);
297 this->SetItem(nID
, 0, wxT("*"));
298 this->SetItem(nID
, 1, wxFileName(szString
).GetName());
302 kNewItem
.SetBackgroundColour(wxColour(192,192,192));
303 this->SetItem(kNewItem
);
307 void GetSelectedItem(wxListItem
& listitem
)
309 listitem
.SetMask(wxLIST_MASK_TEXT
| wxLIST_MASK_DATA
);
310 int nLast
= -1, nLastSelected
= -1;
311 while ((nLast
= this->GetNextItem(nLast
,
313 wxLIST_STATE_SELECTED
)) != -1)
315 listitem
.SetId(nLast
);
316 this->GetItem(listitem
);
317 if ((listitem
.GetState() & wxLIST_STATE_FOCUSED
) )
319 nLastSelected
= nLast
;
321 if (nLast
== -1 && nLastSelected
== -1)
323 listitem
.SetId(nLastSelected
== -1 ? nLast
: nLastSelected
);
324 this->GetItem(listitem
);
328 // ----------------------------------------------------------------------------
329 // wxPlayListDropTarget
331 // Drop target for playlist (i.e. user drags a file from explorer unto
332 // playlist it adds the file)
333 // ----------------------------------------------------------------------------
334 class wxPlayListDropTarget
: public wxFileDropTarget
337 wxPlayListDropTarget(wxMediaPlayerListCtrl
& list
) : m_list(list
) {}
338 ~wxPlayListDropTarget(){}
339 virtual bool OnDropFiles(wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
),
340 const wxArrayString
& files
)
342 for (size_t i
= 0; i
< files
.GetCount(); ++i
)
344 m_list
.AddToPlayList(files
[i
]);
348 wxMediaPlayerListCtrl
& m_list
;
351 // ============================================================================
355 // ============================================================================
357 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
361 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
363 // ----------------------------------------------------------------------------
364 // wxGetMediaStateText
366 // Converts a wxMediaCtrl state into something useful that we can display
368 // ----------------------------------------------------------------------------
369 const wxChar
* wxGetMediaStateText(int nState
)
373 case wxMEDIASTATE_PLAYING
:
374 return wxT("Playing");
375 case wxMEDIASTATE_STOPPED
:
376 return wxT("Stopped");
377 ///case wxMEDIASTATE_PAUSED:
379 return wxT("Paused");
383 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
387 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
389 // ----------------------------------------------------------------------------
390 // This sets up this wxApp as the global wxApp that gui calls in wxWidgets
391 // use. For example, if you were to be in windows and use a file dialog,
392 // wxWidgets would use wxTheApp->GetHInstance() which would get the instance
393 // handle of the application. These routines in wx _DO NOT_ check to see if
394 // the wxApp exists, and thus will crash the application if you try it.
396 // IMPLEMENT_APP does this, and also implements the platform-specific entry
397 // routine, such as main or WinMain(). Use IMPLEMENT_APP_NO_MAIN if you do
398 // not desire this behavior.
399 // ----------------------------------------------------------------------------
400 IMPLEMENT_APP(wxMediaPlayerApp
)
402 // ----------------------------------------------------------------------------
403 // wxMediaPlayerApp::OnInit
405 // Where execution starts - akin to a main or WinMain.
406 // 1) Create the frame and show it to the user
407 // 2) Process filenames from the commandline
408 // 3) return true specifying that we want execution to continue past OnInit
409 // ----------------------------------------------------------------------------
410 bool wxMediaPlayerApp::OnInit()
412 wxMediaPlayerFrame
*frame
=
413 new wxMediaPlayerFrame(wxT("MediaPlayer wxWidgets Sample"));
416 #if wxUSE_CMDLINE_PARSER
418 // What this does is get all the command line arguments
419 // and treat each one as a file to put to the initial playlist
421 wxCmdLineEntryDesc cmdLineDesc
[2];
422 cmdLineDesc
[0].kind
= wxCMD_LINE_PARAM
;
423 cmdLineDesc
[0].shortName
= NULL
;
424 cmdLineDesc
[0].longName
= NULL
;
425 cmdLineDesc
[0].description
= wxT("input files");
426 cmdLineDesc
[0].type
= wxCMD_LINE_VAL_STRING
;
427 cmdLineDesc
[0].flags
= wxCMD_LINE_PARAM_OPTIONAL
| wxCMD_LINE_PARAM_MULTIPLE
;
429 cmdLineDesc
[1].kind
= wxCMD_LINE_NONE
;
431 //gets the passed media files from cmd line
432 wxCmdLineParser
parser (cmdLineDesc
, argc
, argv
);
434 // get filenames from the commandline
435 if (parser
.Parse() == 0)
437 for (size_t paramNr
=0; paramNr
< parser
.GetParamCount(); ++paramNr
)
439 frame
->AddToPlayList((parser
.GetParam (paramNr
)));
441 wxCommandEvent emptyevt
;
442 frame
->OnNext(emptyevt
);
451 void wxMediaPlayerApp::MacOpenFile(const wxString
& fileName
)
453 //Called when a user drags a file over our app
454 m_frame
->DoOpenFile(fileName
, true /* new page */);
459 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
461 // wxMediaPlayerFrame
463 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
465 // ----------------------------------------------------------------------------
466 // wxMediaPlayerFrame Constructor
468 // 1) Create our menus
469 // 2) Create our notebook control and add it to the frame
470 // 3) Create our status bar
471 // 4) Connect our events
472 // 5) Start our timer
473 // ----------------------------------------------------------------------------
475 wxMediaPlayerFrame::wxMediaPlayerFrame(const wxString
& title
)
476 : wxFrame(NULL
, wxID_ANY
, title
, wxDefaultPosition
, wxSize(600,600))
481 wxMenu
*fileMenu
= new wxMenu
;
482 wxMenu
*controlsMenu
= new wxMenu
;
483 wxMenu
*optionsMenu
= new wxMenu
;
484 wxMenu
*helpMenu
= new wxMenu
;
485 wxMenu
*debugMenu
= new wxMenu
;
487 fileMenu
->Append(wxID_OPENFILESAMEPAGE
, wxT("&Open File\tCtrl-Shift-O"),
488 wxT("Open a File in the current notebook page"));
489 fileMenu
->Append(wxID_OPENFILENEWPAGE
, wxT("&Open File in a new page"),
490 wxT("Open a File in a new notebook page"));
491 fileMenu
->Append(wxID_OPENURLSAMEPAGE
, wxT("&Open URL"),
492 wxT("Open a URL in the current notebook page"));
493 fileMenu
->Append(wxID_OPENURLNEWPAGE
, wxT("&Open URL in a new page"),
494 wxT("Open a URL in a new notebook page"));
495 fileMenu
->AppendSeparator();
496 fileMenu
->Append(wxID_CLOSECURRENTPAGE
, wxT("&Close Current Page\tCtrl-C"),
497 wxT("Close current notebook page"));
498 fileMenu
->AppendSeparator();
499 fileMenu
->Append(wxID_EXIT
,
501 wxT("Quit this program"));
503 controlsMenu
->Append(wxID_PLAY
, wxT("&Play/Pause\tCtrl-P"), wxT("Resume/Pause playback"));
504 controlsMenu
->Append(wxID_STOP
, wxT("&Stop\tCtrl-S"), wxT("Stop playback"));
505 controlsMenu
->AppendSeparator();
506 controlsMenu
->Append(wxID_PREV
, wxT("&Previous\tCtrl-B"), wxT("Go to previous track"));
507 controlsMenu
->Append(wxID_NEXT
, wxT("&Next\tCtrl-N"), wxT("Skip to next track"));
509 optionsMenu
->AppendCheckItem(wxID_LOOP
,
510 wxT("&Loop\tCtrl-L"),
511 wxT("Loop Selected Media"));
512 optionsMenu
->AppendCheckItem(wxID_SHOWINTERFACE
,
513 wxT("&Show Interface\tCtrl-I"),
514 wxT("Show wxMediaCtrl native controls"));
516 debugMenu
->Append(wxID_SELECTBACKEND
,
517 wxT("&Select Backend...\tCtrl-D"),
518 wxT("Select a backend manually"));
520 helpMenu
->Append(wxID_ABOUT
,
521 wxT("&About...\tF1"),
522 wxT("Show about dialog"));
525 wxMenuBar
*menuBar
= new wxMenuBar();
526 menuBar
->Append(fileMenu
, wxT("&File"));
527 menuBar
->Append(controlsMenu
, wxT("&Controls"));
528 menuBar
->Append(optionsMenu
, wxT("&Options"));
529 menuBar
->Append(debugMenu
, wxT("&Debug"));
530 menuBar
->Append(helpMenu
, wxT("&Help"));
534 // Create our notebook - using wxNotebook is luckily pretty
535 // simple and self-explanatory in most cases
537 m_notebook
= new wxNotebook(this, wxID_NOTEBOOK
);
540 // Create our status bar
543 // create a status bar just for fun (by default with 1 pane only)
545 #endif // wxUSE_STATUSBAR
550 // There are two ways in wxWidgets to use events -
551 // Message Maps and Connections.
553 // Message Maps are implemented by putting
554 // DECLARE_MESSAGE_MAP in your wxEvtHandler-derived
555 // class you want to use for events, such as wxMediaPlayerFrame.
557 // Then after your class declaration you put
558 // BEGIN_EVENT_TABLE(wxMediaPlayerFrame, wxFrame)
562 // Where wxMediaPlayerFrame is the class with the DECLARE_MESSAGE_MAP
563 // in it. EVT_XXX(XXX) are each of your handlers, such
564 // as EVT_MENU for menu events and the XXX inside
565 // is the parameters to the event macro - in the case
566 // of EVT_MENU the menu id and then the function to call.
568 // However, with wxEvtHandler::Connect you can avoid a
569 // global message map for your class and those annoying
570 // macros. You can also change the context in which
571 // the call the handler (more later).
573 // The downside is that due to the limitation that
574 // wxWidgets doesn't use templates in certain areas,
575 // You have to triple-cast the event function.
577 // There are five parameters to wxEvtHandler::Connect -
579 // The first is the id of the instance whose events
580 // you want to handle - i.e. a menu id for menus,
581 // a control id for controls (wxControl::GetId())
584 // The second is the event id. This is the same
585 // as the message maps (EVT_MENU) except prefixed
586 // with "wx" (wxEVT_MENU).
588 // The third is the function handler for the event -
589 // You need to cast it to the specific event handler
590 // type, then to a wxEventFunction, then to a
591 // wxObjectEventFunction - I.E.
592 // (wxObjectEventFunction)(wxEventFunction)
593 // (wxCommandEventFunction) &wxMediaPlayerFrame::MyHandler
595 // Or, you can use the new (2.5.5+) event handler
596 // conversion macros - for instance the above could
598 // wxCommandEventHandler(wxMediaPlayerFrame::MyHandler)
599 // pretty simple, eh?
601 // The fourth is an optional userdata param -
602 // this is of historical relevance only and is
603 // there only for backwards compatibility.
605 // The fifth is the context in which to call the
606 // handler - by default (this param is optional)
607 // this. For example in your event handler
608 // if you were to call "this->MyFunc()"
609 // it would literally do this->MyFunc. However,
610 // if you were to pass myHandler as the fifth
611 // parameter, for instance, you would _really_
612 // be calling myHandler->MyFunc, even though
613 // the compiler doesn't really know it.
619 this->Connect(wxID_EXIT
, wxEVT_COMMAND_MENU_SELECTED
,
620 wxCommandEventHandler(wxMediaPlayerFrame::OnQuit
));
622 this->Connect(wxID_ABOUT
, wxEVT_COMMAND_MENU_SELECTED
,
623 wxCommandEventHandler(wxMediaPlayerFrame::OnAbout
));
625 this->Connect(wxID_LOOP
, wxEVT_COMMAND_MENU_SELECTED
,
626 wxCommandEventHandler(wxMediaPlayerFrame::OnLoop
));
628 this->Connect(wxID_SHOWINTERFACE
, wxEVT_COMMAND_MENU_SELECTED
,
629 wxCommandEventHandler(wxMediaPlayerFrame::OnShowInterface
));
631 this->Connect(wxID_OPENFILENEWPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
632 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileNewPage
));
634 this->Connect(wxID_OPENFILESAMEPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
635 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileSamePage
));
637 this->Connect(wxID_OPENURLNEWPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
638 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLNewPage
));
640 this->Connect(wxID_OPENURLSAMEPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
641 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLSamePage
));
643 this->Connect(wxID_CLOSECURRENTPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
644 wxCommandEventHandler(wxMediaPlayerFrame::OnCloseCurrentPage
));
646 this->Connect(wxID_PLAY
, wxEVT_COMMAND_MENU_SELECTED
,
647 wxCommandEventHandler(wxMediaPlayerFrame::OnPlay
));
649 this->Connect(wxID_STOP
, wxEVT_COMMAND_MENU_SELECTED
,
650 wxCommandEventHandler(wxMediaPlayerFrame::OnStop
));
652 this->Connect(wxID_NEXT
, wxEVT_COMMAND_MENU_SELECTED
,
653 wxCommandEventHandler(wxMediaPlayerFrame::OnNext
));
655 this->Connect(wxID_PREV
, wxEVT_COMMAND_MENU_SELECTED
,
656 wxCommandEventHandler(wxMediaPlayerFrame::OnPrev
));
658 this->Connect(wxID_SELECTBACKEND
, wxEVT_COMMAND_MENU_SELECTED
,
659 wxCommandEventHandler(wxMediaPlayerFrame::OnSelectBackend
));
664 this->Connect(wxID_NOTEBOOK
, wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED
,
665 wxNotebookEventHandler(wxMediaPlayerFrame::OnPageChange
));
670 wxTheApp
->Connect(wxID_ANY
, wxEVT_KEY_DOWN
,
671 wxKeyEventHandler(wxMediaPlayerFrame::OnKeyDown
),
677 this->Connect(wxID_ANY
, wxEVT_CLOSE_WINDOW
,
678 wxCloseEventHandler(wxMediaPlayerFrame::OnClose
));
685 // Create an initial notebook page so the user has something
686 // to work with without having to go file->open every time :).
688 wxMediaPlayerNotebookPage
* page
=
689 new wxMediaPlayerNotebookPage(this, m_notebook
);
690 m_notebook
->AddPage(page
,
695 // Here we load the our configuration -
696 // in our case we load all the files that were left in
697 // the playlist the last time the user closed our application
699 // As an exercise to the reader try modifying it so that
700 // it properly loads the playlist for each page without
701 // conflicting (loading the same data) with the other ones.
703 wxConfigBase
* conf
= wxConfigBase::Get();
704 wxString key
, outstring
;
705 for(int i
= 0; ; ++i
)
709 if(!conf
->Read(key
, &outstring
))
711 page
->m_playlist
->AddToPlayList(outstring
);
715 // Create a timer to update our status bar
717 m_timer
= new wxMediaPlayerTimer(this);
721 // ----------------------------------------------------------------------------
722 // wxMediaPlayerFrame Destructor
724 // 1) Deletes child objects implicitly
725 // 2) Delete our timer explicitly
726 // ----------------------------------------------------------------------------
727 wxMediaPlayerFrame::~wxMediaPlayerFrame()
730 // Here we save our info to the registry or whatever
731 // mechanism the OS uses.
733 // This makes it so that when mediaplayer loads up again
734 // it restores the same files that were in the playlist
735 // this time, rather than the user manually re-adding them.
737 // We need to do conf->DeleteAll() here because by default
738 // the config still contains the same files as last time
739 // so we need to clear it before writing our new ones.
741 // TODO: Maybe you could add a menu option to the
742 // options menu to delete the configuration on exit -
743 // all you'd need to do is just remove everything after
744 // conf->DeleteAll() here
746 // As an exercise to the reader, try modifying this so
747 // that it saves the data for each notebook page
749 wxMediaPlayerListCtrl
* playlist
=
750 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetPage(0))->m_playlist
;
752 wxConfigBase
* conf
= wxConfigBase::Get();
755 for(int i
= 0; i
< playlist
->GetItemCount(); ++i
)
757 wxString
* pData
= (wxString
*) playlist
->GetItemData(i
);
760 conf
->Write(s
, *(pData
));
767 // ----------------------------------------------------------------------------
768 // wxMediaPlayerFrame::OnClose
769 // ----------------------------------------------------------------------------
770 void wxMediaPlayerFrame::OnClose(wxCloseEvent
& event
)
772 event
.Skip(); //really close the frame
775 // ----------------------------------------------------------------------------
776 // wxMediaPlayerFrame::AddToPlayList
777 // ----------------------------------------------------------------------------
778 void wxMediaPlayerFrame::AddToPlayList(const wxString
& szString
)
780 wxMediaPlayerNotebookPage
* currentpage
=
781 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
783 currentpage
->m_playlist
->AddToPlayList(szString
);
787 // ----------------------------------------------------------------------------
788 // wxMediaPlayerFrame::ResetStatus
790 // Here we just make a simple status string with some useful info about
791 // the media that we won't change later - such as the length of the media.
793 // We then append some other info that changes in wxMediaPlayerTimer::Notify, then
794 // set the status bar to this text.
796 // In real applications, you'd want to find a better way to do this,
797 // such as static text controls (wxStaticText).
799 // We display info here in seconds (wxMediaCtrl uses milliseconds - that's why
800 // we divide by 1000).
802 // We also reset our loop counter here.
803 // ----------------------------------------------------------------------------
804 void wxMediaPlayerFrame::ResetStatus()
806 wxMediaCtrl
* currentMediaCtrl
=
807 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage())->m_mediactrl
;
809 m_basestatus
= wxString::Format(wxT("Size(x,y):%i,%i ")
810 wxT("Length(Seconds):%u Speed:%1.1fx"),
811 currentMediaCtrl
->GetBestSize().x
,
812 currentMediaCtrl
->GetBestSize().y
,
813 (unsigned)((currentMediaCtrl
->Length() / 1000)),
814 currentMediaCtrl
->GetPlaybackRate()
818 // ----------------------------------------------------------------------------
819 // wxMediaPlayerFrame::OnQuit
821 // Called from file->quit.
822 // Closes this application.
823 // ----------------------------------------------------------------------------
824 void wxMediaPlayerFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
826 // true is to force the frame to close
830 // ----------------------------------------------------------------------------
831 // wxMediaPlayerFrame::OnAbout
833 // Called from help->about.
834 // Gets some info about this application.
835 // ----------------------------------------------------------------------------
836 void wxMediaPlayerFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
839 msg
.Printf( wxT("This is a test of wxMediaCtrl.\n")
840 wxT("Welcome to %s"), wxVERSION_STRING
);
842 wxMessageBox(msg
, wxT("About wxMediaCtrl test"), wxOK
| wxICON_INFORMATION
, this);
845 // ----------------------------------------------------------------------------
846 // wxMediaPlayerFrame::OnLoop
848 // Called from file->loop.
849 // Changes the state of whether we want to loop or not.
850 // ----------------------------------------------------------------------------
851 void wxMediaPlayerFrame::OnLoop(wxCommandEvent
& WXUNUSED(event
))
853 wxMediaPlayerNotebookPage
* currentpage
=
854 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
856 currentpage
->m_bLoop
= !currentpage
->m_bLoop
;
859 // ----------------------------------------------------------------------------
860 // wxMediaPlayerFrame::OnLoop
862 // Called from file->loop.
863 // Changes the state of whether we want to loop or not.
864 // ----------------------------------------------------------------------------
865 void wxMediaPlayerFrame::OnShowInterface(wxCommandEvent
& event
)
867 wxMediaPlayerNotebookPage
* currentpage
=
868 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
870 if( !currentpage
->m_mediactrl
->ShowPlayerControls(event
.IsChecked() ?
871 wxMEDIACTRLPLAYERCONTROLS_DEFAULT
:
872 wxMEDIACTRLPLAYERCONTROLS_NONE
) )
874 //error - uncheck and warn user
875 wxMenuItem
* pSIItem
= GetMenuBar()->FindItem(wxID_SHOWINTERFACE
);
877 pSIItem
->Check(!event
.IsChecked());
879 if(event
.IsChecked())
880 wxMessageBox(wxT("Could not show player controls"));
882 wxMessageBox(wxT("Could not hide player controls"));
886 // ----------------------------------------------------------------------------
887 // wxMediaPlayerFrame::OnOpenFileSamePage
889 // Called from file->openfile.
890 // Opens and plays a media file in the current notebook page
891 // ----------------------------------------------------------------------------
892 void wxMediaPlayerFrame::OnOpenFileSamePage(wxCommandEvent
& WXUNUSED(event
))
897 // ----------------------------------------------------------------------------
898 // wxMediaPlayerFrame::OnOpenFileNewPage
900 // Called from file->openfileinnewpage.
901 // Opens and plays a media file in a new notebook page
902 // ----------------------------------------------------------------------------
903 void wxMediaPlayerFrame::OnOpenFileNewPage(wxCommandEvent
& WXUNUSED(event
))
908 // ----------------------------------------------------------------------------
909 // wxMediaPlayerFrame::OpenFile
911 // Opens a file dialog asking the user for a filename, then
912 // calls DoOpenFile which will add the file to the playlist and play it
913 // ----------------------------------------------------------------------------
914 void wxMediaPlayerFrame::OpenFile(bool bNewPage
)
916 wxFileDialog
fd(this);
918 if(fd
.ShowModal() == wxID_OK
)
920 DoOpenFile(fd
.GetPath(), bNewPage
);
924 // ----------------------------------------------------------------------------
925 // wxMediaPlayerFrame::DoOpenFile
927 // Adds the file to our playlist, selects it in the playlist,
928 // and then calls DoPlayFile to play it
929 // ----------------------------------------------------------------------------
930 void wxMediaPlayerFrame::DoOpenFile(const wxString
& path
, bool bNewPage
)
935 new wxMediaPlayerNotebookPage(this, m_notebook
),
940 wxMediaPlayerNotebookPage
* currentpage
=
941 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
943 if(currentpage
->m_nLastFileId
!= -1)
944 currentpage
->m_playlist
->SetItemState(currentpage
->m_nLastFileId
,
945 0, wxLIST_STATE_SELECTED
);
947 wxListItem newlistitem
;
948 newlistitem
.SetAlign(wxLIST_FORMAT_LEFT
);
952 newlistitem
.SetId(nID
= currentpage
->m_playlist
->GetItemCount());
953 newlistitem
.SetMask(wxLIST_MASK_DATA
| wxLIST_MASK_STATE
);
954 newlistitem
.SetState(wxLIST_STATE_SELECTED
);
955 newlistitem
.SetData(new wxString(path
));
957 currentpage
->m_playlist
->InsertItem(newlistitem
);
958 currentpage
->m_playlist
->SetItem(nID
, 0, wxT("*"));
959 currentpage
->m_playlist
->SetItem(nID
, 1, wxFileName(path
).GetName());
963 newlistitem
.SetBackgroundColour(wxColour(192,192,192));
964 currentpage
->m_playlist
->SetItem(newlistitem
);
970 // ----------------------------------------------------------------------------
971 // wxMediaPlayerFrame::DoPlayFile
973 // Pauses the file if its the currently playing file,
974 // otherwise it plays the file
975 // ----------------------------------------------------------------------------
976 void wxMediaPlayerFrame::DoPlayFile(const wxString
& path
)
978 wxMediaPlayerNotebookPage
* currentpage
=
979 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
982 currentpage
->m_playlist
->GetSelectedItem(listitem
);
984 if( ( listitem
.GetData() &&
985 currentpage
->m_nLastFileId
== listitem
.GetId() &&
986 currentpage
->m_szFile
.compare(path
) == 0 ) ||
987 ( !listitem
.GetData() &&
988 currentpage
->m_nLastFileId
!= -1 &&
989 currentpage
->m_szFile
.compare(path
) == 0)
992 if(currentpage
->m_mediactrl
->GetState() == wxMEDIASTATE_PLAYING
)
994 if( !currentpage
->m_mediactrl
->Pause() )
995 wxMessageBox(wxT("Couldn't pause movie!"));
997 currentpage
->m_playlist
->SetItem(
998 currentpage
->m_nLastFileId
, 0, wxT("||"));
1002 if( !currentpage
->m_mediactrl
->Play() )
1003 wxMessageBox(wxT("Couldn't play movie!"));
1005 currentpage
->m_playlist
->SetItem(
1006 currentpage
->m_nLastFileId
, 0, wxT(">"));
1011 int nNewId
= listitem
.GetData() ? listitem
.GetId() :
1012 currentpage
->m_playlist
->GetItemCount()-1;
1013 m_notebook
->SetPageText(m_notebook
->GetSelection(),
1014 wxFileName(path
).GetName());
1016 if(currentpage
->m_nLastFileId
!= -1)
1017 currentpage
->m_playlist
->SetItem(
1018 currentpage
->m_nLastFileId
, 0, wxT("*"));
1020 wxURI
uripath(path
);
1021 if( uripath
.IsReference() )
1023 if( !currentpage
->m_mediactrl
->Load(path
) )
1025 wxMessageBox(wxT("Couldn't load file!"));
1026 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("E"));
1030 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("O"));
1035 if( !currentpage
->m_mediactrl
->Load(uripath
) )
1037 wxMessageBox(wxT("Couldn't load URL!"));
1038 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("E"));
1042 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("O"));
1046 currentpage
->m_nLastFileId
= nNewId
;
1047 currentpage
->m_szFile
= path
;
1048 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
,
1049 1, wxFileName(path
).GetName());
1050 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
,
1055 // ----------------------------------------------------------------------------
1056 // wxMediaPlayerFrame::OnMediaLoaded
1058 // Called when the media is ready to be played - and does
1059 // so, also gets the length of media and shows that in the list control
1060 // ----------------------------------------------------------------------------
1061 void wxMediaPlayerFrame::OnMediaLoaded(wxMediaEvent
& WXUNUSED(evt
))
1063 wxMediaPlayerNotebookPage
* currentpage
=
1064 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1066 if( !currentpage
->m_mediactrl
->Play() )
1068 wxMessageBox(wxT("Couldn't play movie!"));
1069 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
, 0, wxT("E"));
1073 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
, 0, wxT(">"));
1076 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
,
1077 2, wxString::Format(wxT("%u"),
1078 (unsigned) currentpage
->m_mediactrl
->Length() / 1000)
1083 currentpage
->m_slider
->SetRange(0,
1084 (int)(currentpage
->m_mediactrl
->Length() / 1000));
1085 currentpage
->m_gauge
->SetRange((int)(currentpage
->m_mediactrl
->Length() / 1000));
1088 // ----------------------------------------------------------------------------
1089 // wxMediaPlayerFrame::OnSelectBackend
1091 // Little debugging routine - enter the class name of a backend and it
1092 // will use that instead of letting wxMediaCtrl search the wxMediaBackend
1094 // ----------------------------------------------------------------------------
1095 void wxMediaPlayerFrame::OnSelectBackend(wxCommandEvent
& WXUNUSED(evt
))
1097 wxString sBackend
= wxGetTextFromUser(wxT("Enter backend to use"));
1099 if(sBackend
.empty() == false) //could have been cancelled by the user
1101 int sel
= m_notebook
->GetSelection();
1103 if (sel
!= wxNOT_FOUND
)
1105 m_notebook
->DeletePage(sel
);
1108 m_notebook
->AddPage(new wxMediaPlayerNotebookPage(this, m_notebook
,
1113 ((wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage())->m_szFile
,
1118 // ----------------------------------------------------------------------------
1119 // wxMediaPlayerFrame::OnOpenURLSamePage
1121 // Called from file->openurl.
1122 // Opens and plays a media file from a URL in the current notebook page
1123 // ----------------------------------------------------------------------------
1124 void wxMediaPlayerFrame::OnOpenURLSamePage(wxCommandEvent
& WXUNUSED(event
))
1129 // ----------------------------------------------------------------------------
1130 // wxMediaPlayerFrame::OnOpenURLNewPage
1132 // Called from file->openurlinnewpage.
1133 // Opens and plays a media file from a URL in a new notebook page
1134 // ----------------------------------------------------------------------------
1135 void wxMediaPlayerFrame::OnOpenURLNewPage(wxCommandEvent
& WXUNUSED(event
))
1140 // ----------------------------------------------------------------------------
1141 // wxMediaPlayerFrame::OpenURL
1143 // Just calls DoOpenFile with the url path - which calls DoPlayFile
1144 // which handles the real dirty work
1145 // ----------------------------------------------------------------------------
1146 void wxMediaPlayerFrame::OpenURL(bool bNewPage
)
1148 wxString sUrl
= wxGetTextFromUser(
1149 wxT("Enter the URL that has the movie to play")
1152 if(sUrl
.empty() == false) //could have been cancelled by user
1154 DoOpenFile(sUrl
, bNewPage
);
1158 // ----------------------------------------------------------------------------
1159 // wxMediaPlayerFrame::OnCloseCurrentPage
1161 // Called when the user wants to close the current notebook page
1163 // 1) Get the current page number (wxControl::GetSelection)
1164 // 2) If there is no current page, break out
1165 // 3) Delete the current page
1166 // ----------------------------------------------------------------------------
1167 void wxMediaPlayerFrame::OnCloseCurrentPage(wxCommandEvent
& WXUNUSED(event
))
1169 if( m_notebook
->GetPageCount() > 1 )
1171 int sel
= m_notebook
->GetSelection();
1173 if (sel
!= wxNOT_FOUND
)
1175 m_notebook
->DeletePage(sel
);
1180 wxMessageBox(wxT("Cannot close main page"));
1184 // ----------------------------------------------------------------------------
1185 // wxMediaPlayerFrame::OnPlay
1187 // Called from file->play.
1188 // Resumes the media if it is paused or stopped.
1189 // ----------------------------------------------------------------------------
1190 void wxMediaPlayerFrame::OnPlay(wxCommandEvent
& WXUNUSED(event
))
1192 wxMediaPlayerNotebookPage
* currentpage
=
1193 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1195 wxListItem listitem
;
1196 currentpage
->m_playlist
->GetSelectedItem(listitem
);
1197 if ( !listitem
.GetData() )
1200 if ((nLast
= currentpage
->m_playlist
->GetNextItem(nLast
,
1202 wxLIST_STATE_DONTCARE
)) == -1)
1205 wxMessageBox(wxT("No items in playlist!"));
1209 listitem
.SetId(nLast
);
1210 currentpage
->m_playlist
->GetItem(listitem
);
1211 listitem
.SetMask(listitem
.GetMask() | wxLIST_MASK_STATE
);
1212 listitem
.SetState(listitem
.GetState() | wxLIST_STATE_SELECTED
);
1213 currentpage
->m_playlist
->SetItem(listitem
);
1214 wxASSERT(listitem
.GetData());
1215 DoPlayFile((*((wxString
*) listitem
.GetData())));
1220 wxASSERT(listitem
.GetData());
1221 DoPlayFile((*((wxString
*) listitem
.GetData())));
1225 // ----------------------------------------------------------------------------
1226 // wxMediaPlayerFrame::OnKeyDown
1228 // Deletes all selected files from the playlist if the backspace key is pressed
1229 // ----------------------------------------------------------------------------
1230 void wxMediaPlayerFrame::OnKeyDown(wxKeyEvent
& event
)
1232 if(event
.GetKeyCode() == WXK_BACK
/*DELETE*/)
1234 wxMediaPlayerNotebookPage
* currentpage
=
1235 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1236 //delete all selected items
1239 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(
1240 -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1241 if (nSelectedItem
== -1)
1244 wxListItem listitem
;
1245 listitem
.SetId(nSelectedItem
);
1246 currentpage
->m_playlist
->GetItem(listitem
);
1247 delete (wxString
*) listitem
.GetData();
1249 currentpage
->m_playlist
->DeleteItem(nSelectedItem
);
1253 //Could be wxGetTextFromUser or something else important
1254 if(event
.GetEventObject() != this)
1258 // ----------------------------------------------------------------------------
1259 // wxMediaPlayerFrame::OnStop
1261 // Called from file->stop.
1262 // Where it stops depends on whether you can seek in the
1263 // media control or not - if you can it stops and seeks to the beginning,
1264 // otherwise it will appear to be at the end - but it will start over again
1265 // when Play() is called
1266 // ----------------------------------------------------------------------------
1267 void wxMediaPlayerFrame::OnStop(wxCommandEvent
& WXUNUSED(evt
))
1269 wxMediaPlayerNotebookPage
* currentpage
=
1270 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1272 if( !currentpage
->m_mediactrl
->Stop() )
1273 wxMessageBox(wxT("Couldn't stop movie!"));
1275 currentpage
->m_playlist
->SetItem(
1276 currentpage
->m_nLastFileId
, 0, wxT("[]"));
1280 // ----------------------------------------------------------------------------
1281 // wxMediaPlayerFrame::OnChangeSong
1283 // Routine that plays the currently selected file in the playlist.
1284 // Called when the user actives the song from the playlist,
1285 // and from other various places in the sample
1286 // ----------------------------------------------------------------------------
1287 void wxMediaPlayerFrame::OnChangeSong(wxListEvent
& WXUNUSED(evt
))
1289 wxMediaPlayerNotebookPage
* currentpage
=
1290 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1292 wxListItem listitem
;
1293 currentpage
->m_playlist
->GetSelectedItem(listitem
);
1294 if(listitem
.GetData())
1295 DoPlayFile((*((wxString
*) listitem
.GetData())));
1297 wxMessageBox(wxT("No selected item!"));
1300 // ----------------------------------------------------------------------------
1301 // wxMediaPlayerFrame::OnPrev
1303 // Tedious wxListCtrl stuff. Goes to prevous song in list, or if at the
1304 // beginning goes to the last in the list.
1305 // ----------------------------------------------------------------------------
1306 void wxMediaPlayerFrame::OnPrev(wxCommandEvent
& WXUNUSED(event
))
1308 wxMediaPlayerNotebookPage
* currentpage
=
1309 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1311 if (currentpage
->m_playlist
->GetItemCount() == 0)
1314 wxInt32 nLastSelectedItem
= -1;
1317 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(nLastSelectedItem
,
1318 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1319 if (nSelectedItem
== -1)
1321 nLastSelectedItem
= nSelectedItem
;
1322 currentpage
->m_playlist
->SetItemState(nSelectedItem
, 0, wxLIST_STATE_SELECTED
);
1325 if (nLastSelectedItem
== -1)
1327 //nothing selected, default to the file before the currently playing one
1328 if(currentpage
->m_nLastFileId
== 0)
1329 nLastSelectedItem
= currentpage
->m_playlist
->GetItemCount() - 1;
1331 nLastSelectedItem
= currentpage
->m_nLastFileId
- 1;
1333 else if (nLastSelectedItem
== 0)
1334 nLastSelectedItem
= currentpage
->m_playlist
->GetItemCount() - 1;
1336 nLastSelectedItem
-= 1;
1338 if(nLastSelectedItem
== currentpage
->m_nLastFileId
)
1339 return; //already playing... nothing to do
1341 wxListItem listitem
;
1342 listitem
.SetId(nLastSelectedItem
);
1343 listitem
.SetMask(wxLIST_MASK_TEXT
| wxLIST_MASK_DATA
);
1344 currentpage
->m_playlist
->GetItem(listitem
);
1345 listitem
.SetMask(listitem
.GetMask() | wxLIST_MASK_STATE
);
1346 listitem
.SetState(listitem
.GetState() | wxLIST_STATE_SELECTED
);
1347 currentpage
->m_playlist
->SetItem(listitem
);
1349 wxASSERT(listitem
.GetData());
1350 DoPlayFile((*((wxString
*) listitem
.GetData())));
1353 // ----------------------------------------------------------------------------
1354 // wxMediaPlayerFrame::OnNext
1356 // Tedious wxListCtrl stuff. Goes to next song in list, or if at the
1357 // end goes to the first in the list.
1358 // ----------------------------------------------------------------------------
1359 void wxMediaPlayerFrame::OnNext(wxCommandEvent
& WXUNUSED(event
))
1361 wxMediaPlayerNotebookPage
* currentpage
=
1362 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1364 if (currentpage
->m_playlist
->GetItemCount() == 0)
1367 wxInt32 nLastSelectedItem
= -1;
1370 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(nLastSelectedItem
,
1371 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1372 if (nSelectedItem
== -1)
1374 nLastSelectedItem
= nSelectedItem
;
1375 currentpage
->m_playlist
->SetItemState(nSelectedItem
, 0, wxLIST_STATE_SELECTED
);
1378 if (nLastSelectedItem
== -1)
1380 if(currentpage
->m_nLastFileId
== currentpage
->m_playlist
->GetItemCount() - 1)
1381 nLastSelectedItem
= 0;
1383 nLastSelectedItem
= currentpage
->m_nLastFileId
+ 1;
1385 else if (nLastSelectedItem
== currentpage
->m_playlist
->GetItemCount() - 1)
1386 nLastSelectedItem
= 0;
1388 nLastSelectedItem
+= 1;
1390 if(nLastSelectedItem
== currentpage
->m_nLastFileId
)
1391 return; //already playing... nothing to do
1393 wxListItem listitem
;
1394 listitem
.SetMask(wxLIST_MASK_TEXT
| wxLIST_MASK_DATA
);
1395 listitem
.SetId(nLastSelectedItem
);
1396 currentpage
->m_playlist
->GetItem(listitem
);
1397 listitem
.SetMask(listitem
.GetMask() | wxLIST_MASK_STATE
);
1398 listitem
.SetState(listitem
.GetState() | wxLIST_STATE_SELECTED
);
1399 currentpage
->m_playlist
->SetItem(listitem
);
1401 wxASSERT(listitem
.GetData());
1402 DoPlayFile((*((wxString
*) listitem
.GetData())));
1406 // ----------------------------------------------------------------------------
1407 // wxMediaPlayerFrame::OnVolumeDown
1409 // Lowers the volume of the media control by 10%
1410 // ----------------------------------------------------------------------------
1411 void wxMediaPlayerFrame::OnVolumeDown(wxCommandEvent
& WXUNUSED(event
))
1413 wxMediaPlayerNotebookPage
* currentpage
=
1414 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1416 double dVolume
= currentpage
->m_mediactrl
->GetVolume();
1417 currentpage
->m_mediactrl
->SetVolume(dVolume
< 0.1 ? 0.0 : dVolume
- .1);
1420 // ----------------------------------------------------------------------------
1421 // wxMediaPlayerFrame::OnVolumeUp
1423 // Increases the volume of the media control by 10%
1424 // ----------------------------------------------------------------------------
1425 void wxMediaPlayerFrame::OnVolumeUp(wxCommandEvent
& WXUNUSED(event
))
1427 wxMediaPlayerNotebookPage
* currentpage
=
1428 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1430 double dVolume
= currentpage
->m_mediactrl
->GetVolume();
1431 currentpage
->m_mediactrl
->SetVolume(dVolume
> 0.9 ? 1.0 : dVolume
+ .1);
1434 // ----------------------------------------------------------------------------
1435 // wxMediaPlayerFrame::OnPageChange
1437 // Called when the user changes the current notebook page shown
1438 // ----------------------------------------------------------------------------
1439 void wxMediaPlayerFrame::OnPageChange(wxNotebookEvent
& WXUNUSED(event
))
1444 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1446 // wxMediaPlayerTimer
1448 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1450 // ----------------------------------------------------------------------------
1451 // wxMediaPlayerTimer::Notify
1453 // 1) Update our slider with the position were are in in the media
1454 // 2) Update our status bar with the base text from wxMediaPlayerFrame::ResetStatus,
1455 // append some non-static (changing) info to it, then set the
1456 // status bar text to that result
1457 // ----------------------------------------------------------------------------
1458 void wxMediaPlayerTimer::Notify()
1460 wxMediaPlayerNotebookPage
* currentpage
=
1461 (wxMediaPlayerNotebookPage
*) m_frame
->m_notebook
->GetCurrentPage();
1465 // if the slider is being dragged then update it with the song position
1466 if(currentpage
->IsBeingDragged() == false)
1468 long lPosition
= (long)( currentpage
->m_mediactrl
->Tell() / 1000 );
1469 currentpage
->m_slider
->SetValue(lPosition
);
1472 // update guage with value from slider
1473 currentpage
->m_gauge
->SetValue(currentpage
->m_slider
->GetValue());
1475 m_frame
->SetStatusText(wxString::Format(
1476 wxT("%s Pos:%u State:%s Loops:%i D/T:[%i]/[%i] V:%i%%"),
1477 m_frame
->m_basestatus
.c_str(),
1478 currentpage
->m_slider
->GetValue(),
1479 wxGetMediaStateText(currentpage
->m_mediactrl
->GetState()),
1480 currentpage
->m_nLoops
,
1481 (int)currentpage
->m_mediactrl
->GetDownloadProgress(),
1482 (int)currentpage
->m_mediactrl
->GetDownloadTotal(),
1483 (int)(currentpage
->m_mediactrl
->GetVolume() * 100)));
1484 #endif // wxUSE_STATUSBAR
1489 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1491 // wxMediaPlayerNotebookPage
1493 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1495 // ----------------------------------------------------------------------------
1496 // wxMediaPlayerNotebookPage Constructor
1498 // Creates a media control and slider and adds it to this panel,
1499 // along with some sizers for positioning
1500 // ----------------------------------------------------------------------------
1501 wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame
* parentFrame
,
1502 wxNotebook
* theBook
,
1503 const wxString
& szBackend
)
1504 : wxPanel(theBook
, wxID_ANY
),
1508 m_bIsBeingDragged(false),
1509 m_parentFrame(parentFrame
)
1517 // [5 control buttons]
1523 // Create and attach the sizer
1525 wxFlexGridSizer
* sizer
= new wxFlexGridSizer(2, 1, 0, 0);
1526 this->SetSizer(sizer
);
1527 this->SetAutoLayout(true);
1528 sizer
->AddGrowableRow(0);
1529 sizer
->AddGrowableCol(0);
1532 // Create our media control
1534 m_mediactrl
= new wxMediaCtrl();
1536 // Make sure creation was successful
1537 bool bOK
= m_mediactrl
->Create(this, wxID_MEDIACTRL
, wxEmptyString
,
1538 wxDefaultPosition
, wxDefaultSize
, 0,
1539 //you could specify a macrod backend here like
1540 //wxMEDIABACKEND_QUICKTIME);
1542 //you could change the cursor here like
1543 // m_mediactrl->SetCursor(wxCURSOR_BLANK);
1544 //note that this may not effect it if SetPlayerControls
1545 //is set to something else than wxMEDIACTRLPLAYERCONTROLS_NONE
1546 wxASSERT_MSG(bOK
, wxT("Could not create media control!"));
1549 sizer
->Add(m_mediactrl
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1552 // Create the playlist/listctrl
1554 m_playlist
= new wxMediaPlayerListCtrl();
1555 m_playlist
->Create(this, wxID_LISTCTRL
, wxDefaultPosition
,
1557 wxLC_REPORT
//wxLC_LIST
1560 // Set the background of our listctrl to white
1561 m_playlist
->SetBackgroundColour(wxColour(255,255,255));
1563 // The layout of the headers of the listctrl are like
1564 // | | File | Length
1566 // Where Column one is a character representing the state the file is in:
1567 // * - not the current file
1568 // E - Error has occured
1569 // > - Currently Playing
1572 // (( - Volume Down 10%
1573 // )) - Volume Up 10%
1575 // Column two is the name of the file
1577 // Column three is the length in seconds of the file
1578 m_playlist
->InsertColumn(0,_(""), wxLIST_FORMAT_CENTER
, 20);
1579 m_playlist
->InsertColumn(1,_("File"), wxLIST_FORMAT_LEFT
, /*wxLIST_AUTOSIZE_USEHEADER*/305);
1580 m_playlist
->InsertColumn(2,_("Length"), wxLIST_FORMAT_CENTER
, 75);
1582 m_playlist
->SetDropTarget(new wxPlayListDropTarget(*m_playlist
));
1583 sizer
->Add(m_playlist
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1586 // Create the control buttons
1587 // TODO/FIXME/HACK: This part about sizers is really a nice hack
1588 // and probably isn't proper
1590 wxBoxSizer
* horsizer1
= new wxBoxSizer(wxHORIZONTAL
);
1591 wxBoxSizer
* vertsizer
= new wxBoxSizer(wxHORIZONTAL
);
1593 m_prevButton
= new wxButton();
1594 m_playButton
= new wxButton();
1595 m_stopButton
= new wxButton();
1596 m_nextButton
= new wxButton();
1597 m_vdButton
= new wxButton();
1598 m_vuButton
= new wxButton();
1600 m_prevButton
->Create(this, wxID_BUTTONPREV
, wxT("|<"));
1601 m_playButton
->Create(this, wxID_BUTTONPLAY
, wxT(">"));
1602 m_stopButton
->Create(this, wxID_BUTTONSTOP
, wxT("[]"));
1603 m_nextButton
->Create(this, wxID_BUTTONNEXT
, wxT(">|"));
1604 m_vdButton
->Create(this, wxID_BUTTONVD
, wxT("(("));
1605 m_vuButton
->Create(this, wxID_BUTTONVU
, wxT("))"));
1606 vertsizer
->Add(m_prevButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1607 vertsizer
->Add(m_playButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1608 vertsizer
->Add(m_stopButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1609 vertsizer
->Add(m_nextButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1610 vertsizer
->Add(m_vdButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1611 vertsizer
->Add(m_vuButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1612 horsizer1
->Add(vertsizer
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1613 sizer
->Add(horsizer1
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1617 // Create our slider
1619 m_slider
= new wxSlider(this, wxID_SLIDER
, 0, //init
1622 wxDefaultPosition
, wxDefaultSize
,
1624 sizer
->Add(m_slider
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1630 m_gauge
= new wxGauge();
1631 m_gauge
->Create(this, wxID_GAUGE
, 0, wxDefaultPosition
, wxDefaultSize
,
1632 wxGA_HORIZONTAL
| wxGA_SMOOTH
);
1633 sizer
->Add(m_gauge
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1638 this->Connect( wxID_LISTCTRL
, wxEVT_COMMAND_LIST_ITEM_ACTIVATED
,
1639 wxListEventHandler(wxMediaPlayerFrame::OnChangeSong
),
1640 (wxObject
*)0, parentFrame
);
1645 this->Connect(wxID_SLIDER
, wxEVT_SCROLL_THUMBTRACK
,
1646 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnBeginSeek
));
1647 this->Connect(wxID_SLIDER
, wxEVT_SCROLL_THUMBRELEASE
,
1648 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnEndSeek
));
1651 // Media Control events
1653 this->Connect(wxID_MEDIACTRL
, wxEVT_MEDIA_FINISHED
,
1654 wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaFinished
));
1655 this->Connect(wxID_MEDIACTRL
, wxEVT_MEDIA_LOADED
,
1656 wxMediaEventHandler(wxMediaPlayerFrame::OnMediaLoaded
),
1657 (wxObject
*)0, parentFrame
);
1662 this->Connect( wxID_BUTTONPREV
, wxEVT_COMMAND_BUTTON_CLICKED
,
1663 wxCommandEventHandler(wxMediaPlayerFrame::OnPrev
),
1664 (wxObject
*)0, parentFrame
);
1665 this->Connect( wxID_BUTTONPLAY
, wxEVT_COMMAND_BUTTON_CLICKED
,
1666 wxCommandEventHandler(wxMediaPlayerFrame::OnPlay
),
1667 (wxObject
*)0, parentFrame
);
1668 this->Connect( wxID_BUTTONSTOP
, wxEVT_COMMAND_BUTTON_CLICKED
,
1669 wxCommandEventHandler(wxMediaPlayerFrame::OnStop
),
1670 (wxObject
*)0, parentFrame
);
1671 this->Connect( wxID_BUTTONNEXT
, wxEVT_COMMAND_BUTTON_CLICKED
,
1672 wxCommandEventHandler(wxMediaPlayerFrame::OnNext
),
1673 (wxObject
*)0, parentFrame
);
1674 this->Connect( wxID_BUTTONVD
, wxEVT_COMMAND_BUTTON_CLICKED
,
1675 wxCommandEventHandler(wxMediaPlayerFrame::OnVolumeDown
),
1676 (wxObject
*)0, parentFrame
);
1677 this->Connect( wxID_BUTTONVU
, wxEVT_COMMAND_BUTTON_CLICKED
,
1678 wxCommandEventHandler(wxMediaPlayerFrame::OnVolumeUp
),
1679 (wxObject
*)0, parentFrame
);
1682 // ----------------------------------------------------------------------------
1683 // MyNotebook::OnBeginSeek
1685 // Sets m_bIsBeingDragged to true to stop the timer from changing the position
1687 // ----------------------------------------------------------------------------
1688 void wxMediaPlayerNotebookPage::OnBeginSeek(wxScrollEvent
& WXUNUSED(event
))
1690 m_bIsBeingDragged
= true;
1693 // ----------------------------------------------------------------------------
1694 // MyNotebook::OnEndSeek
1696 // Called from file->seek.
1697 // Called when the user moves the slider -
1698 // seeks to a position within the media
1699 // then sets m_bIsBeingDragged to false to ok the timer to change the position
1700 // ----------------------------------------------------------------------------
1701 void wxMediaPlayerNotebookPage::OnEndSeek(wxScrollEvent
& WXUNUSED(event
))
1703 if( m_mediactrl
->Seek(
1704 m_slider
->GetValue() * 1000
1705 ) == wxInvalidOffset
)
1706 wxMessageBox(wxT("Couldn't seek in movie!"));
1708 m_bIsBeingDragged
= false;
1711 // ----------------------------------------------------------------------------
1712 // wxMediaPlayerNotebookPage::IsBeingDragged
1714 // Returns true if the user is dragging the slider
1715 // ----------------------------------------------------------------------------
1716 bool wxMediaPlayerNotebookPage::IsBeingDragged()
1718 return m_bIsBeingDragged
;
1721 // ----------------------------------------------------------------------------
1724 // Called when the media stops playing.
1725 // Here we loop it if the user wants to (has been selected from file menu)
1726 // ----------------------------------------------------------------------------
1727 void wxMediaPlayerNotebookPage::OnMediaFinished(wxMediaEvent
& WXUNUSED(event
))
1731 if ( !m_mediactrl
->Play() )
1733 wxMessageBox(wxT("Couldn't loop movie!"));
1734 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("E"));
1741 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("[]"));
1746 // End of MediaPlayer sample