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