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