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