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
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 #if wxUSE_DRAG_AND_DROP
335 class wxPlayListDropTarget
: public wxFileDropTarget
338 wxPlayListDropTarget(wxMediaPlayerListCtrl
& list
) : m_list(list
) {}
339 ~wxPlayListDropTarget(){}
340 virtual bool OnDropFiles(wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
),
341 const wxArrayString
& files
)
343 for (size_t i
= 0; i
< files
.GetCount(); ++i
)
345 m_list
.AddToPlayList(files
[i
]);
349 wxMediaPlayerListCtrl
& m_list
;
353 // ============================================================================
357 // ============================================================================
359 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
363 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
365 // ----------------------------------------------------------------------------
366 // wxGetMediaStateText
368 // Converts a wxMediaCtrl state into something useful that we can display
370 // ----------------------------------------------------------------------------
371 const wxChar
* wxGetMediaStateText(int nState
)
375 case wxMEDIASTATE_PLAYING
:
376 return wxT("Playing");
377 case wxMEDIASTATE_STOPPED
:
378 return wxT("Stopped");
379 ///case wxMEDIASTATE_PAUSED:
381 return wxT("Paused");
385 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
389 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
391 // ----------------------------------------------------------------------------
392 // This sets up this wxApp as the global wxApp that gui calls in wxWidgets
393 // use. For example, if you were to be in windows and use a file dialog,
394 // wxWidgets would use wxTheApp->GetHInstance() which would get the instance
395 // handle of the application. These routines in wx _DO NOT_ check to see if
396 // the wxApp exists, and thus will crash the application if you try it.
398 // IMPLEMENT_APP does this, and also implements the platform-specific entry
399 // routine, such as main or WinMain(). Use IMPLEMENT_APP_NO_MAIN if you do
400 // not desire this behavior.
401 // ----------------------------------------------------------------------------
402 IMPLEMENT_APP(wxMediaPlayerApp
)
404 // ----------------------------------------------------------------------------
405 // wxMediaPlayerApp::OnInit
407 // Where execution starts - akin to a main or WinMain.
408 // 1) Create the frame and show it to the user
409 // 2) Process filenames from the commandline
410 // 3) return true specifying that we want execution to continue past OnInit
411 // ----------------------------------------------------------------------------
412 bool wxMediaPlayerApp::OnInit()
414 wxMediaPlayerFrame
*frame
=
415 new wxMediaPlayerFrame(wxT("MediaPlayer wxWidgets Sample"));
418 #if wxUSE_CMDLINE_PARSER
420 // What this does is get all the command line arguments
421 // and treat each one as a file to put to the initial playlist
423 wxCmdLineEntryDesc cmdLineDesc
[2];
424 cmdLineDesc
[0].kind
= wxCMD_LINE_PARAM
;
425 cmdLineDesc
[0].shortName
= NULL
;
426 cmdLineDesc
[0].longName
= NULL
;
427 cmdLineDesc
[0].description
= wxT("input files");
428 cmdLineDesc
[0].type
= wxCMD_LINE_VAL_STRING
;
429 cmdLineDesc
[0].flags
= wxCMD_LINE_PARAM_OPTIONAL
| wxCMD_LINE_PARAM_MULTIPLE
;
431 cmdLineDesc
[1].kind
= wxCMD_LINE_NONE
;
433 //gets the passed media files from cmd line
434 wxCmdLineParser
parser (cmdLineDesc
, argc
, argv
);
436 // get filenames from the commandline
437 if (parser
.Parse() == 0)
439 for (size_t paramNr
=0; paramNr
< parser
.GetParamCount(); ++paramNr
)
441 frame
->AddToPlayList((parser
.GetParam (paramNr
)));
443 wxCommandEvent emptyevt
;
444 frame
->OnNext(emptyevt
);
453 void wxMediaPlayerApp::MacOpenFile(const wxString
& fileName
)
455 //Called when a user drags a file over our app
456 m_frame
->DoOpenFile(fileName
, true /* new page */);
461 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
463 // wxMediaPlayerFrame
465 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
467 // ----------------------------------------------------------------------------
468 // wxMediaPlayerFrame Constructor
470 // 1) Create our menus
471 // 2) Create our notebook control and add it to the frame
472 // 3) Create our status bar
473 // 4) Connect our events
474 // 5) Start our timer
475 // ----------------------------------------------------------------------------
477 wxMediaPlayerFrame::wxMediaPlayerFrame(const wxString
& title
)
478 : wxFrame(NULL
, wxID_ANY
, title
, wxDefaultPosition
, wxSize(600,600))
483 wxMenu
*fileMenu
= new wxMenu
;
484 wxMenu
*controlsMenu
= new wxMenu
;
485 wxMenu
*optionsMenu
= new wxMenu
;
486 wxMenu
*helpMenu
= new wxMenu
;
487 wxMenu
*debugMenu
= new wxMenu
;
489 fileMenu
->Append(wxID_OPENFILESAMEPAGE
, wxT("&Open File\tCtrl-Shift-O"),
490 wxT("Open a File in the current notebook page"));
491 fileMenu
->Append(wxID_OPENFILENEWPAGE
, wxT("&Open File in a new page"),
492 wxT("Open a File in a new notebook page"));
493 fileMenu
->Append(wxID_OPENURLSAMEPAGE
, wxT("&Open URL"),
494 wxT("Open a URL in the current notebook page"));
495 fileMenu
->Append(wxID_OPENURLNEWPAGE
, wxT("&Open URL in a new page"),
496 wxT("Open a URL in a new notebook page"));
497 fileMenu
->AppendSeparator();
498 fileMenu
->Append(wxID_CLOSECURRENTPAGE
, wxT("&Close Current Page\tCtrl-C"),
499 wxT("Close current notebook page"));
500 fileMenu
->AppendSeparator();
501 fileMenu
->Append(wxID_EXIT
,
503 wxT("Quit this program"));
505 controlsMenu
->Append(wxID_PLAY
, wxT("&Play/Pause\tCtrl-P"), wxT("Resume/Pause playback"));
506 controlsMenu
->Append(wxID_STOP
, wxT("&Stop\tCtrl-S"), wxT("Stop playback"));
507 controlsMenu
->AppendSeparator();
508 controlsMenu
->Append(wxID_PREV
, wxT("&Previous\tCtrl-B"), wxT("Go to previous track"));
509 controlsMenu
->Append(wxID_NEXT
, wxT("&Next\tCtrl-N"), wxT("Skip to next track"));
511 optionsMenu
->AppendCheckItem(wxID_LOOP
,
512 wxT("&Loop\tCtrl-L"),
513 wxT("Loop Selected Media"));
514 optionsMenu
->AppendCheckItem(wxID_SHOWINTERFACE
,
515 wxT("&Show Interface\tCtrl-I"),
516 wxT("Show wxMediaCtrl native controls"));
518 debugMenu
->Append(wxID_SELECTBACKEND
,
519 wxT("&Select Backend...\tCtrl-D"),
520 wxT("Select a backend manually"));
522 helpMenu
->Append(wxID_ABOUT
,
523 wxT("&About...\tF1"),
524 wxT("Show about dialog"));
527 wxMenuBar
*menuBar
= new wxMenuBar();
528 menuBar
->Append(fileMenu
, wxT("&File"));
529 menuBar
->Append(controlsMenu
, wxT("&Controls"));
530 menuBar
->Append(optionsMenu
, wxT("&Options"));
531 menuBar
->Append(debugMenu
, wxT("&Debug"));
532 menuBar
->Append(helpMenu
, wxT("&Help"));
536 // Create our notebook - using wxNotebook is luckily pretty
537 // simple and self-explanatory in most cases
539 m_notebook
= new wxNotebook(this, wxID_NOTEBOOK
);
542 // Create our status bar
545 // create a status bar just for fun (by default with 1 pane only)
547 #endif // wxUSE_STATUSBAR
552 // There are two ways in wxWidgets to use events -
553 // Message Maps and Connections.
555 // Message Maps are implemented by putting
556 // DECLARE_MESSAGE_MAP in your wxEvtHandler-derived
557 // class you want to use for events, such as wxMediaPlayerFrame.
559 // Then after your class declaration you put
560 // BEGIN_EVENT_TABLE(wxMediaPlayerFrame, wxFrame)
564 // Where wxMediaPlayerFrame is the class with the DECLARE_MESSAGE_MAP
565 // in it. EVT_XXX(XXX) are each of your handlers, such
566 // as EVT_MENU for menu events and the XXX inside
567 // is the parameters to the event macro - in the case
568 // of EVT_MENU the menu id and then the function to call.
570 // However, with wxEvtHandler::Connect you can avoid a
571 // global message map for your class and those annoying
572 // macros. You can also change the context in which
573 // the call the handler (more later).
575 // The downside is that due to the limitation that
576 // wxWidgets doesn't use templates in certain areas,
577 // You have to triple-cast the event function.
579 // There are five parameters to wxEvtHandler::Connect -
581 // The first is the id of the instance whose events
582 // you want to handle - i.e. a menu id for menus,
583 // a control id for controls (wxControl::GetId())
586 // The second is the event id. This is the same
587 // as the message maps (EVT_MENU) except prefixed
588 // with "wx" (wxEVT_MENU).
590 // The third is the function handler for the event -
591 // You need to cast it to the specific event handler
592 // type, then to a wxEventFunction, then to a
593 // wxObjectEventFunction - I.E.
594 // (wxObjectEventFunction)(wxEventFunction)
595 // (wxCommandEventFunction) &wxMediaPlayerFrame::MyHandler
597 // Or, you can use the new (2.5.5+) event handler
598 // conversion macros - for instance the above could
600 // wxCommandEventHandler(wxMediaPlayerFrame::MyHandler)
601 // pretty simple, eh?
603 // The fourth is an optional userdata param -
604 // this is of historical relevance only and is
605 // there only for backwards compatibility.
607 // The fifth is the context in which to call the
608 // handler - by default (this param is optional)
609 // this. For example in your event handler
610 // if you were to call "this->MyFunc()"
611 // it would literally do this->MyFunc. However,
612 // if you were to pass myHandler as the fifth
613 // parameter, for instance, you would _really_
614 // be calling myHandler->MyFunc, even though
615 // the compiler doesn't really know it.
621 this->Connect(wxID_EXIT
, wxEVT_COMMAND_MENU_SELECTED
,
622 wxCommandEventHandler(wxMediaPlayerFrame::OnQuit
));
624 this->Connect(wxID_ABOUT
, wxEVT_COMMAND_MENU_SELECTED
,
625 wxCommandEventHandler(wxMediaPlayerFrame::OnAbout
));
627 this->Connect(wxID_LOOP
, wxEVT_COMMAND_MENU_SELECTED
,
628 wxCommandEventHandler(wxMediaPlayerFrame::OnLoop
));
630 this->Connect(wxID_SHOWINTERFACE
, wxEVT_COMMAND_MENU_SELECTED
,
631 wxCommandEventHandler(wxMediaPlayerFrame::OnShowInterface
));
633 this->Connect(wxID_OPENFILENEWPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
634 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileNewPage
));
636 this->Connect(wxID_OPENFILESAMEPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
637 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileSamePage
));
639 this->Connect(wxID_OPENURLNEWPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
640 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLNewPage
));
642 this->Connect(wxID_OPENURLSAMEPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
643 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLSamePage
));
645 this->Connect(wxID_CLOSECURRENTPAGE
, wxEVT_COMMAND_MENU_SELECTED
,
646 wxCommandEventHandler(wxMediaPlayerFrame::OnCloseCurrentPage
));
648 this->Connect(wxID_PLAY
, wxEVT_COMMAND_MENU_SELECTED
,
649 wxCommandEventHandler(wxMediaPlayerFrame::OnPlay
));
651 this->Connect(wxID_STOP
, wxEVT_COMMAND_MENU_SELECTED
,
652 wxCommandEventHandler(wxMediaPlayerFrame::OnStop
));
654 this->Connect(wxID_NEXT
, wxEVT_COMMAND_MENU_SELECTED
,
655 wxCommandEventHandler(wxMediaPlayerFrame::OnNext
));
657 this->Connect(wxID_PREV
, wxEVT_COMMAND_MENU_SELECTED
,
658 wxCommandEventHandler(wxMediaPlayerFrame::OnPrev
));
660 this->Connect(wxID_SELECTBACKEND
, wxEVT_COMMAND_MENU_SELECTED
,
661 wxCommandEventHandler(wxMediaPlayerFrame::OnSelectBackend
));
666 this->Connect(wxID_NOTEBOOK
, wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED
,
667 wxNotebookEventHandler(wxMediaPlayerFrame::OnPageChange
));
672 wxTheApp
->Connect(wxID_ANY
, wxEVT_KEY_DOWN
,
673 wxKeyEventHandler(wxMediaPlayerFrame::OnKeyDown
),
679 this->Connect(wxID_ANY
, wxEVT_CLOSE_WINDOW
,
680 wxCloseEventHandler(wxMediaPlayerFrame::OnClose
));
687 // Create an initial notebook page so the user has something
688 // to work with without having to go file->open every time :).
690 wxMediaPlayerNotebookPage
* page
=
691 new wxMediaPlayerNotebookPage(this, m_notebook
);
692 m_notebook
->AddPage(page
,
697 // Here we load the our configuration -
698 // in our case we load all the files that were left in
699 // the playlist the last time the user closed our application
701 // As an exercise to the reader try modifying it so that
702 // it properly loads the playlist for each page without
703 // conflicting (loading the same data) with the other ones.
705 wxConfigBase
* conf
= wxConfigBase::Get();
706 wxString key
, outstring
;
707 for(int i
= 0; ; ++i
)
711 if(!conf
->Read(key
, &outstring
))
713 page
->m_playlist
->AddToPlayList(outstring
);
717 // Create a timer to update our status bar
719 m_timer
= new wxMediaPlayerTimer(this);
723 // ----------------------------------------------------------------------------
724 // wxMediaPlayerFrame Destructor
726 // 1) Deletes child objects implicitly
727 // 2) Delete our timer explicitly
728 // ----------------------------------------------------------------------------
729 wxMediaPlayerFrame::~wxMediaPlayerFrame()
732 // Here we save our info to the registry or whatever
733 // mechanism the OS uses.
735 // This makes it so that when mediaplayer loads up again
736 // it restores the same files that were in the playlist
737 // this time, rather than the user manually re-adding them.
739 // We need to do conf->DeleteAll() here because by default
740 // the config still contains the same files as last time
741 // so we need to clear it before writing our new ones.
743 // TODO: Maybe you could add a menu option to the
744 // options menu to delete the configuration on exit -
745 // all you'd need to do is just remove everything after
746 // conf->DeleteAll() here
748 // As an exercise to the reader, try modifying this so
749 // that it saves the data for each notebook page
751 wxMediaPlayerListCtrl
* playlist
=
752 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetPage(0))->m_playlist
;
754 wxConfigBase
* conf
= wxConfigBase::Get();
757 for(int i
= 0; i
< playlist
->GetItemCount(); ++i
)
759 wxString
* pData
= (wxString
*) playlist
->GetItemData(i
);
762 conf
->Write(s
, *(pData
));
769 // ----------------------------------------------------------------------------
770 // wxMediaPlayerFrame::OnClose
771 // ----------------------------------------------------------------------------
772 void wxMediaPlayerFrame::OnClose(wxCloseEvent
& event
)
774 event
.Skip(); //really close the frame
777 // ----------------------------------------------------------------------------
778 // wxMediaPlayerFrame::AddToPlayList
779 // ----------------------------------------------------------------------------
780 void wxMediaPlayerFrame::AddToPlayList(const wxString
& szString
)
782 wxMediaPlayerNotebookPage
* currentpage
=
783 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
785 currentpage
->m_playlist
->AddToPlayList(szString
);
789 // ----------------------------------------------------------------------------
790 // wxMediaPlayerFrame::ResetStatus
792 // Here we just make a simple status string with some useful info about
793 // the media that we won't change later - such as the length of the media.
795 // We then append some other info that changes in wxMediaPlayerTimer::Notify, then
796 // set the status bar to this text.
798 // In real applications, you'd want to find a better way to do this,
799 // such as static text controls (wxStaticText).
801 // We display info here in seconds (wxMediaCtrl uses milliseconds - that's why
802 // we divide by 1000).
804 // We also reset our loop counter here.
805 // ----------------------------------------------------------------------------
806 void wxMediaPlayerFrame::ResetStatus()
808 wxMediaCtrl
* currentMediaCtrl
=
809 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage())->m_mediactrl
;
811 m_basestatus
= wxString::Format(wxT("Size(x,y):%i,%i ")
812 wxT("Length(Seconds):%u Speed:%1.1fx"),
813 currentMediaCtrl
->GetBestSize().x
,
814 currentMediaCtrl
->GetBestSize().y
,
815 (unsigned)((currentMediaCtrl
->Length() / 1000)),
816 currentMediaCtrl
->GetPlaybackRate()
820 // ----------------------------------------------------------------------------
821 // wxMediaPlayerFrame::OnQuit
823 // Called from file->quit.
824 // Closes this application.
825 // ----------------------------------------------------------------------------
826 void wxMediaPlayerFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
828 // true is to force the frame to close
832 // ----------------------------------------------------------------------------
833 // wxMediaPlayerFrame::OnAbout
835 // Called from help->about.
836 // Gets some info about this application.
837 // ----------------------------------------------------------------------------
838 void wxMediaPlayerFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
841 msg
.Printf( wxT("This is a test of wxMediaCtrl.\n")
842 wxT("Welcome to %s"), wxVERSION_STRING
);
844 wxMessageBox(msg
, wxT("About wxMediaCtrl test"), wxOK
| wxICON_INFORMATION
, this);
847 // ----------------------------------------------------------------------------
848 // wxMediaPlayerFrame::OnLoop
850 // Called from file->loop.
851 // Changes the state of whether we want to loop or not.
852 // ----------------------------------------------------------------------------
853 void wxMediaPlayerFrame::OnLoop(wxCommandEvent
& WXUNUSED(event
))
855 wxMediaPlayerNotebookPage
* currentpage
=
856 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
858 currentpage
->m_bLoop
= !currentpage
->m_bLoop
;
861 // ----------------------------------------------------------------------------
862 // wxMediaPlayerFrame::OnLoop
864 // Called from file->loop.
865 // Changes the state of whether we want to loop or not.
866 // ----------------------------------------------------------------------------
867 void wxMediaPlayerFrame::OnShowInterface(wxCommandEvent
& event
)
869 wxMediaPlayerNotebookPage
* currentpage
=
870 ((wxMediaPlayerNotebookPage
*)m_notebook
->GetCurrentPage());
872 if( !currentpage
->m_mediactrl
->ShowPlayerControls(event
.IsChecked() ?
873 wxMEDIACTRLPLAYERCONTROLS_DEFAULT
:
874 wxMEDIACTRLPLAYERCONTROLS_NONE
) )
876 //error - uncheck and warn user
877 wxMenuItem
* pSIItem
= GetMenuBar()->FindItem(wxID_SHOWINTERFACE
);
879 pSIItem
->Check(!event
.IsChecked());
881 if(event
.IsChecked())
882 wxMessageBox(wxT("Could not show player controls"));
884 wxMessageBox(wxT("Could not hide player controls"));
888 // ----------------------------------------------------------------------------
889 // wxMediaPlayerFrame::OnOpenFileSamePage
891 // Called from file->openfile.
892 // Opens and plays a media file in the current notebook page
893 // ----------------------------------------------------------------------------
894 void wxMediaPlayerFrame::OnOpenFileSamePage(wxCommandEvent
& WXUNUSED(event
))
899 // ----------------------------------------------------------------------------
900 // wxMediaPlayerFrame::OnOpenFileNewPage
902 // Called from file->openfileinnewpage.
903 // Opens and plays a media file in a new notebook page
904 // ----------------------------------------------------------------------------
905 void wxMediaPlayerFrame::OnOpenFileNewPage(wxCommandEvent
& WXUNUSED(event
))
910 // ----------------------------------------------------------------------------
911 // wxMediaPlayerFrame::OpenFile
913 // Opens a file dialog asking the user for a filename, then
914 // calls DoOpenFile which will add the file to the playlist and play it
915 // ----------------------------------------------------------------------------
916 void wxMediaPlayerFrame::OpenFile(bool bNewPage
)
918 wxFileDialog
fd(this);
920 if(fd
.ShowModal() == wxID_OK
)
922 DoOpenFile(fd
.GetPath(), bNewPage
);
926 // ----------------------------------------------------------------------------
927 // wxMediaPlayerFrame::DoOpenFile
929 // Adds the file to our playlist, selects it in the playlist,
930 // and then calls DoPlayFile to play it
931 // ----------------------------------------------------------------------------
932 void wxMediaPlayerFrame::DoOpenFile(const wxString
& path
, bool bNewPage
)
937 new wxMediaPlayerNotebookPage(this, m_notebook
),
942 wxMediaPlayerNotebookPage
* currentpage
=
943 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
945 if(currentpage
->m_nLastFileId
!= -1)
946 currentpage
->m_playlist
->SetItemState(currentpage
->m_nLastFileId
,
947 0, wxLIST_STATE_SELECTED
);
949 wxListItem newlistitem
;
950 newlistitem
.SetAlign(wxLIST_FORMAT_LEFT
);
954 newlistitem
.SetId(nID
= currentpage
->m_playlist
->GetItemCount());
955 newlistitem
.SetMask(wxLIST_MASK_DATA
| wxLIST_MASK_STATE
);
956 newlistitem
.SetState(wxLIST_STATE_SELECTED
);
957 newlistitem
.SetData(new wxString(path
));
959 currentpage
->m_playlist
->InsertItem(newlistitem
);
960 currentpage
->m_playlist
->SetItem(nID
, 0, wxT("*"));
961 currentpage
->m_playlist
->SetItem(nID
, 1, wxFileName(path
).GetName());
965 newlistitem
.SetBackgroundColour(wxColour(192,192,192));
966 currentpage
->m_playlist
->SetItem(newlistitem
);
972 // ----------------------------------------------------------------------------
973 // wxMediaPlayerFrame::DoPlayFile
975 // Pauses the file if its the currently playing file,
976 // otherwise it plays the file
977 // ----------------------------------------------------------------------------
978 void wxMediaPlayerFrame::DoPlayFile(const wxString
& path
)
980 wxMediaPlayerNotebookPage
* currentpage
=
981 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
984 currentpage
->m_playlist
->GetSelectedItem(listitem
);
986 if( ( listitem
.GetData() &&
987 currentpage
->m_nLastFileId
== listitem
.GetId() &&
988 currentpage
->m_szFile
.compare(path
) == 0 ) ||
989 ( !listitem
.GetData() &&
990 currentpage
->m_nLastFileId
!= -1 &&
991 currentpage
->m_szFile
.compare(path
) == 0)
994 if(currentpage
->m_mediactrl
->GetState() == wxMEDIASTATE_PLAYING
)
996 if( !currentpage
->m_mediactrl
->Pause() )
997 wxMessageBox(wxT("Couldn't pause movie!"));
999 currentpage
->m_playlist
->SetItem(
1000 currentpage
->m_nLastFileId
, 0, wxT("||"));
1004 if( !currentpage
->m_mediactrl
->Play() )
1005 wxMessageBox(wxT("Couldn't play movie!"));
1007 currentpage
->m_playlist
->SetItem(
1008 currentpage
->m_nLastFileId
, 0, wxT(">"));
1013 int nNewId
= listitem
.GetData() ? listitem
.GetId() :
1014 currentpage
->m_playlist
->GetItemCount()-1;
1015 m_notebook
->SetPageText(m_notebook
->GetSelection(),
1016 wxFileName(path
).GetName());
1018 if(currentpage
->m_nLastFileId
!= -1)
1019 currentpage
->m_playlist
->SetItem(
1020 currentpage
->m_nLastFileId
, 0, wxT("*"));
1022 wxURI
uripath(path
);
1023 if( uripath
.IsReference() )
1025 if( !currentpage
->m_mediactrl
->Load(path
) )
1027 wxMessageBox(wxT("Couldn't load file!"));
1028 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("E"));
1032 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("O"));
1037 if( !currentpage
->m_mediactrl
->Load(uripath
) )
1039 wxMessageBox(wxT("Couldn't load URL!"));
1040 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("E"));
1044 currentpage
->m_playlist
->SetItem(nNewId
, 0, wxT("O"));
1048 currentpage
->m_nLastFileId
= nNewId
;
1049 currentpage
->m_szFile
= path
;
1050 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
,
1051 1, wxFileName(path
).GetName());
1052 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
,
1057 // ----------------------------------------------------------------------------
1058 // wxMediaPlayerFrame::OnMediaLoaded
1060 // Called when the media is ready to be played - and does
1061 // so, also gets the length of media and shows that in the list control
1062 // ----------------------------------------------------------------------------
1063 void wxMediaPlayerFrame::OnMediaLoaded(wxMediaEvent
& WXUNUSED(evt
))
1065 wxMediaPlayerNotebookPage
* currentpage
=
1066 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1068 if( !currentpage
->m_mediactrl
->Play() )
1070 wxMessageBox(wxT("Couldn't play movie!"));
1071 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
, 0, wxT("E"));
1075 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
, 0, wxT(">"));
1078 currentpage
->m_playlist
->SetItem(currentpage
->m_nLastFileId
,
1079 2, wxString::Format(wxT("%u"),
1080 (unsigned) currentpage
->m_mediactrl
->Length() / 1000)
1085 currentpage
->m_slider
->SetRange(0,
1086 (int)(currentpage
->m_mediactrl
->Length() / 1000));
1087 currentpage
->m_gauge
->SetRange((int)(currentpage
->m_mediactrl
->Length() / 1000));
1090 // ----------------------------------------------------------------------------
1091 // wxMediaPlayerFrame::OnSelectBackend
1093 // Little debugging routine - enter the class name of a backend and it
1094 // will use that instead of letting wxMediaCtrl search the wxMediaBackend
1096 // ----------------------------------------------------------------------------
1097 void wxMediaPlayerFrame::OnSelectBackend(wxCommandEvent
& WXUNUSED(evt
))
1099 wxString sBackend
= wxGetTextFromUser(wxT("Enter backend to use"));
1101 if(sBackend
.empty() == false) //could have been cancelled by the user
1103 int sel
= m_notebook
->GetSelection();
1105 if (sel
!= wxNOT_FOUND
)
1107 m_notebook
->DeletePage(sel
);
1110 m_notebook
->AddPage(new wxMediaPlayerNotebookPage(this, m_notebook
,
1115 ((wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage())->m_szFile
,
1120 // ----------------------------------------------------------------------------
1121 // wxMediaPlayerFrame::OnOpenURLSamePage
1123 // Called from file->openurl.
1124 // Opens and plays a media file from a URL in the current notebook page
1125 // ----------------------------------------------------------------------------
1126 void wxMediaPlayerFrame::OnOpenURLSamePage(wxCommandEvent
& WXUNUSED(event
))
1131 // ----------------------------------------------------------------------------
1132 // wxMediaPlayerFrame::OnOpenURLNewPage
1134 // Called from file->openurlinnewpage.
1135 // Opens and plays a media file from a URL in a new notebook page
1136 // ----------------------------------------------------------------------------
1137 void wxMediaPlayerFrame::OnOpenURLNewPage(wxCommandEvent
& WXUNUSED(event
))
1142 // ----------------------------------------------------------------------------
1143 // wxMediaPlayerFrame::OpenURL
1145 // Just calls DoOpenFile with the url path - which calls DoPlayFile
1146 // which handles the real dirty work
1147 // ----------------------------------------------------------------------------
1148 void wxMediaPlayerFrame::OpenURL(bool bNewPage
)
1150 wxString sUrl
= wxGetTextFromUser(
1151 wxT("Enter the URL that has the movie to play")
1154 if(sUrl
.empty() == false) //could have been cancelled by user
1156 DoOpenFile(sUrl
, bNewPage
);
1160 // ----------------------------------------------------------------------------
1161 // wxMediaPlayerFrame::OnCloseCurrentPage
1163 // Called when the user wants to close the current notebook page
1165 // 1) Get the current page number (wxControl::GetSelection)
1166 // 2) If there is no current page, break out
1167 // 3) Delete the current page
1168 // ----------------------------------------------------------------------------
1169 void wxMediaPlayerFrame::OnCloseCurrentPage(wxCommandEvent
& WXUNUSED(event
))
1171 if( m_notebook
->GetPageCount() > 1 )
1173 int sel
= m_notebook
->GetSelection();
1175 if (sel
!= wxNOT_FOUND
)
1177 m_notebook
->DeletePage(sel
);
1182 wxMessageBox(wxT("Cannot close main page"));
1186 // ----------------------------------------------------------------------------
1187 // wxMediaPlayerFrame::OnPlay
1189 // Called from file->play.
1190 // Resumes the media if it is paused or stopped.
1191 // ----------------------------------------------------------------------------
1192 void wxMediaPlayerFrame::OnPlay(wxCommandEvent
& WXUNUSED(event
))
1194 wxMediaPlayerNotebookPage
* currentpage
=
1195 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1197 wxListItem listitem
;
1198 currentpage
->m_playlist
->GetSelectedItem(listitem
);
1199 if ( !listitem
.GetData() )
1202 if ((nLast
= currentpage
->m_playlist
->GetNextItem(nLast
,
1204 wxLIST_STATE_DONTCARE
)) == -1)
1207 wxMessageBox(wxT("No items in playlist!"));
1211 listitem
.SetId(nLast
);
1212 currentpage
->m_playlist
->GetItem(listitem
);
1213 listitem
.SetMask(listitem
.GetMask() | wxLIST_MASK_STATE
);
1214 listitem
.SetState(listitem
.GetState() | wxLIST_STATE_SELECTED
);
1215 currentpage
->m_playlist
->SetItem(listitem
);
1216 wxASSERT(listitem
.GetData());
1217 DoPlayFile((*((wxString
*) listitem
.GetData())));
1222 wxASSERT(listitem
.GetData());
1223 DoPlayFile((*((wxString
*) listitem
.GetData())));
1227 // ----------------------------------------------------------------------------
1228 // wxMediaPlayerFrame::OnKeyDown
1230 // Deletes all selected files from the playlist if the backspace key is pressed
1231 // ----------------------------------------------------------------------------
1232 void wxMediaPlayerFrame::OnKeyDown(wxKeyEvent
& event
)
1234 if(event
.GetKeyCode() == WXK_BACK
/*DELETE*/)
1236 wxMediaPlayerNotebookPage
* currentpage
=
1237 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1238 //delete all selected items
1241 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(
1242 -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1243 if (nSelectedItem
== -1)
1246 wxListItem listitem
;
1247 listitem
.SetId(nSelectedItem
);
1248 currentpage
->m_playlist
->GetItem(listitem
);
1249 delete (wxString
*) listitem
.GetData();
1251 currentpage
->m_playlist
->DeleteItem(nSelectedItem
);
1255 //Could be wxGetTextFromUser or something else important
1256 if(event
.GetEventObject() != this)
1260 // ----------------------------------------------------------------------------
1261 // wxMediaPlayerFrame::OnStop
1263 // Called from file->stop.
1264 // Where it stops depends on whether you can seek in the
1265 // media control or not - if you can it stops and seeks to the beginning,
1266 // otherwise it will appear to be at the end - but it will start over again
1267 // when Play() is called
1268 // ----------------------------------------------------------------------------
1269 void wxMediaPlayerFrame::OnStop(wxCommandEvent
& WXUNUSED(evt
))
1271 wxMediaPlayerNotebookPage
* currentpage
=
1272 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1274 if( !currentpage
->m_mediactrl
->Stop() )
1275 wxMessageBox(wxT("Couldn't stop movie!"));
1277 currentpage
->m_playlist
->SetItem(
1278 currentpage
->m_nLastFileId
, 0, wxT("[]"));
1282 // ----------------------------------------------------------------------------
1283 // wxMediaPlayerFrame::OnChangeSong
1285 // Routine that plays the currently selected file in the playlist.
1286 // Called when the user actives the song from the playlist,
1287 // and from other various places in the sample
1288 // ----------------------------------------------------------------------------
1289 void wxMediaPlayerFrame::OnChangeSong(wxListEvent
& WXUNUSED(evt
))
1291 wxMediaPlayerNotebookPage
* currentpage
=
1292 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1294 wxListItem listitem
;
1295 currentpage
->m_playlist
->GetSelectedItem(listitem
);
1296 if(listitem
.GetData())
1297 DoPlayFile((*((wxString
*) listitem
.GetData())));
1299 wxMessageBox(wxT("No selected item!"));
1302 // ----------------------------------------------------------------------------
1303 // wxMediaPlayerFrame::OnPrev
1305 // Tedious wxListCtrl stuff. Goes to prevous song in list, or if at the
1306 // beginning goes to the last in the list.
1307 // ----------------------------------------------------------------------------
1308 void wxMediaPlayerFrame::OnPrev(wxCommandEvent
& WXUNUSED(event
))
1310 wxMediaPlayerNotebookPage
* currentpage
=
1311 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1313 if (currentpage
->m_playlist
->GetItemCount() == 0)
1316 wxInt32 nLastSelectedItem
= -1;
1319 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(nLastSelectedItem
,
1320 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1321 if (nSelectedItem
== -1)
1323 nLastSelectedItem
= nSelectedItem
;
1324 currentpage
->m_playlist
->SetItemState(nSelectedItem
, 0, wxLIST_STATE_SELECTED
);
1327 if (nLastSelectedItem
== -1)
1329 //nothing selected, default to the file before the currently playing one
1330 if(currentpage
->m_nLastFileId
== 0)
1331 nLastSelectedItem
= currentpage
->m_playlist
->GetItemCount() - 1;
1333 nLastSelectedItem
= currentpage
->m_nLastFileId
- 1;
1335 else if (nLastSelectedItem
== 0)
1336 nLastSelectedItem
= currentpage
->m_playlist
->GetItemCount() - 1;
1338 nLastSelectedItem
-= 1;
1340 if(nLastSelectedItem
== currentpage
->m_nLastFileId
)
1341 return; //already playing... nothing to do
1343 wxListItem listitem
;
1344 listitem
.SetId(nLastSelectedItem
);
1345 listitem
.SetMask(wxLIST_MASK_TEXT
| wxLIST_MASK_DATA
);
1346 currentpage
->m_playlist
->GetItem(listitem
);
1347 listitem
.SetMask(listitem
.GetMask() | wxLIST_MASK_STATE
);
1348 listitem
.SetState(listitem
.GetState() | wxLIST_STATE_SELECTED
);
1349 currentpage
->m_playlist
->SetItem(listitem
);
1351 wxASSERT(listitem
.GetData());
1352 DoPlayFile((*((wxString
*) listitem
.GetData())));
1355 // ----------------------------------------------------------------------------
1356 // wxMediaPlayerFrame::OnNext
1358 // Tedious wxListCtrl stuff. Goes to next song in list, or if at the
1359 // end goes to the first in the list.
1360 // ----------------------------------------------------------------------------
1361 void wxMediaPlayerFrame::OnNext(wxCommandEvent
& WXUNUSED(event
))
1363 wxMediaPlayerNotebookPage
* currentpage
=
1364 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1366 if (currentpage
->m_playlist
->GetItemCount() == 0)
1369 wxInt32 nLastSelectedItem
= -1;
1372 wxInt32 nSelectedItem
= currentpage
->m_playlist
->GetNextItem(nLastSelectedItem
,
1373 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1374 if (nSelectedItem
== -1)
1376 nLastSelectedItem
= nSelectedItem
;
1377 currentpage
->m_playlist
->SetItemState(nSelectedItem
, 0, wxLIST_STATE_SELECTED
);
1380 if (nLastSelectedItem
== -1)
1382 if(currentpage
->m_nLastFileId
== currentpage
->m_playlist
->GetItemCount() - 1)
1383 nLastSelectedItem
= 0;
1385 nLastSelectedItem
= currentpage
->m_nLastFileId
+ 1;
1387 else if (nLastSelectedItem
== currentpage
->m_playlist
->GetItemCount() - 1)
1388 nLastSelectedItem
= 0;
1390 nLastSelectedItem
+= 1;
1392 if(nLastSelectedItem
== currentpage
->m_nLastFileId
)
1393 return; //already playing... nothing to do
1395 wxListItem listitem
;
1396 listitem
.SetMask(wxLIST_MASK_TEXT
| wxLIST_MASK_DATA
);
1397 listitem
.SetId(nLastSelectedItem
);
1398 currentpage
->m_playlist
->GetItem(listitem
);
1399 listitem
.SetMask(listitem
.GetMask() | wxLIST_MASK_STATE
);
1400 listitem
.SetState(listitem
.GetState() | wxLIST_STATE_SELECTED
);
1401 currentpage
->m_playlist
->SetItem(listitem
);
1403 wxASSERT(listitem
.GetData());
1404 DoPlayFile((*((wxString
*) listitem
.GetData())));
1408 // ----------------------------------------------------------------------------
1409 // wxMediaPlayerFrame::OnVolumeDown
1411 // Lowers the volume of the media control by 10%
1412 // ----------------------------------------------------------------------------
1413 void wxMediaPlayerFrame::OnVolumeDown(wxCommandEvent
& WXUNUSED(event
))
1415 wxMediaPlayerNotebookPage
* currentpage
=
1416 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1418 double dVolume
= currentpage
->m_mediactrl
->GetVolume();
1419 currentpage
->m_mediactrl
->SetVolume(dVolume
< 0.1 ? 0.0 : dVolume
- .1);
1422 // ----------------------------------------------------------------------------
1423 // wxMediaPlayerFrame::OnVolumeUp
1425 // Increases the volume of the media control by 10%
1426 // ----------------------------------------------------------------------------
1427 void wxMediaPlayerFrame::OnVolumeUp(wxCommandEvent
& WXUNUSED(event
))
1429 wxMediaPlayerNotebookPage
* currentpage
=
1430 (wxMediaPlayerNotebookPage
*) m_notebook
->GetCurrentPage();
1432 double dVolume
= currentpage
->m_mediactrl
->GetVolume();
1433 currentpage
->m_mediactrl
->SetVolume(dVolume
> 0.9 ? 1.0 : dVolume
+ .1);
1436 // ----------------------------------------------------------------------------
1437 // wxMediaPlayerFrame::OnPageChange
1439 // Called when the user changes the current notebook page shown
1440 // ----------------------------------------------------------------------------
1441 void wxMediaPlayerFrame::OnPageChange(wxNotebookEvent
& WXUNUSED(event
))
1446 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1448 // wxMediaPlayerTimer
1450 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1452 // ----------------------------------------------------------------------------
1453 // wxMediaPlayerTimer::Notify
1455 // 1) Update our slider with the position were are in in the media
1456 // 2) Update our status bar with the base text from wxMediaPlayerFrame::ResetStatus,
1457 // append some non-static (changing) info to it, then set the
1458 // status bar text to that result
1459 // ----------------------------------------------------------------------------
1460 void wxMediaPlayerTimer::Notify()
1462 wxMediaPlayerNotebookPage
* currentpage
=
1463 (wxMediaPlayerNotebookPage
*) m_frame
->m_notebook
->GetCurrentPage();
1467 // if the slider is being dragged then update it with the song position
1468 if(currentpage
->IsBeingDragged() == false)
1470 long lPosition
= (long)( currentpage
->m_mediactrl
->Tell() / 1000 );
1471 currentpage
->m_slider
->SetValue(lPosition
);
1474 // update guage with value from slider
1475 currentpage
->m_gauge
->SetValue(currentpage
->m_slider
->GetValue());
1477 m_frame
->SetStatusText(wxString::Format(
1478 wxT("%s Pos:%u State:%s Loops:%i D/T:[%i]/[%i] V:%i%%"),
1479 m_frame
->m_basestatus
.c_str(),
1480 currentpage
->m_slider
->GetValue(),
1481 wxGetMediaStateText(currentpage
->m_mediactrl
->GetState()),
1482 currentpage
->m_nLoops
,
1483 (int)currentpage
->m_mediactrl
->GetDownloadProgress(),
1484 (int)currentpage
->m_mediactrl
->GetDownloadTotal(),
1485 (int)(currentpage
->m_mediactrl
->GetVolume() * 100)));
1486 #endif // wxUSE_STATUSBAR
1491 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1493 // wxMediaPlayerNotebookPage
1495 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1497 // ----------------------------------------------------------------------------
1498 // wxMediaPlayerNotebookPage Constructor
1500 // Creates a media control and slider and adds it to this panel,
1501 // along with some sizers for positioning
1502 // ----------------------------------------------------------------------------
1503 wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame
* parentFrame
,
1504 wxNotebook
* theBook
,
1505 const wxString
& szBackend
)
1506 : wxPanel(theBook
, wxID_ANY
),
1510 m_bIsBeingDragged(false),
1511 m_parentFrame(parentFrame
)
1519 // [5 control buttons]
1525 // Create and attach the sizer
1527 wxFlexGridSizer
* sizer
= new wxFlexGridSizer(2, 1, 0, 0);
1528 this->SetSizer(sizer
);
1529 this->SetAutoLayout(true);
1530 sizer
->AddGrowableRow(0);
1531 sizer
->AddGrowableCol(0);
1534 // Create our media control
1536 m_mediactrl
= new wxMediaCtrl();
1538 // Make sure creation was successful
1539 bool bOK
= m_mediactrl
->Create(this, wxID_MEDIACTRL
, wxEmptyString
,
1540 wxDefaultPosition
, wxDefaultSize
, 0,
1541 //you could specify a macrod backend here like
1542 //wxMEDIABACKEND_QUICKTIME);
1544 //you could change the cursor here like
1545 // m_mediactrl->SetCursor(wxCURSOR_BLANK);
1546 //note that this may not effect it if SetPlayerControls
1547 //is set to something else than wxMEDIACTRLPLAYERCONTROLS_NONE
1548 wxASSERT_MSG(bOK
, wxT("Could not create media control!"));
1551 sizer
->Add(m_mediactrl
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1554 // Create the playlist/listctrl
1556 m_playlist
= new wxMediaPlayerListCtrl();
1557 m_playlist
->Create(this, wxID_LISTCTRL
, wxDefaultPosition
,
1559 wxLC_REPORT
//wxLC_LIST
1562 // Set the background of our listctrl to white
1563 m_playlist
->SetBackgroundColour(wxColour(255,255,255));
1565 // The layout of the headers of the listctrl are like
1566 // | | File | Length
1568 // Where Column one is a character representing the state the file is in:
1569 // * - not the current file
1570 // E - Error has occured
1571 // > - Currently Playing
1574 // (( - Volume Down 10%
1575 // )) - Volume Up 10%
1577 // Column two is the name of the file
1579 // Column three is the length in seconds of the file
1580 m_playlist
->InsertColumn(0,_(""), wxLIST_FORMAT_CENTER
, 20);
1581 m_playlist
->InsertColumn(1,_("File"), wxLIST_FORMAT_LEFT
, /*wxLIST_AUTOSIZE_USEHEADER*/305);
1582 m_playlist
->InsertColumn(2,_("Length"), wxLIST_FORMAT_CENTER
, 75);
1584 #if wxUSE_DRAG_AND_DROP
1585 m_playlist
->SetDropTarget(new wxPlayListDropTarget(*m_playlist
));
1588 sizer
->Add(m_playlist
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1591 // Create the control buttons
1592 // TODO/FIXME/HACK: This part about sizers is really a nice hack
1593 // and probably isn't proper
1595 wxBoxSizer
* horsizer1
= new wxBoxSizer(wxHORIZONTAL
);
1596 wxBoxSizer
* vertsizer
= new wxBoxSizer(wxHORIZONTAL
);
1598 m_prevButton
= new wxButton();
1599 m_playButton
= new wxButton();
1600 m_stopButton
= new wxButton();
1601 m_nextButton
= new wxButton();
1602 m_vdButton
= new wxButton();
1603 m_vuButton
= new wxButton();
1605 m_prevButton
->Create(this, wxID_BUTTONPREV
, wxT("|<"));
1606 m_playButton
->Create(this, wxID_BUTTONPLAY
, wxT(">"));
1607 m_stopButton
->Create(this, wxID_BUTTONSTOP
, wxT("[]"));
1608 m_nextButton
->Create(this, wxID_BUTTONNEXT
, wxT(">|"));
1609 m_vdButton
->Create(this, wxID_BUTTONVD
, wxT("(("));
1610 m_vuButton
->Create(this, wxID_BUTTONVU
, wxT("))"));
1611 vertsizer
->Add(m_prevButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1612 vertsizer
->Add(m_playButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1613 vertsizer
->Add(m_stopButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1614 vertsizer
->Add(m_nextButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1615 vertsizer
->Add(m_vdButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1616 vertsizer
->Add(m_vuButton
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1617 horsizer1
->Add(vertsizer
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1618 sizer
->Add(horsizer1
, 0, wxALIGN_CENTER_VERTICAL
|wxALL
, 5);
1622 // Create our slider
1624 m_slider
= new wxSlider(this, wxID_SLIDER
, 0, //init
1627 wxDefaultPosition
, wxDefaultSize
,
1629 sizer
->Add(m_slider
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1635 m_gauge
= new wxGauge();
1636 m_gauge
->Create(this, wxID_GAUGE
, 0, wxDefaultPosition
, wxDefaultSize
,
1637 wxGA_HORIZONTAL
| wxGA_SMOOTH
);
1638 sizer
->Add(m_gauge
, 0, wxALIGN_CENTER_HORIZONTAL
|wxALL
|wxEXPAND
, 5);
1643 this->Connect( wxID_LISTCTRL
, wxEVT_COMMAND_LIST_ITEM_ACTIVATED
,
1644 wxListEventHandler(wxMediaPlayerFrame::OnChangeSong
),
1645 (wxObject
*)0, parentFrame
);
1650 this->Connect(wxID_SLIDER
, wxEVT_SCROLL_THUMBTRACK
,
1651 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnBeginSeek
));
1652 this->Connect(wxID_SLIDER
, wxEVT_SCROLL_THUMBRELEASE
,
1653 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnEndSeek
));
1656 // Media Control events
1658 this->Connect(wxID_MEDIACTRL
, wxEVT_MEDIA_FINISHED
,
1659 wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaFinished
));
1660 this->Connect(wxID_MEDIACTRL
, wxEVT_MEDIA_LOADED
,
1661 wxMediaEventHandler(wxMediaPlayerFrame::OnMediaLoaded
),
1662 (wxObject
*)0, parentFrame
);
1667 this->Connect( wxID_BUTTONPREV
, wxEVT_COMMAND_BUTTON_CLICKED
,
1668 wxCommandEventHandler(wxMediaPlayerFrame::OnPrev
),
1669 (wxObject
*)0, parentFrame
);
1670 this->Connect( wxID_BUTTONPLAY
, wxEVT_COMMAND_BUTTON_CLICKED
,
1671 wxCommandEventHandler(wxMediaPlayerFrame::OnPlay
),
1672 (wxObject
*)0, parentFrame
);
1673 this->Connect( wxID_BUTTONSTOP
, wxEVT_COMMAND_BUTTON_CLICKED
,
1674 wxCommandEventHandler(wxMediaPlayerFrame::OnStop
),
1675 (wxObject
*)0, parentFrame
);
1676 this->Connect( wxID_BUTTONNEXT
, wxEVT_COMMAND_BUTTON_CLICKED
,
1677 wxCommandEventHandler(wxMediaPlayerFrame::OnNext
),
1678 (wxObject
*)0, parentFrame
);
1679 this->Connect( wxID_BUTTONVD
, wxEVT_COMMAND_BUTTON_CLICKED
,
1680 wxCommandEventHandler(wxMediaPlayerFrame::OnVolumeDown
),
1681 (wxObject
*)0, parentFrame
);
1682 this->Connect( wxID_BUTTONVU
, wxEVT_COMMAND_BUTTON_CLICKED
,
1683 wxCommandEventHandler(wxMediaPlayerFrame::OnVolumeUp
),
1684 (wxObject
*)0, parentFrame
);
1687 // ----------------------------------------------------------------------------
1688 // MyNotebook::OnBeginSeek
1690 // Sets m_bIsBeingDragged to true to stop the timer from changing the position
1692 // ----------------------------------------------------------------------------
1693 void wxMediaPlayerNotebookPage::OnBeginSeek(wxScrollEvent
& WXUNUSED(event
))
1695 m_bIsBeingDragged
= true;
1698 // ----------------------------------------------------------------------------
1699 // MyNotebook::OnEndSeek
1701 // Called from file->seek.
1702 // Called when the user moves the slider -
1703 // seeks to a position within the media
1704 // then sets m_bIsBeingDragged to false to ok the timer to change the position
1705 // ----------------------------------------------------------------------------
1706 void wxMediaPlayerNotebookPage::OnEndSeek(wxScrollEvent
& WXUNUSED(event
))
1708 if( m_mediactrl
->Seek(
1709 m_slider
->GetValue() * 1000
1710 ) == wxInvalidOffset
)
1711 wxMessageBox(wxT("Couldn't seek in movie!"));
1713 m_bIsBeingDragged
= false;
1716 // ----------------------------------------------------------------------------
1717 // wxMediaPlayerNotebookPage::IsBeingDragged
1719 // Returns true if the user is dragging the slider
1720 // ----------------------------------------------------------------------------
1721 bool wxMediaPlayerNotebookPage::IsBeingDragged()
1723 return m_bIsBeingDragged
;
1726 // ----------------------------------------------------------------------------
1729 // Called when the media stops playing.
1730 // Here we loop it if the user wants to (has been selected from file menu)
1731 // ----------------------------------------------------------------------------
1732 void wxMediaPlayerNotebookPage::OnMediaFinished(wxMediaEvent
& WXUNUSED(event
))
1736 if ( !m_mediactrl
->Play() )
1738 wxMessageBox(wxT("Couldn't loop movie!"));
1739 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("E"));
1746 m_playlist
->SetItem(m_nLastFileId
, 0, wxT("[]"));
1751 // End of MediaPlayer sample