]> git.saurik.com Git - wxWidgets.git/blob - samples/mediaplayer/mediaplayer.cpp
/usr/sbin is a better default location for sendmail than /usr/lib nowadays
[wxWidgets.git] / samples / mediaplayer / mediaplayer.cpp
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
99 enum
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
135 class wxMediaPlayerApp : public wxApp
136 {
137 public:
138 #ifdef __WXMAC__
139 virtual void MacOpenFile(const wxString & fileName );
140 #endif
141
142 virtual bool OnInit();
143
144 protected:
145 class wxMediaPlayerFrame* m_frame;
146 };
147
148 // ----------------------------------------------------------------------------
149 // wxMediaPlayerFrame
150 // ----------------------------------------------------------------------------
151
152 class wxMediaPlayerFrame : public wxFrame
153 {
154 public:
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
200 private:
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
234 class 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
246 public:
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
272 class wxMediaPlayerTimer : public wxTimer
273 {
274 public:
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 // ----------------------------------------------------------------------------
287 class wxMediaPlayerListCtrl : public wxListCtrl
288 {
289 public:
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 // ----------------------------------------------------------------------------
340 class wxPlayListDropTarget : public wxFileDropTarget
341 {
342 public:
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 // ----------------------------------------------------------------------------
375 const 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 // ----------------------------------------------------------------------------
406 IMPLEMENT_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 // ----------------------------------------------------------------------------
416 bool 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
457 void 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
481 wxMediaPlayerFrame::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 // ----------------------------------------------------------------------------
712 wxMediaPlayerFrame::~wxMediaPlayerFrame()
713 {
714 delete m_timer;
715
716 }
717
718 // ----------------------------------------------------------------------------
719 // wxMediaPlayerFrame::OnClose
720 // ----------------------------------------------------------------------------
721 void 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 // ----------------------------------------------------------------------------
761 void 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 // ----------------------------------------------------------------------------
787 void 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 // ----------------------------------------------------------------------------
806 wxMediaCtrl* 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 // ----------------------------------------------------------------------------
816 wxSlider* 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 // ----------------------------------------------------------------------------
826 wxGauge* 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 // ----------------------------------------------------------------------------
837 void 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 // ----------------------------------------------------------------------------
849 void 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 // ----------------------------------------------------------------------------
864 void 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 // ----------------------------------------------------------------------------
882 void 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 // ----------------------------------------------------------------------------
901 void 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 // ----------------------------------------------------------------------------
912 void 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 // ----------------------------------------------------------------------------
923 void 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 // ----------------------------------------------------------------------------
939 void 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 // ----------------------------------------------------------------------------
985 void 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 // ----------------------------------------------------------------------------
1059 void 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 // ----------------------------------------------------------------------------
1093 void 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 // ----------------------------------------------------------------------------
1119 void 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 // ----------------------------------------------------------------------------
1130 void 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 // ----------------------------------------------------------------------------
1141 void 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 // ----------------------------------------------------------------------------
1162 void 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 // ----------------------------------------------------------------------------
1185 void 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 // ----------------------------------------------------------------------------
1224 void 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 // ----------------------------------------------------------------------------
1261 void 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 // ----------------------------------------------------------------------------
1288 void 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 // ----------------------------------------------------------------------------
1304 void 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 // ----------------------------------------------------------------------------
1345 void 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 // ----------------------------------------------------------------------------
1391 void 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 // ----------------------------------------------------------------------------
1402 void 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
1414 void 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 // ----------------------------------------------------------------------------
1433 void 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
1482 wxMediaPlayerNotebookPage::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 // ----------------------------------------------------------------------------
1692 void 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 // ----------------------------------------------------------------------------
1705 void 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 // ----------------------------------------------------------------------------
1720 bool 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 // ----------------------------------------------------------------------------
1731 void 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 //