]> git.saurik.com Git - wxWidgets.git/blame_incremental - samples/mediaplayer/mediaplayer.cpp
added wxChoice:: and wxCombobox::GetCurrentSelection()
[wxWidgets.git] / samples / mediaplayer / mediaplayer.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: mediaplayer.cpp
3// Purpose: wxMediaCtrl sample
4// Author: Ryan Norton
5// Modified by:
6// Created: 11/10/04
7// RCS-ID: $Id$
8// Copyright: (c) Ryan Norton
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13// MediaPlayer
14//
15// This is a somewhat comprehensive example of how to use all the funtionality
16// of the wxMediaCtrl class in wxWidgets.
17//
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.
21//
22// You can select one of the menu options, or move the slider around
23// to manipulate what is playing.
24// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
25
26// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
27// Known bugs with wxMediaCtrl:
28//
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// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38
39// ============================================================================
40// Definitions
41// ============================================================================
42
43// ----------------------------------------------------------------------------
44// Pre-compiled header stuff
45// ----------------------------------------------------------------------------
46
47#include "wx/wxprec.h"
48
49#ifdef __BORLANDC__
50 #pragma hdrstop
51#endif
52
53#ifndef WX_PRECOMP
54 #include "wx/wx.h"
55#endif
56
57// ----------------------------------------------------------------------------
58// Headers
59// ----------------------------------------------------------------------------
60
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
73
74// ----------------------------------------------------------------------------
75// Bail out if the user doesn't want one of the
76// things we need
77// ----------------------------------------------------------------------------
78
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...
81#if !wxUSE_GUI
82#error "This is a GUI sample"
83#endif
84
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!"
88#endif
89
90// ============================================================================
91// Declarations
92// ============================================================================
93
94// ----------------------------------------------------------------------------
95// Enumurations
96// ----------------------------------------------------------------------------
97
98// IDs for the controls and the menu commands
99enum
100{
101 // Menu event IDs
102 wxID_LOOP = 1,
103 wxID_OPENFILESAMEPAGE,
104 wxID_OPENFILENEWPAGE,
105 wxID_OPENURLSAMEPAGE,
106 wxID_OPENURLNEWPAGE,
107 wxID_CLOSECURRENTPAGE,
108 wxID_PLAY,
109 wxID_PAUSE,
110 wxID_NEXT,
111 wxID_PREV,
112 wxID_SELECTBACKEND,
113 wxID_SHOWINTERFACE,
114// wxID_STOP, [built-in to wxWidgets]
115// wxID_ABOUT, [built-in to wxWidgets]
116// wxID_EXIT, [built-in to wxWidgets]
117 // Control event IDs
118 wxID_SLIDER,
119 wxID_NOTEBOOK,
120 wxID_MEDIACTRL,
121 wxID_BUTTONNEXT,
122 wxID_BUTTONPREV,
123 wxID_BUTTONSTOP,
124 wxID_BUTTONPLAY,
125 wxID_BUTTONVD,
126 wxID_BUTTONVU,
127 wxID_LISTCTRL,
128 wxID_GAUGE
129};
130
131// ----------------------------------------------------------------------------
132// wxMediaPlayerApp
133// ----------------------------------------------------------------------------
134
135class wxMediaPlayerApp : public wxApp
136{
137public:
138#ifdef __WXMAC__
139 virtual void MacOpenFile(const wxString & fileName );
140#endif
141
142 virtual bool OnInit();
143
144protected:
145 class wxMediaPlayerFrame* m_frame;
146};
147
148// ----------------------------------------------------------------------------
149// wxMediaPlayerFrame
150// ----------------------------------------------------------------------------
151
152class wxMediaPlayerFrame : public wxFrame
153{
154public:
155 // Ctor/Dtor
156 wxMediaPlayerFrame(const wxString& title);
157 ~wxMediaPlayerFrame();
158
159 // Menu event handlers
160 void OnQuit(wxCommandEvent& event);
161 void OnAbout(wxCommandEvent& event);
162
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);
168
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);
176
177 void OnLoop(wxCommandEvent& event);
178 void OnShowInterface(wxCommandEvent& event);
179
180 void OnSelectBackend(wxCommandEvent& event);
181
182 // Notebook event handlers
183 void OnPageChange(wxNotebookEvent& event);
184
185 // Key event handlers
186 void OnKeyDown(wxKeyEvent& event);
187
188 // Quickie for playing from command line
189 void AddToPlayList(const wxString& szString);
190
191 // ListCtrl event handlers
192 void OnChangeSong(wxListEvent& event);
193
194 // Media event handlers
195 void OnMediaLoaded(wxMediaEvent& event);
196
197 // Close event handlers
198 void OnClose(wxCloseEvent& event);
199
200private:
201 // Rebuild base status string (see Implementation)
202 void ResetStatus();
203
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);
209
210 // Get the controls of current notebook page
211 wxMediaCtrl* GetCurrentMediaCtrl();
212 wxSlider* GetCurrentSlider();
213 wxGauge* GetCurrentGauge();
214
215 int m_nLastFileId; //List ID of played file in listctrl
216 wxString m_szFile; //Name of currently playing file/location
217 class wxMediaPlayerTimer* m_timer; //Timer to write info to status bar
218 wxString m_basestatus; //Base status string (see ResetStatus())
219 wxNotebook* m_notebook; //Notebook containing our pages
220
221 // Maybe I should use more accessors, but for simplicity
222 // I'll allow the other classes access to our members
223 friend class wxMediaPlayerApp;
224 friend class wxMediaPlayerNotebookPage;
225 friend class wxMediaPlayerTimer;
226};
227
228
229
230// ----------------------------------------------------------------------------
231// wxMediaPlayerNotebookPage
232// ----------------------------------------------------------------------------
233
234class wxMediaPlayerNotebookPage : public wxPanel
235{
236 wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentFrame,
237 wxNotebook* book, const wxString& be = wxEmptyString);
238
239 // Slider event handlers
240 void OnBeginSeek(wxScrollEvent& event);
241 void OnEndSeek(wxScrollEvent& event);
242
243 // Media event handlers
244 void OnMediaFinished(wxMediaEvent& event);
245
246public:
247 bool IsBeingDragged(); //accessor for m_bIsBeingDragged
248
249 //make wxMediaPlayerFrame able to access the private members
250 friend class wxMediaPlayerFrame;
251
252 wxMediaCtrl* m_mediactrl; //Our media control
253 class wxMediaPlayerListCtrl* m_playlist; //Our playlist
254 wxSlider* m_slider; //The slider below our media control
255 int m_nLoops; //Number of times media has looped
256 bool m_bLoop; //Whether we are looping or not
257 bool m_bIsBeingDragged; //Whether the user is dragging the scroll bar
258 wxMediaPlayerFrame* m_parentFrame; //Main wxFrame of our sample
259 wxButton* m_prevButton; //Go to previous file button
260 wxButton* m_playButton; //Play/pause file button
261 wxButton* m_stopButton; //Stop playing file button
262 wxButton* m_nextButton; //Next file button
263 wxButton* m_vdButton; //Volume down button
264 wxButton* m_vuButton; //Volume up button
265 wxGauge* m_gauge; //Gauge to keep in line with slider
266};
267
268// ----------------------------------------------------------------------------
269// wxMediaPlayerTimer
270// ----------------------------------------------------------------------------
271
272class wxMediaPlayerTimer : public wxTimer
273{
274public:
275 //Ctor
276 wxMediaPlayerTimer(wxMediaPlayerFrame* frame) {m_frame = frame;}
277
278 //Called each time the timer's timeout expires
279 void Notify();
280
281 wxMediaPlayerFrame* m_frame; //The wxMediaPlayerFrame
282};
283
284// ----------------------------------------------------------------------------
285// wxMediaPlayerListCtrl
286// ----------------------------------------------------------------------------
287class wxMediaPlayerListCtrl : public wxListCtrl
288{
289public:
290 void AddToPlayList(const wxString& szString)
291 {
292 wxListItem kNewItem;
293 kNewItem.SetAlign(wxLIST_FORMAT_LEFT);
294
295 int nID;
296
297 kNewItem.SetId(nID = this->GetItemCount());
298 kNewItem.SetMask(wxLIST_MASK_DATA);
299 kNewItem.SetData(new wxString(szString));
300
301 this->InsertItem(kNewItem);
302 this->SetItem(nID, 0, _T("*"));
303 this->SetItem(nID, 1, wxFileName(szString).GetName());
304
305 if (nID % 2)
306 {
307 kNewItem.SetBackgroundColour(wxColour(192,192,192));
308 this->SetItem(kNewItem);
309 }
310 }
311
312 void GetSelectedItem(wxListItem& listitem)
313 {
314 listitem.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_DATA);
315 int nLast = -1, nLastSelected = -1;
316 while ((nLast = this->GetNextItem(nLast,
317 wxLIST_NEXT_ALL,
318 wxLIST_STATE_SELECTED)) != -1)
319 {
320 listitem.SetId(nLast);
321 this->GetItem(listitem);
322 if ((listitem.GetState() & wxLIST_STATE_FOCUSED) )
323 break;
324 nLastSelected = nLast;
325 }
326 if (nLast == -1 && nLastSelected == -1)
327 return;
328 listitem.SetId(nLastSelected == -1 ? nLast : nLastSelected);
329 this->GetItem(listitem);
330 }
331
332};
333
334// ----------------------------------------------------------------------------
335// wxPlayListDropTarget
336//
337// Drop target for playlist (i.e. user drags a file from explorer unto
338// playlist it adds the file)
339// ----------------------------------------------------------------------------
340class wxPlayListDropTarget : public wxFileDropTarget
341{
342public:
343 wxPlayListDropTarget(wxMediaPlayerListCtrl& list) : m_list(list) {}
344 ~wxPlayListDropTarget(){}
345 virtual bool OnDropFiles(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
346 const wxArrayString& files)
347 {
348 for (size_t i = 0; i < files.GetCount(); ++i)
349 {
350 m_list.AddToPlayList(files[i]);
351 }
352 return true;
353 }
354 wxMediaPlayerListCtrl& m_list;
355};
356
357// ============================================================================
358//
359// Implementation
360//
361// ============================================================================
362
363// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
364//
365// [Functions]
366//
367// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
368
369// ----------------------------------------------------------------------------
370// wxGetMediaStateText
371//
372// Converts a wxMediaCtrl state into something useful that we can display
373// to the user
374// ----------------------------------------------------------------------------
375const wxChar* wxGetMediaStateText(int nState)
376{
377 switch(nState)
378 {
379 case wxMEDIASTATE_PLAYING:
380 return wxT("Playing");
381 case wxMEDIASTATE_STOPPED:
382 return wxT("Stopped");
383 ///case wxMEDIASTATE_PAUSED:
384 default:
385 return wxT("Paused");
386 }
387}
388
389// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
390//
391// wxMediaPlayerApp
392//
393// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
394
395// ----------------------------------------------------------------------------
396// This sets up this wxApp as the global wxApp that gui calls in wxWidgets
397// use. For example, if you were to be in windows and use a file dialog,
398// wxWidgets would use wxTheApp->GetHInstance() which would get the instance
399// handle of the application. These routines in wx _DO NOT_ check to see if
400// the wxApp exists, and thus will crash the application if you try it.
401//
402// IMPLEMENT_APP does this, and also implements the platform-specific entry
403// routine, such as main or WinMain(). Use IMPLEMENT_APP_NO_MAIN if you do
404// not desire this behavior.
405// ----------------------------------------------------------------------------
406IMPLEMENT_APP(wxMediaPlayerApp)
407
408// ----------------------------------------------------------------------------
409// wxMediaPlayerApp::OnInit
410//
411// Where execution starts - akin to a main or WinMain.
412// 1) Create the frame and show it to the user
413// 2) Process filenames from the commandline
414// 3) return true specifying that we want execution to continue past OnInit
415// ----------------------------------------------------------------------------
416bool wxMediaPlayerApp::OnInit()
417{
418 wxMediaPlayerFrame *frame =
419 new wxMediaPlayerFrame(_T("MediaPlayer wxWidgets Sample"));
420 frame->Show(true);
421
422#if wxUSE_CMDLINE_PARSER
423 //
424 // What this does is get all the command line arguments
425 // and treat each one as a file to put to the initial playlist
426 //
427 wxCmdLineEntryDesc cmdLineDesc[2];
428 cmdLineDesc[0].kind = wxCMD_LINE_PARAM;
429 cmdLineDesc[0].shortName = NULL;
430 cmdLineDesc[0].longName = NULL;
431 cmdLineDesc[0].description = wxT("input files");
432 cmdLineDesc[0].type = wxCMD_LINE_VAL_STRING;
433 cmdLineDesc[0].flags = wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE;
434
435 cmdLineDesc[1].kind = wxCMD_LINE_NONE;
436
437 //gets the passed media files from cmd line
438 wxCmdLineParser parser (cmdLineDesc, argc, argv);
439
440 // get filenames from the commandline
441 if (parser.Parse() == 0)
442 {
443 for (size_t paramNr=0; paramNr < parser.GetParamCount(); ++paramNr)
444 {
445 frame->AddToPlayList((parser.GetParam (paramNr)));
446 }
447 wxCommandEvent emptyevt;
448 frame->OnNext(emptyevt);
449 }
450#endif
451
452 return true;
453}
454
455#ifdef __WXMAC__
456
457void wxMediaPlayerApp::MacOpenFile(const wxString & fileName )
458{
459 //Called when a user drags a file over our app
460 m_frame->DoOpenFile(fileName, true /* new page */);
461}
462
463#endif // __WXMAC__
464
465// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
466//
467// wxMediaPlayerFrame
468//
469// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
470
471// ----------------------------------------------------------------------------
472// wxMediaPlayerFrame Constructor
473//
474// 1) Create our menus
475// 2) Create our notebook control and add it to the frame
476// 3) Create our status bar
477// 4) Connect our events
478// 5) Start our timer
479// ----------------------------------------------------------------------------
480
481wxMediaPlayerFrame::wxMediaPlayerFrame(const wxString& title)
482 : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(600,600)),
483 m_nLastFileId(-1)
484{
485 //
486 // Create Menus
487 //
488 wxMenu *fileMenu = new wxMenu;
489 wxMenu *controlsMenu = new wxMenu;
490 wxMenu *optionsMenu = new wxMenu;
491 wxMenu *helpMenu = new wxMenu;
492 wxMenu *debugMenu = new wxMenu;
493
494 fileMenu->Append(wxID_OPENFILESAMEPAGE, _T("&Open File\tCtrl-Shift-O"),
495 _T("Open a File in the current notebook page"));
496 fileMenu->Append(wxID_OPENFILENEWPAGE, _T("&Open File in a new page"),
497 _T("Open a File in a new notebook page"));
498 fileMenu->Append(wxID_OPENURLSAMEPAGE, _T("&Open URL"),
499 _T("Open a URL in the current notebook page"));
500 fileMenu->Append(wxID_OPENURLNEWPAGE, _T("&Open URL in a new page"),
501 _T("Open a URL in a new notebook page"));
502 fileMenu->AppendSeparator();
503 fileMenu->Append(wxID_CLOSECURRENTPAGE, _T("&Close Current Page\tCtrl-C"),
504 _T("Close current notebook page"));
505 fileMenu->AppendSeparator();
506 fileMenu->Append(wxID_EXIT,
507 _T("E&xit\tAlt-X"),
508 _T("Quit this program"));
509
510 controlsMenu->Append(wxID_PLAY, _T("&Play/Pause\tCtrl-P"), _T("Resume/Pause playback"));
511 controlsMenu->Append(wxID_STOP, _T("&Stop\tCtrl-S"), _T("Stop playback"));
512 controlsMenu->AppendSeparator();
513 controlsMenu->Append(wxID_PREV, _T("&Previous\tCtrl-B"), _T("Go to previous track"));
514 controlsMenu->Append(wxID_NEXT, _T("&Next\tCtrl-N"), _T("Skip to next track"));
515
516 optionsMenu->AppendCheckItem(wxID_LOOP,
517 _T("&Loop\tCtrl-L"),
518 _T("Loop Selected Media"));
519 optionsMenu->AppendCheckItem(wxID_SHOWINTERFACE,
520 _T("&Show Interface\tCtrl-I"),
521 _T("Show wxMediaCtrl native controls"));
522
523 debugMenu->Append(wxID_SELECTBACKEND,
524 _T("&Select Backend...\tCtrl-D"),
525 _T("Select a backend manually"));
526
527 helpMenu->Append(wxID_ABOUT,
528 _T("&About...\tF1"),
529 _T("Show about dialog"));
530
531
532 wxMenuBar *menuBar = new wxMenuBar();
533 menuBar->Append(fileMenu, _T("&File"));
534 menuBar->Append(controlsMenu, _T("&Controls"));
535 menuBar->Append(optionsMenu, _T("&Options"));
536 menuBar->Append(debugMenu, _T("&Debug"));
537 menuBar->Append(helpMenu, _T("&Help"));
538 SetMenuBar(menuBar);
539
540 //
541 // Create our notebook - using wxNotebook is luckily pretty
542 // simple and self-explanatory in most cases
543 //
544 m_notebook = new wxNotebook(this, wxID_NOTEBOOK);
545
546 //
547 // Create our status bar
548 //
549#if wxUSE_STATUSBAR
550 // create a status bar just for fun (by default with 1 pane only)
551 CreateStatusBar(1);
552#endif // wxUSE_STATUSBAR
553
554 //
555 // Connect events.
556 //
557 // There are two ways in wxWidgets to use events -
558 // Message Maps and Connections.
559 //
560 // Message Maps are implemented by putting
561 // DECLARE_MESSAGE_MAP in your wxEvtHandler-derived
562 // class you want to use for events, such as wxMediaPlayerFrame.
563 //
564 // Then after your class declaration you put
565 // BEGIN_EVENT_TABLE(wxMediaPlayerFrame, wxFrame)
566 // EVT_XXX(XXX)...
567 // END_EVENT_TABLE()
568 //
569 // Where wxMediaPlayerFrame is the class with the DECLARE_MESSAGE_MAP
570 // in it. EVT_XXX(XXX) are each of your handlers, such
571 // as EVT_MENU for menu events and the XXX inside
572 // is the parameters to the event macro - in the case
573 // of EVT_MENU the menu id and then the function to call.
574 //
575 // However, with wxEvtHandler::Connect you can avoid a
576 // global message map for your class and those annoying
577 // macros. You can also change the context in which
578 // the call the handler (more later).
579 //
580 // The downside is that due to the limitation that
581 // wxWidgets doesn't use templates in certain areas,
582 // You have to triple-cast the event function.
583 //
584 // There are five parameters to wxEvtHandler::Connect -
585 //
586 // The first is the id of the instance whose events
587 // you want to handle - i.e. a menu id for menus,
588 // a control id for controls (wxControl::GetId())
589 // and so on.
590 //
591 // The second is the event id. This is the same
592 // as the message maps (EVT_MENU) except prefixed
593 // with "wx" (wxEVT_MENU).
594 //
595 // The third is the function handler for the event -
596 // You need to cast it to the specific event handler
597 // type, then to a wxEventFunction, then to a
598 // wxObjectEventFunction - I.E.
599 // (wxObjectEventFunction)(wxEventFunction)
600 // (wxCommandEventFunction) &wxMediaPlayerFrame::MyHandler
601 //
602 // Or, you can use the new (2.5.5+) event handler
603 // conversion macros - for instance the above could
604 // be done as
605 // wxCommandEventHandler(wxMediaPlayerFrame::MyHandler)
606 // pretty simple, eh?
607 //
608 // The fourth is an optional userdata param -
609 // this is of historical relevance only and is
610 // there only for backwards compatibility.
611 //
612 // The fifth is the context in which to call the
613 // handler - by default (this param is optional)
614 // this. For example in your event handler
615 // if you were to call "this->MyFunc()"
616 // it would literally do this->MyFunc. However,
617 // if you were to pass myHandler as the fifth
618 // parameter, for instance, you would _really_
619 // be calling myHandler->MyFunc, even though
620 // the compiler doesn't really know it.
621 //
622
623 //
624 // Menu events
625 //
626 this->Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED,
627 wxCommandEventHandler(wxMediaPlayerFrame::OnQuit));
628
629 this->Connect(wxID_ABOUT, wxEVT_COMMAND_MENU_SELECTED,
630 wxCommandEventHandler(wxMediaPlayerFrame::OnAbout));
631
632 this->Connect(wxID_LOOP, wxEVT_COMMAND_MENU_SELECTED,
633 wxCommandEventHandler(wxMediaPlayerFrame::OnLoop));
634
635 this->Connect(wxID_SHOWINTERFACE, wxEVT_COMMAND_MENU_SELECTED,
636 wxCommandEventHandler(wxMediaPlayerFrame::OnShowInterface));
637
638 this->Connect(wxID_OPENFILENEWPAGE, wxEVT_COMMAND_MENU_SELECTED,
639 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileNewPage));
640
641 this->Connect(wxID_OPENFILESAMEPAGE, wxEVT_COMMAND_MENU_SELECTED,
642 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenFileSamePage));
643
644 this->Connect(wxID_OPENURLNEWPAGE, wxEVT_COMMAND_MENU_SELECTED,
645 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLNewPage));
646
647 this->Connect(wxID_OPENURLSAMEPAGE, wxEVT_COMMAND_MENU_SELECTED,
648 wxCommandEventHandler(wxMediaPlayerFrame::OnOpenURLSamePage));
649
650 this->Connect(wxID_CLOSECURRENTPAGE, wxEVT_COMMAND_MENU_SELECTED,
651 wxCommandEventHandler(wxMediaPlayerFrame::OnCloseCurrentPage));
652
653 this->Connect(wxID_PLAY, wxEVT_COMMAND_MENU_SELECTED,
654 wxCommandEventHandler(wxMediaPlayerFrame::OnPlay));
655
656 this->Connect(wxID_STOP, wxEVT_COMMAND_MENU_SELECTED,
657 wxCommandEventHandler(wxMediaPlayerFrame::OnStop));
658
659 this->Connect(wxID_NEXT, wxEVT_COMMAND_MENU_SELECTED,
660 wxCommandEventHandler(wxMediaPlayerFrame::OnNext));
661
662 this->Connect(wxID_PREV, wxEVT_COMMAND_MENU_SELECTED,
663 wxCommandEventHandler(wxMediaPlayerFrame::OnPrev));
664
665 this->Connect(wxID_SELECTBACKEND, wxEVT_COMMAND_MENU_SELECTED,
666 wxCommandEventHandler(wxMediaPlayerFrame::OnSelectBackend));
667
668 //
669 // Notebook events
670 //
671 this->Connect(wxID_NOTEBOOK, wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
672 wxNotebookEventHandler(wxMediaPlayerFrame::OnPageChange));
673
674 //
675 // Key events
676 //
677 wxTheApp->Connect(wxID_ANY, wxEVT_KEY_DOWN,
678 wxKeyEventHandler(wxMediaPlayerFrame::OnKeyDown),
679 (wxObject*)0, this);
680
681 //
682 // Close events
683 //
684 this->Connect(wxID_ANY, wxEVT_CLOSE_WINDOW,
685 wxCloseEventHandler(wxMediaPlayerFrame::OnClose));
686
687 //
688 // End of Events
689 //
690
691 //
692 // Create an initial notebook page so the user has something
693 // to work with without having to go file->open every time :).
694 //
695 m_notebook->AddPage(new wxMediaPlayerNotebookPage(this, m_notebook),
696 wxT(""),
697 true);
698
699 //
700 // Create a timer to update our status bar
701 //
702 m_timer = new wxMediaPlayerTimer(this);
703 m_timer->Start(100);
704}
705
706// ----------------------------------------------------------------------------
707// wxMediaPlayerFrame Destructor
708//
709// 1) Deletes child objects implicitly
710// 2) Delete our timer explicitly
711// ----------------------------------------------------------------------------
712wxMediaPlayerFrame::~wxMediaPlayerFrame()
713{
714 delete m_timer;
715
716}
717
718// ----------------------------------------------------------------------------
719// wxMediaPlayerFrame::OnClose
720// ----------------------------------------------------------------------------
721void wxMediaPlayerFrame::OnClose(wxCloseEvent& event)
722{
723 //
724 // Here we save our info to the registry or whatever
725 // mechanism the OS uses.
726 //
727 // This makes it so that when mediaplayer loads up again
728 // it restores the same files that were in the playlist
729 // this time, rather than the user manually re-adding them.
730 //
731 // We need to do conf->DeleteAll() here because by default
732 // the config still contains the same files as last time
733 // so we need to clear it before writing our new ones.
734 //
735 // TODO: Maybe you could add a menu option to the
736 // options menu to delete the configuration on exit -
737 // all you'd need to do is just remove everything after
738 // conf->DeleteAll() here
739 //
740 wxMediaPlayerListCtrl* m_playlist =
741 ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage())->m_playlist;
742
743 wxConfigBase* conf = wxConfigBase::Get();
744 conf->DeleteAll();
745
746 for(int i = 0; i < m_playlist->GetItemCount(); ++i)
747 {
748 wxString* pData = (wxString*) m_playlist->GetItemData(i);
749 wxString s;
750 s << i;
751 conf->Write(s, *(pData));
752 delete pData;
753 }
754
755 event.Skip(); //really close the frame
756}
757
758// ----------------------------------------------------------------------------
759// wxMediaPlayerFrame::AddToPlayList
760// ----------------------------------------------------------------------------
761void wxMediaPlayerFrame::AddToPlayList(const wxString& szString)
762{
763 wxMediaPlayerNotebookPage* currentpage =
764 ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage());
765
766 currentpage->m_playlist->AddToPlayList(szString);
767}
768
769
770// ----------------------------------------------------------------------------
771// wxMediaPlayerFrame::ResetStatus
772//
773// Here we just make a simple status string with some useful info about
774// the media that we won't change later - such as the length of the media.
775//
776// We then append some other info that changes in wxMediaPlayerTimer::Notify, then
777// set the status bar to this text.
778//
779// In real applications, you'd want to find a better way to do this,
780// such as static text controls (wxStaticText).
781//
782// We display info here in seconds (wxMediaCtrl uses milliseconds - that's why
783// we divide by 1000).
784//
785// We also reset our loop counter here.
786// ----------------------------------------------------------------------------
787void wxMediaPlayerFrame::ResetStatus()
788{
789 wxMediaCtrl* currentMediaCtrl = GetCurrentMediaCtrl();
790
791 m_basestatus = wxString::Format(_T("Size(x,y):%i,%i ")
792 _T("Length(Seconds):%u Speed:%1.1fx"),
793 currentMediaCtrl->GetBestSize().x,
794 currentMediaCtrl->GetBestSize().y,
795 (unsigned)((currentMediaCtrl->Length() / 1000)),
796 currentMediaCtrl->GetPlaybackRate()
797 );
798}
799
800// ----------------------------------------------------------------------------
801// wxMediaPlayerFrame::GetCurrentMediaCtrl
802//
803// Obtains the media control of the current page, or NULL if there are no
804// pages open
805// ----------------------------------------------------------------------------
806wxMediaCtrl* wxMediaPlayerFrame::GetCurrentMediaCtrl()
807{
808 return ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage())->m_mediactrl;
809}
810
811// ----------------------------------------------------------------------------
812// wxMediaPlayerFrame::GetCurrentSlider
813//
814// Obtains the slider of the current page
815// ----------------------------------------------------------------------------
816wxSlider* wxMediaPlayerFrame::GetCurrentSlider()
817{
818 return ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage())->m_slider;
819}
820
821// ----------------------------------------------------------------------------
822// wxMediaPlayerFrame::GetCurrentGauge
823//
824// Obtains the gauge of the current page
825// ----------------------------------------------------------------------------
826wxGauge* wxMediaPlayerFrame::GetCurrentGauge()
827{
828 return ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage())->m_gauge;
829}
830
831// ----------------------------------------------------------------------------
832// wxMediaPlayerFrame::OnQuit
833//
834// Called from file->quit.
835// Closes this application.
836// ----------------------------------------------------------------------------
837void wxMediaPlayerFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
838{
839 // true is to force the frame to close
840 Close(true);
841}
842
843// ----------------------------------------------------------------------------
844// wxMediaPlayerFrame::OnAbout
845//
846// Called from help->about.
847// Gets some info about this application.
848// ----------------------------------------------------------------------------
849void wxMediaPlayerFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
850{
851 wxString msg;
852 msg.Printf( _T("This is a test of wxMediaCtrl.\n")
853 _T("Welcome to %s"), wxVERSION_STRING);
854
855 wxMessageBox(msg, _T("About wxMediaCtrl test"), wxOK | wxICON_INFORMATION, this);
856}
857
858// ----------------------------------------------------------------------------
859// wxMediaPlayerFrame::OnLoop
860//
861// Called from file->loop.
862// Changes the state of whether we want to loop or not.
863// ----------------------------------------------------------------------------
864void wxMediaPlayerFrame::OnLoop(wxCommandEvent& WXUNUSED(event))
865{
866 if(!m_notebook->GetCurrentPage())
867 {
868 wxMessageBox(wxT("No files are currently open!"));
869 return;
870 }
871
872 ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage())->m_bLoop =
873 !((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage())->m_bLoop;
874}
875
876// ----------------------------------------------------------------------------
877// wxMediaPlayerFrame::OnLoop
878//
879// Called from file->loop.
880// Changes the state of whether we want to loop or not.
881// ----------------------------------------------------------------------------
882void wxMediaPlayerFrame::OnShowInterface(wxCommandEvent& event)
883{
884 if(!m_notebook->GetCurrentPage())
885 {
886 wxMessageBox(wxT("No files are currently open!"));
887 return;
888 }
889
890 GetCurrentMediaCtrl()->ShowPlayerControls(event.IsChecked() ?
891 wxMEDIACTRLPLAYERCONTROLS_DEFAULT :
892 wxMEDIACTRLPLAYERCONTROLS_NONE);
893}
894
895// ----------------------------------------------------------------------------
896// wxMediaPlayerFrame::OnOpenFileSamePage
897//
898// Called from file->openfile.
899// Opens and plays a media file in the current notebook page
900// ----------------------------------------------------------------------------
901void wxMediaPlayerFrame::OnOpenFileSamePage(wxCommandEvent& WXUNUSED(event))
902{
903 OpenFile(false);
904}
905
906// ----------------------------------------------------------------------------
907// wxMediaPlayerFrame::OnOpenFileNewPage
908//
909// Called from file->openfileinnewpage.
910// Opens and plays a media file in a new notebook page
911// ----------------------------------------------------------------------------
912void wxMediaPlayerFrame::OnOpenFileNewPage(wxCommandEvent& WXUNUSED(event))
913{
914 OpenFile(true);
915}
916
917// ----------------------------------------------------------------------------
918// wxMediaPlayerFrame::OpenFile
919//
920// Opens a file dialog asking the user for a filename, then
921// calls DoOpenFile which will add the file to the playlist and play it
922// ----------------------------------------------------------------------------
923void wxMediaPlayerFrame::OpenFile(bool bNewPage)
924{
925 wxFileDialog fd(this);
926
927 if(fd.ShowModal() == wxID_OK)
928 {
929 DoOpenFile(fd.GetPath(), bNewPage);
930 }
931}
932
933// ----------------------------------------------------------------------------
934// wxMediaPlayerFrame::DoOpenFile
935//
936// Adds the file to our playlist, selects it in the playlist,
937// and then calls DoPlayFile to play it
938// ----------------------------------------------------------------------------
939void wxMediaPlayerFrame::DoOpenFile(const wxString& path, bool bNewPage)
940{
941 if(bNewPage)
942 {
943 m_notebook->AddPage(
944 new wxMediaPlayerNotebookPage(this, m_notebook),
945 path,
946 true);
947 }
948
949 wxMediaPlayerListCtrl* m_playlist =
950 ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage())->m_playlist;
951
952 if(m_nLastFileId != -1)
953 m_playlist->SetItemState(m_nLastFileId, 0, wxLIST_STATE_SELECTED);
954
955 wxListItem newlistitem;
956 newlistitem.SetAlign(wxLIST_FORMAT_LEFT);
957
958 int nID;
959
960 newlistitem.SetId(nID = m_playlist->GetItemCount());
961 newlistitem.SetMask(wxLIST_MASK_DATA | wxLIST_MASK_STATE);
962 newlistitem.SetState(wxLIST_STATE_SELECTED);
963 newlistitem.SetData(new wxString(path));
964
965 m_playlist->InsertItem(newlistitem);
966 m_playlist->SetItem(nID, 0, _T("*"));
967 m_playlist->SetItem(nID, 1, wxFileName(path).GetName());
968
969 if (nID % 2)
970 {
971 newlistitem.SetBackgroundColour(wxColour(192,192,192));
972 m_playlist->SetItem(newlistitem);
973 }
974
975 DoPlayFile(path);
976 // m_playlist->Focus(nID);
977}
978
979// ----------------------------------------------------------------------------
980// wxMediaPlayerFrame::DoPlayFile
981//
982// Pauses the file if its the currently playing file,
983// otherwise it plays the file
984// ----------------------------------------------------------------------------
985void wxMediaPlayerFrame::DoPlayFile(const wxString& path)
986{
987 wxMediaPlayerListCtrl* m_playlist =
988 ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage())->m_playlist;
989
990 wxListItem listitem;
991 m_playlist->GetSelectedItem(listitem);
992
993 if(listitem.GetData() &&
994 m_szFile.compare(path) == 0 &&
995 m_nLastFileId == listitem.GetId())
996 {
997 if(GetCurrentMediaCtrl()->GetState() == wxMEDIASTATE_PLAYING)
998 {
999 if( !GetCurrentMediaCtrl()->Pause() )
1000 wxMessageBox(wxT("Couldn't pause movie!"));
1001 else
1002 m_playlist->SetItem(listitem.GetId(), 0, _T("||"));
1003 }
1004 else
1005 {
1006 if( !GetCurrentMediaCtrl()->Play() )
1007 wxMessageBox(wxT("Couldn't pause movie!"));
1008 else
1009 m_playlist->SetItem(listitem.GetId(), 0, _T(">"));
1010 }
1011 }
1012 else
1013 {
1014 m_notebook->SetPageText(m_notebook->GetSelection(),
1015 wxFileName(path).GetName());
1016
1017 if(m_nLastFileId != -1)
1018 m_playlist->SetItem(m_nLastFileId, 0, _T("*"));
1019
1020 wxURI uripath(path);
1021 if( uripath.IsReference() )
1022 {
1023 if( !GetCurrentMediaCtrl()->Load(path) )
1024 {
1025 wxMessageBox(wxT("Couldn't load file!"));
1026 m_playlist->SetItem(listitem.GetId(), 0, _T("E"));
1027 }
1028 else
1029 {
1030 m_playlist->SetItem(listitem.GetId(), 0, _T("O"));
1031 }
1032 }
1033 else
1034 {
1035 if( !GetCurrentMediaCtrl()->Load(uripath) )
1036 {
1037 wxMessageBox(wxT("Couldn't load file!"));
1038 m_playlist->SetItem(listitem.GetId(), 0, _T("E"));
1039 }
1040 else
1041 {
1042 m_playlist->SetItem(listitem.GetId(), 0, _T("O"));
1043 }
1044 }
1045
1046 m_nLastFileId = listitem.GetId();
1047 m_szFile = path;
1048 m_playlist->SetItem(m_nLastFileId, 1, wxFileName(path).GetName());
1049 m_playlist->SetItem(m_nLastFileId, 2, wxT(""));
1050 }
1051}
1052
1053// ----------------------------------------------------------------------------
1054// wxMediaPlayerFrame::OnMediaLoaded
1055//
1056// Called when the media is ready to be played - and does
1057// so, also gets the length of media and shows that in the list control
1058// ----------------------------------------------------------------------------
1059void wxMediaPlayerFrame::OnMediaLoaded(wxMediaEvent& WXUNUSED(evt))
1060{
1061 wxMediaPlayerListCtrl* m_playlist =
1062 ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage())->m_playlist;
1063 wxListItem listitem;
1064 m_playlist->GetSelectedItem(listitem);
1065
1066 if( !GetCurrentMediaCtrl()->Play() )
1067 {
1068 wxMessageBox(wxT("Couldn't play movie!"));
1069 m_playlist->SetItem(listitem.GetId(), 0, _T("E"));
1070 }
1071 else
1072 {
1073 m_playlist->SetItem(listitem.GetId(), 0, _T(">"));
1074 }
1075
1076 m_playlist->SetItem(listitem.GetId(), 2, wxString::Format(wxT("%u"),
1077 (unsigned) GetCurrentMediaCtrl()->Length() / 1000) );
1078
1079 ResetStatus();
1080
1081 GetCurrentSlider()->SetRange(0,
1082 (int)(GetCurrentMediaCtrl()->Length() / 1000));
1083 GetCurrentGauge()->SetRange((int)(GetCurrentMediaCtrl()->Length() / 1000));
1084}
1085
1086// ----------------------------------------------------------------------------
1087// wxMediaPlayerFrame::OnSelectBackend
1088//
1089// Little debugging routine - enter the class name of a backend and it
1090// will use that instead of letting wxMediaCtrl search the wxMediaBackend
1091// RTTI class list.
1092// ----------------------------------------------------------------------------
1093void wxMediaPlayerFrame::OnSelectBackend(wxCommandEvent& WXUNUSED(evt))
1094{
1095 wxString sBackend = wxGetTextFromUser(wxT("Enter backend to use"));
1096
1097 if(sBackend.empty() == false) //could have been cancelled by the user
1098 {
1099 int sel = m_notebook->GetSelection();
1100
1101 if (sel != wxNOT_FOUND)
1102 {
1103 m_notebook->DeletePage(sel);
1104 }
1105
1106 m_notebook->AddPage(new wxMediaPlayerNotebookPage(this, m_notebook,
1107 sBackend
1108 ), wxT(""), true);
1109 DoOpenFile(m_szFile, false);
1110 }
1111}
1112
1113// ----------------------------------------------------------------------------
1114// wxMediaPlayerFrame::OnOpenURLSamePage
1115//
1116// Called from file->openurl.
1117// Opens and plays a media file from a URL in the current notebook page
1118// ----------------------------------------------------------------------------
1119void wxMediaPlayerFrame::OnOpenURLSamePage(wxCommandEvent& WXUNUSED(event))
1120{
1121 OpenURL(false);
1122}
1123
1124// ----------------------------------------------------------------------------
1125// wxMediaPlayerFrame::OnOpenURLNewPage
1126//
1127// Called from file->openurlinnewpage.
1128// Opens and plays a media file from a URL in a new notebook page
1129// ----------------------------------------------------------------------------
1130void wxMediaPlayerFrame::OnOpenURLNewPage(wxCommandEvent& WXUNUSED(event))
1131{
1132 OpenURL(true);
1133}
1134
1135// ----------------------------------------------------------------------------
1136// wxMediaPlayerFrame::OpenURL
1137//
1138// Just calls DoOpenFile with the url path - which calls DoPlayFile
1139// which handles the real dirty work
1140// ----------------------------------------------------------------------------
1141void wxMediaPlayerFrame::OpenURL(bool bNewPage)
1142{
1143 wxString sUrl = wxGetTextFromUser(
1144 wxT("Enter the URL that has the movie to play")
1145 );
1146
1147 if(sUrl.empty() == false) //could have been cancelled by user
1148 {
1149 DoOpenFile(sUrl, bNewPage);
1150 }
1151}
1152
1153// ----------------------------------------------------------------------------
1154// wxMediaPlayerFrame::OnCloseCurrentPage
1155//
1156// Called when the user wants to close the current notebook page
1157//
1158// 1) Get the current page number (wxControl::GetSelection)
1159// 2) If there is no current page, break out
1160// 3) Delete the current page
1161// ----------------------------------------------------------------------------
1162void wxMediaPlayerFrame::OnCloseCurrentPage(wxCommandEvent& WXUNUSED(event))
1163{
1164 if( m_notebook->GetPageCount() > 1 )
1165 {
1166 int sel = m_notebook->GetSelection();
1167
1168 if (sel != wxNOT_FOUND)
1169 {
1170 m_notebook->DeletePage(sel);
1171 }
1172 }
1173 else
1174 {
1175 wxMessageBox(wxT("Cannot close main page"));
1176 }
1177}
1178
1179// ----------------------------------------------------------------------------
1180// wxMediaPlayerFrame::OnPlay
1181//
1182// Called from file->play.
1183// Resumes the media if it is paused or stopped.
1184// ----------------------------------------------------------------------------
1185void wxMediaPlayerFrame::OnPlay(wxCommandEvent& WXUNUSED(event))
1186{
1187 wxMediaPlayerListCtrl* m_playlist =
1188 ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage())->m_playlist;
1189
1190 wxListItem listitem;
1191 m_playlist->GetSelectedItem(listitem);
1192 if ( !listitem.GetData() )
1193 {
1194 int nLast = -1;
1195 if ((nLast = m_playlist->GetNextItem(nLast,
1196 wxLIST_NEXT_ALL,
1197 wxLIST_STATE_DONTCARE)) == -1)
1198 {
1199 //no items in list
1200 wxMessageBox(_T("No items in playlist!"));
1201 return;
1202 }
1203 wxListItem listitem;
1204 listitem.SetId(nLast);
1205 m_playlist->GetItem(listitem);
1206 listitem.SetMask(listitem.GetMask() | wxLIST_MASK_STATE);
1207 listitem.SetState(listitem.GetState() | wxLIST_STATE_SELECTED);
1208 m_playlist->SetItem(listitem);
1209 wxListEvent event;
1210 OnChangeSong(event);
1211 }
1212 else
1213 {
1214 wxListEvent event;
1215 OnChangeSong(event);
1216 }
1217}
1218
1219// ----------------------------------------------------------------------------
1220// wxMediaPlayerFrame::OnKeyDown
1221//
1222// Deletes all selected files from the playlist if the backspace key is pressed
1223// ----------------------------------------------------------------------------
1224void wxMediaPlayerFrame::OnKeyDown(wxKeyEvent& event)
1225{
1226 if(event.GetKeyCode() == WXK_BACK/*DELETE*/)
1227 {
1228 wxMediaPlayerListCtrl* m_playlist =
1229 ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage())->m_playlist;
1230 //delete all selected items
1231 while(true)
1232 {
1233 wxInt32 nSelectedItem = m_playlist->GetNextItem(
1234 -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
1235 if (nSelectedItem == -1)
1236 break;
1237
1238 wxListItem listitem;
1239 listitem.SetId(nSelectedItem);
1240 m_playlist->GetItem(listitem);
1241 delete (wxString*) listitem.GetData();
1242
1243 m_playlist->DeleteItem(nSelectedItem);
1244 }
1245 }
1246
1247 //Could be wxGetTextFromUser or something else important
1248 if(event.GetEventObject() != this)
1249 event.Skip();
1250}
1251
1252// ----------------------------------------------------------------------------
1253// wxMediaPlayerFrame::OnStop
1254//
1255// Called from file->stop.
1256// Where it stops depends on whether you can seek in the
1257// media control or not - if you can it stops and seeks to the beginning,
1258// otherwise it will appear to be at the end - but it will start over again
1259// when Play() is called
1260// ----------------------------------------------------------------------------
1261void wxMediaPlayerFrame::OnStop(wxCommandEvent& WXUNUSED(evt))
1262{
1263 wxMediaPlayerListCtrl* m_playlist =
1264 ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage())->m_playlist;
1265
1266 wxListItem listitem;
1267 m_playlist->GetSelectedItem(listitem);
1268 m_playlist->SetItem(listitem.GetId(), 0, _T("[]"));
1269
1270 if(!m_notebook->GetCurrentPage())
1271 {
1272 wxMessageBox(wxT("No files are currently open!"));
1273 return;
1274 }
1275
1276 if( !GetCurrentMediaCtrl()->Stop() )
1277 wxMessageBox(wxT("Couldn't stop movie!"));
1278}
1279
1280
1281// ----------------------------------------------------------------------------
1282// wxMediaPlayerFrame::OnChangeSong
1283//
1284// Routine that plays the currently selected file in the playlist.
1285// Called when the user actives the song from the playlist,
1286// and from other various places in the sample
1287// ----------------------------------------------------------------------------
1288void wxMediaPlayerFrame::OnChangeSong(wxListEvent& WXUNUSED(evt))
1289{
1290 wxMediaPlayerListCtrl* m_playlist =
1291 ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage())->m_playlist;
1292
1293 wxListItem listitem;
1294 m_playlist->GetSelectedItem(listitem);
1295 DoPlayFile((*((wxString*) listitem.GetData())));
1296}
1297
1298// ----------------------------------------------------------------------------
1299// wxMediaPlayerFrame::OnPrev
1300//
1301// Tedious wxListCtrl stuff. Goes to prevous song in list, or if at the
1302// beginning goes to the last in the list.
1303// ----------------------------------------------------------------------------
1304void wxMediaPlayerFrame::OnPrev(wxCommandEvent& WXUNUSED(event))
1305{
1306 wxMediaPlayerListCtrl* m_playlist =
1307 ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage())->m_playlist;
1308
1309 if (m_playlist->GetItemCount() == 0)
1310 return;
1311
1312 wxInt32 nLastSelectedItem = -1;
1313 while(true)
1314 {
1315 wxInt32 nSelectedItem = m_playlist->GetNextItem(nLastSelectedItem,
1316 wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
1317 if (nSelectedItem == -1)
1318 break;
1319 nLastSelectedItem = nSelectedItem;
1320 m_playlist->SetItemState(nSelectedItem, 0, wxLIST_STATE_SELECTED);
1321 }
1322
1323 if (nLastSelectedItem <= 0)
1324 nLastSelectedItem = m_playlist->GetItemCount() - 1;
1325 else
1326 nLastSelectedItem -= 1;
1327
1328 wxListItem listitem;
1329 listitem.SetId(nLastSelectedItem);
1330 m_playlist->GetItem(listitem);
1331 listitem.SetMask(listitem.GetMask() | wxLIST_MASK_STATE);
1332 listitem.SetState(listitem.GetState() | wxLIST_STATE_SELECTED);
1333 m_playlist->SetItem(listitem);
1334
1335 wxListEvent emptyEvent;
1336 OnChangeSong(emptyEvent);
1337}
1338
1339// ----------------------------------------------------------------------------
1340// wxMediaPlayerFrame::OnNext
1341//
1342// Tedious wxListCtrl stuff. Goes to next song in list, or if at the
1343// end goes to the first in the list.
1344// ----------------------------------------------------------------------------
1345void wxMediaPlayerFrame::OnNext(wxCommandEvent& WXUNUSED(event))
1346{
1347 wxMediaPlayerListCtrl* m_playlist =
1348 ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage())->m_playlist;
1349
1350 if (m_playlist->GetItemCount() == 0)
1351 return;
1352
1353 wxInt32 nLastSelectedItem = -1;
1354 while(true)
1355 {
1356 wxInt32 nSelectedItem = m_playlist->GetNextItem(nLastSelectedItem,
1357 wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
1358 if (nSelectedItem == -1)
1359 break;
1360 nLastSelectedItem = nSelectedItem;
1361 m_playlist->SetItemState(nSelectedItem, 0, wxLIST_STATE_SELECTED);
1362 }
1363
1364 if (nLastSelectedItem == -1)
1365 nLastSelectedItem = 0;
1366 else
1367 {
1368 if (nLastSelectedItem == m_playlist->GetItemCount() - 1)
1369 nLastSelectedItem = 0;
1370 else
1371 nLastSelectedItem += 1;
1372 }
1373
1374 wxListItem listitem;
1375 listitem.SetId(nLastSelectedItem);
1376 m_playlist->GetItem(listitem);
1377 listitem.SetMask(listitem.GetMask() | wxLIST_MASK_STATE);
1378 listitem.SetState(listitem.GetState() | wxLIST_STATE_SELECTED);
1379 m_playlist->SetItem(listitem);
1380
1381 wxListEvent emptyEvent;
1382 OnChangeSong(emptyEvent);
1383}
1384
1385
1386// ----------------------------------------------------------------------------
1387// wxMediaPlayerFrame::OnVolumeDown
1388//
1389// Lowers the volume of the media control by 10%
1390// ----------------------------------------------------------------------------
1391void wxMediaPlayerFrame::OnVolumeDown(wxCommandEvent& WXUNUSED(event))
1392{
1393 double dVolume = GetCurrentMediaCtrl()->GetVolume();
1394 GetCurrentMediaCtrl()->SetVolume(dVolume < 0.1 ? 0.0 : dVolume - .1);
1395}
1396
1397// ----------------------------------------------------------------------------
1398// wxMediaPlayerFrame::OnVolumeUp
1399//
1400// Increases the volume of the media control by 10%
1401// ----------------------------------------------------------------------------
1402void wxMediaPlayerFrame::OnVolumeUp(wxCommandEvent& WXUNUSED(event))
1403{
1404 double dVolume = GetCurrentMediaCtrl()->GetVolume();
1405 GetCurrentMediaCtrl()->SetVolume(dVolume > 0.9 ? 1.0 : dVolume + .1);
1406}
1407
1408// ----------------------------------------------------------------------------
1409// wxMediaPlayerFrame::OnCloseCurrentPage
1410//
1411// Called when the user wants to closes the current notebook page
1412// ----------------------------------------------------------------------------
1413
1414void wxMediaPlayerFrame::OnPageChange(wxNotebookEvent& WXUNUSED(event))
1415{
1416 ResetStatus();
1417}
1418
1419// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1420//
1421// wxMediaPlayerTimer
1422//
1423// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1424
1425// ----------------------------------------------------------------------------
1426// wxMediaPlayerTimer::Notify
1427//
1428// 1) Update our slider with the position were are in in the media
1429// 2) Update our status bar with the base text from wxMediaPlayerFrame::ResetStatus,
1430// append some non-static (changing) info to it, then set the
1431// status bar text to that result
1432// ----------------------------------------------------------------------------
1433void wxMediaPlayerTimer::Notify()
1434{
1435 if(m_frame->m_notebook->GetCurrentPage())
1436 {
1437 // get some control pointers from current notebook page
1438 wxMediaCtrl* mediactrl =
1439 ((wxMediaPlayerNotebookPage*)m_frame->m_notebook->GetCurrentPage())->m_mediactrl;
1440 wxSlider* slider =
1441 ((wxMediaPlayerNotebookPage*)m_frame->m_notebook->GetCurrentPage())->m_slider;
1442 wxGauge* gauge =
1443 ((wxMediaPlayerNotebookPage*)m_frame->m_notebook->GetCurrentPage())->m_gauge;
1444
1445 // if the slider is being dragged then update it with the song position
1446 if(((wxMediaPlayerNotebookPage*)m_frame->m_notebook->GetCurrentPage())->IsBeingDragged() == false)
1447 {
1448 long lPosition = (long)( mediactrl->Tell() / 1000 );
1449 slider->SetValue(lPosition);
1450 }
1451
1452 // update guage with value from slider
1453 gauge->SetValue(slider->GetValue());
1454#if wxUSE_STATUSBAR
1455 m_frame->SetStatusText(wxString::Format(
1456 wxT("%s Pos:%u State:%s Loops:%i D/T:[%i]/[%i] V:%i%%"),
1457 m_frame->m_basestatus.c_str(),
1458 slider->GetValue(),
1459 wxGetMediaStateText(mediactrl->GetState()),
1460 ((wxMediaPlayerNotebookPage*)m_frame->m_notebook->GetCurrentPage())->m_nLoops,
1461 (int)mediactrl->GetDownloadProgress(),
1462 (int)mediactrl->GetDownloadTotal(),
1463 (int)(mediactrl->GetVolume() * 100)));
1464#endif // wxUSE_STATUSBAR
1465 }
1466}
1467
1468
1469// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1470//
1471// wxMediaPlayerNotebookPage
1472//
1473// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1474
1475// ----------------------------------------------------------------------------
1476// wxMediaPlayerNotebookPage Constructor
1477//
1478// Creates a media control and slider and adds it to this panel,
1479// along with some sizers for positioning
1480// ----------------------------------------------------------------------------
1481
1482wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentFrame,
1483 wxNotebook* theBook,
1484 const wxString& szBackend)
1485 : wxPanel(theBook, wxID_ANY),
1486 m_nLoops(0),
1487 m_bLoop(false),
1488 m_bIsBeingDragged(false),
1489 m_parentFrame(parentFrame)
1490{
1491
1492 //
1493 // Layout
1494 //
1495 // [wxMediaCtrl]
1496 // [playlist]
1497 // [5 control buttons]
1498 // [slider]
1499 // [gauge]
1500 //
1501
1502 //
1503 // Create and attach the sizer
1504 //
1505 wxFlexGridSizer* sizer = new wxFlexGridSizer(2, 1, 0, 0);
1506 this->SetSizer(sizer);
1507 this->SetAutoLayout(true);
1508 sizer->AddGrowableRow(0);
1509 sizer->AddGrowableCol(0);
1510
1511 //
1512 // Create our media control
1513 //
1514 m_mediactrl = new wxMediaCtrl();
1515
1516 // Make sure creation was successful
1517 bool bOK = m_mediactrl->Create(this, wxID_MEDIACTRL, wxEmptyString,
1518 wxDefaultPosition, wxDefaultSize, 0,
1519//you could specify a macrod backend here like
1520//wxMEDIABACKEND_QUICKTIME);
1521 szBackend);
1522//you could change the cursor here like
1523// m_mediactrl->SetCursor(wxCURSOR_BLANK);
1524//note that this may not effect it if SetPlayerControls
1525//is set to something else than wxMEDIACTRLPLAYERCONTROLS_NONE
1526 wxASSERT_MSG(bOK, wxT("Could not create media control!"));
1527 wxUnusedVar(bOK);
1528
1529 sizer->Add(m_mediactrl, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 5);
1530
1531 //
1532 // Create the playlist/listctrl
1533 //
1534 m_playlist = new wxMediaPlayerListCtrl();
1535 m_playlist->Create(this, wxID_LISTCTRL, wxDefaultPosition,
1536 wxDefaultSize,
1537 wxLC_REPORT //wxLC_LIST
1538 | wxSUNKEN_BORDER);
1539
1540 // Set the background of our listctrl to white
1541 m_playlist->SetBackgroundColour(wxColour(255,255,255));
1542
1543 // The layout of the headers of the listctrl are like
1544 // | | File | Length
1545 //
1546 // Where Column one is a character representing the state the file is in:
1547 // * - not the current file
1548 // E - Error has occured
1549 // > - Currently Playing
1550 // [] - Stopped
1551 // || - Paused
1552 // (( - Volume Down 10%
1553 // )) - Volume Up 10%
1554 //
1555 // Column two is the name of the file
1556 //
1557 // Column three is the length in seconds of the file
1558 m_playlist->InsertColumn(0,_(""), wxLIST_FORMAT_CENTER, 20);
1559 m_playlist->InsertColumn(1,_("File"), wxLIST_FORMAT_LEFT, /*wxLIST_AUTOSIZE_USEHEADER*/305);
1560 m_playlist->InsertColumn(2,_("Length"), wxLIST_FORMAT_CENTER, 75);
1561
1562 m_playlist->SetDropTarget(new wxPlayListDropTarget(*m_playlist));
1563 sizer->Add(m_playlist, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 5);
1564
1565 //
1566 // Here we load the our configuration -
1567 // in our case we load all the files that were left in
1568 // the playlist the last time the user closed our application
1569 //
1570 // TODO: This is probably not the best practice since
1571 // the user will load multiple notebook pages with multiple
1572 // wxMediaCtrl elements.
1573 //
1574 // As an exercise to the reader try modifying it so that
1575 // it properly loads the playlist for each page without
1576 // conflicting (loading the same data) with the other ones.
1577 //
1578 wxConfigBase* conf = wxConfigBase::Get();
1579 wxString key, outstring;
1580 for(int i = 0; ; ++i)
1581 {
1582 key.clear();
1583 key << i;
1584 if(!conf->Read(key, &outstring))
1585 break;
1586 m_playlist->AddToPlayList(outstring);
1587 }
1588
1589 //
1590 // Create the control buttons
1591 // TODO/FIXME/HACK: This part about sizers is really a nice hack
1592 // and probably isn't proper
1593 //
1594 wxBoxSizer* horsizer1 = new wxBoxSizer(wxHORIZONTAL);
1595 wxBoxSizer* vertsizer = new wxBoxSizer(wxHORIZONTAL);
1596
1597 m_prevButton = new wxButton();
1598 m_playButton = new wxButton();
1599 m_stopButton = new wxButton();
1600 m_nextButton = new wxButton();
1601 m_vdButton = new wxButton();
1602 m_vuButton = new wxButton();
1603
1604 m_prevButton->Create(this, wxID_BUTTONPREV, _T("|<"));
1605 m_playButton->Create(this, wxID_BUTTONPLAY, _T(">"));
1606 m_stopButton->Create(this, wxID_BUTTONSTOP, _T("[]"));
1607 m_nextButton->Create(this, wxID_BUTTONNEXT, _T(">|"));
1608 m_vdButton->Create(this, wxID_BUTTONVD, _T("(("));
1609 m_vuButton->Create(this, wxID_BUTTONVU, _T("))"));
1610 vertsizer->Add(m_prevButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1611 vertsizer->Add(m_playButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1612 vertsizer->Add(m_stopButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1613 vertsizer->Add(m_nextButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1614 vertsizer->Add(m_vdButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1615 vertsizer->Add(m_vuButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1616 horsizer1->Add(vertsizer, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1617 sizer->Add(horsizer1, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
1618
1619
1620 //
1621 // Create our slider
1622 //
1623 m_slider = new wxSlider(this, wxID_SLIDER, 0, //init
1624 0, //start
1625 0, //end
1626 wxDefaultPosition, wxDefaultSize,
1627 wxSL_HORIZONTAL );
1628 sizer->Add(m_slider, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5);
1629
1630
1631 //
1632 // Create the gauge
1633 //
1634 m_gauge = new wxGauge();
1635 m_gauge->Create(this, wxID_GAUGE, 0, wxDefaultPosition, wxDefaultSize,
1636 wxGA_HORIZONTAL | wxGA_SMOOTH);
1637 sizer->Add(m_gauge, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5);
1638
1639 //
1640 // ListCtrl events
1641 //
1642 this->Connect( wxID_LISTCTRL, wxEVT_COMMAND_LIST_ITEM_ACTIVATED,
1643 wxListEventHandler(wxMediaPlayerFrame::OnChangeSong),
1644 (wxObject*)0, parentFrame);
1645
1646 //
1647 // Slider events
1648 //
1649 this->Connect(wxID_SLIDER, wxEVT_SCROLL_THUMBTRACK,
1650 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnBeginSeek));
1651 this->Connect(wxID_SLIDER, wxEVT_SCROLL_THUMBRELEASE,
1652 wxScrollEventHandler(wxMediaPlayerNotebookPage::OnEndSeek));
1653
1654 //
1655 // Media Control events
1656 //
1657 this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_FINISHED,
1658 wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaFinished));
1659 this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_LOADED,
1660 wxMediaEventHandler(wxMediaPlayerFrame::OnMediaLoaded),
1661 (wxObject*)0, parentFrame);
1662
1663 //
1664 // Button events
1665 //
1666 this->Connect( wxID_BUTTONPREV, wxEVT_COMMAND_BUTTON_CLICKED,
1667 wxCommandEventHandler(wxMediaPlayerFrame::OnPrev),
1668 (wxObject*)0, parentFrame);
1669 this->Connect( wxID_BUTTONPLAY, wxEVT_COMMAND_BUTTON_CLICKED,
1670 wxCommandEventHandler(wxMediaPlayerFrame::OnPlay),
1671 (wxObject*)0, parentFrame);
1672 this->Connect( wxID_BUTTONSTOP, wxEVT_COMMAND_BUTTON_CLICKED,
1673 wxCommandEventHandler(wxMediaPlayerFrame::OnStop),
1674 (wxObject*)0, parentFrame);
1675 this->Connect( wxID_BUTTONNEXT, wxEVT_COMMAND_BUTTON_CLICKED,
1676 wxCommandEventHandler(wxMediaPlayerFrame::OnNext),
1677 (wxObject*)0, parentFrame);
1678 this->Connect( wxID_BUTTONVD, wxEVT_COMMAND_BUTTON_CLICKED,
1679 wxCommandEventHandler(wxMediaPlayerFrame::OnVolumeDown),
1680 (wxObject*)0, parentFrame);
1681 this->Connect( wxID_BUTTONVU, wxEVT_COMMAND_BUTTON_CLICKED,
1682 wxCommandEventHandler(wxMediaPlayerFrame::OnVolumeUp),
1683 (wxObject*)0, parentFrame);
1684}
1685
1686// ----------------------------------------------------------------------------
1687// MyNotebook::OnBeginSeek
1688//
1689// Sets m_bIsBeingDragged to true to stop the timer from changing the position
1690// of our slider
1691// ----------------------------------------------------------------------------
1692void wxMediaPlayerNotebookPage::OnBeginSeek(wxScrollEvent& WXUNUSED(event))
1693{
1694 m_bIsBeingDragged = true;
1695}
1696
1697// ----------------------------------------------------------------------------
1698// MyNotebook::OnEndSeek
1699//
1700// Called from file->seek.
1701// Called when the user moves the slider -
1702// seeks to a position within the media
1703// then sets m_bIsBeingDragged to false to ok the timer to change the position
1704// ----------------------------------------------------------------------------
1705void wxMediaPlayerNotebookPage::OnEndSeek(wxScrollEvent& WXUNUSED(event))
1706{
1707 if( m_mediactrl->Seek(
1708 m_slider->GetValue() * 1000
1709 ) == wxInvalidOffset )
1710 wxMessageBox(wxT("Couldn't seek in movie!"));
1711
1712 m_bIsBeingDragged = false;
1713}
1714
1715// ----------------------------------------------------------------------------
1716// wxMediaPlayerNotebookPage::IsBeingDragged
1717//
1718// Returns true if the user is dragging the slider
1719// ----------------------------------------------------------------------------
1720bool wxMediaPlayerNotebookPage::IsBeingDragged()
1721{
1722 return m_bIsBeingDragged;
1723}
1724
1725// ----------------------------------------------------------------------------
1726// OnMediaFinished
1727//
1728// Called when the media stops playing.
1729// Here we loop it if the user wants to (has been selected from file menu)
1730// ----------------------------------------------------------------------------
1731void wxMediaPlayerNotebookPage::OnMediaFinished(wxMediaEvent& WXUNUSED(event))
1732{
1733 if(m_bLoop)
1734 {
1735 if ( !m_mediactrl->Play() )
1736 {
1737 wxMessageBox(wxT("Couldn't loop movie!"));
1738 m_playlist->SetItem(m_parentFrame->m_nLastFileId, 0, _T("E"));
1739 }
1740 else
1741 ++m_nLoops;
1742 }
1743 else
1744 {
1745 m_playlist->SetItem(m_parentFrame->m_nLastFileId, 0, _T("[]"));
1746 }
1747}
1748
1749//
1750// End of MediaPlayer sample
1751//