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