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