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